summaryrefslogtreecommitdiffstats
path: root/lib/CrossTU/CrossTranslationUnit.cpp
diff options
context:
space:
mode:
authorGabor Marton <martongabesz@gmail.com>2018-12-07 16:32:43 +0000
committerGabor Marton <martongabesz@gmail.com>2018-12-07 16:32:43 +0000
commit38929e836cba3dc9d3e5edc3d53b57343e8f503e (patch)
treeb6737854a73f4337a4247f79d7ec9a1eb542a11c /lib/CrossTU/CrossTranslationUnit.cpp
parent5ac259b653c4bcf25cb9ffc791de11d53e4f0a7a (diff)
[CTU] Add triple/lang mismatch handling
Summary: We introduce a strict policy for C++ CTU. It can work across TUs only if the C++ dialects are the same. We neither allow C vs C++ CTU. We do this because the same constructs might be represented with different properties in the corresponding AST nodes or even the nodes might be completely different (a struct will be RecordDecl in C, but it will be a CXXRectordDecl in C++, thus it may cause certain assertions during cast operations). Reviewers: xazax.hun, a_sidorin Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Differential Revision: https://reviews.llvm.org/D55134 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@348610 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CrossTU/CrossTranslationUnit.cpp')
-rw-r--r--lib/CrossTU/CrossTranslationUnit.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/CrossTU/CrossTranslationUnit.cpp b/lib/CrossTU/CrossTranslationUnit.cpp
index ec8ac6498f..f49db3a8bf 100644
--- a/lib/CrossTU/CrossTranslationUnit.cpp
+++ b/lib/CrossTU/CrossTranslationUnit.cpp
@@ -33,6 +33,7 @@ namespace clang {
namespace cross_tu {
namespace {
+
#define DEBUG_TYPE "CrossTranslationUnit"
STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called");
STATISTIC(
@@ -41,6 +42,37 @@ STATISTIC(
STATISTIC(NumGetCTUSuccess,
"The # of getCTUDefinition successfully returned the "
"requested function's body");
+STATISTIC(NumTripleMismatch, "The # of triple mismatches");
+STATISTIC(NumLangMismatch, "The # of language mismatches");
+
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const llvm::Triple &Lhs, const llvm::Triple &Rhs) {
+ using llvm::Triple;
+ if (Lhs.getArch() != Triple::UnknownArch &&
+ Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch())
+ return false;
+ if (Lhs.getSubArch() != Triple::NoSubArch &&
+ Rhs.getSubArch() != Triple::NoSubArch &&
+ Lhs.getSubArch() != Rhs.getSubArch())
+ return false;
+ if (Lhs.getVendor() != Triple::UnknownVendor &&
+ Rhs.getVendor() != Triple::UnknownVendor &&
+ Lhs.getVendor() != Rhs.getVendor())
+ return false;
+ if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() &&
+ Lhs.getOS() != Rhs.getOS())
+ return false;
+ if (Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+ Rhs.getEnvironment() != Triple::UnknownEnvironment &&
+ Lhs.getEnvironment() != Rhs.getEnvironment())
+ return false;
+ if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+ Rhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+ Lhs.getObjectFormat() != Rhs.getObjectFormat())
+ return false;
+ return true;
+}
// FIXME: This class is will be removed after the transition to llvm::Error.
class IndexErrorCategory : public std::error_category {
@@ -65,6 +97,10 @@ public:
return "Failed to load external AST source.";
case index_error_code::failed_to_generate_usr:
return "Failed to generate USR.";
+ case index_error_code::triple_mismatch:
+ return "Triple mismatch";
+ case index_error_code::lang_mismatch:
+ return "Language mismatch";
}
llvm_unreachable("Unrecognized index_error_code.");
}
@@ -179,6 +215,31 @@ CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
assert(&Unit->getFileManager() ==
&Unit->getASTContext().getSourceManager().getFileManager());
+ const llvm::Triple &TripleTo = Context.getTargetInfo().getTriple();
+ const llvm::Triple &TripleFrom =
+ Unit->getASTContext().getTargetInfo().getTriple();
+ // The imported AST had been generated for a different target.
+ // Some parts of the triple in the loaded ASTContext can be unknown while the
+ // very same parts in the target ASTContext are known. Thus we check for the
+ // known parts only.
+ if (!hasEqualKnownFields(TripleTo, TripleFrom)) {
+ // TODO: Pass the SourceLocation of the CallExpression for more precise
+ // diagnostics.
+ ++NumTripleMismatch;
+ return llvm::make_error<IndexError>(index_error_code::triple_mismatch,
+ Unit->getMainFileName(), TripleTo.str(),
+ TripleFrom.str());
+ }
+
+ const auto &LangTo = Context.getLangOpts();
+ const auto &LangFrom = Unit->getASTContext().getLangOpts();
+ // FIXME: Currenty we do not support CTU across C++ and C and across
+ // different dialects of C++.
+ if (LangTo.CPlusPlus != LangFrom.CPlusPlus) {
+ ++NumLangMismatch;
+ return llvm::make_error<IndexError>(index_error_code::lang_mismatch);
+ }
+
TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
if (const FunctionDecl *ResultDecl =
findFunctionInDeclContext(TU, LookupFnName))
@@ -200,6 +261,10 @@ void CrossTranslationUnitContext::emitCrossTUDiagnostics(const IndexError &IE) {
Context.getDiagnostics().Report(diag::err_multiple_def_index)
<< IE.getLineNum();
break;
+ case index_error_code::triple_mismatch:
+ Context.getDiagnostics().Report(diag::warn_ctu_incompat_triple)
+ << IE.getFileName() << IE.getTripleToName() << IE.getTripleFromName();
+ break;
default:
break;
}