martong created this revision.
martong added reviewers: xazax.hun, a_sidorin.
Herald added subscribers: cfe-commits, gamesh411, Szelethus, dkrupp, rnkovacs.

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).


Repository:
  rC Clang

https://reviews.llvm.org/D55134

Files:
  include/clang/Basic/DiagnosticCrossTUKinds.td
  include/clang/CrossTU/CrossTranslationUnit.h
  lib/CrossTU/CrossTranslationUnit.cpp

Index: lib/CrossTU/CrossTranslationUnit.cpp
===================================================================
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -28,6 +28,36 @@
 #include <fstream>
 #include <sstream>
 
+namespace llvm {
+// Same as Triple's equality operator, but we check a field only if that is
+// known in both instances.
+bool hasEqualKnownFields(const Triple &Lhs, const Triple &Rhs) {
+  return ((Lhs.getArch() != Triple::UnknownArch &&
+           Rhs.getArch() != Triple::UnknownArch)
+              ? Lhs.getArch() == Rhs.getArch()
+              : true) &&
+         ((Lhs.getSubArch() != Triple::NoSubArch &&
+           Rhs.getSubArch() != Triple::NoSubArch)
+              ? Lhs.getSubArch() == Rhs.getSubArch()
+              : true) &&
+         ((Lhs.getVendor() != Triple::UnknownVendor &&
+           Rhs.getVendor() != Triple::UnknownVendor)
+              ? Lhs.getVendor() == Rhs.getVendor()
+              : true) &&
+         ((Lhs.getOS() != Triple::UnknownOS && Rhs.getOS() != Triple::UnknownOS)
+              ? Lhs.getOS() == Rhs.getOS()
+              : true) &&
+         ((Lhs.getEnvironment() != Triple::UnknownEnvironment &&
+           Rhs.getEnvironment() != Triple::UnknownEnvironment)
+              ? Lhs.getEnvironment() == Rhs.getEnvironment()
+              : true) &&
+         ((Lhs.getObjectFormat() != Triple::UnknownObjectFormat &&
+           Rhs.getObjectFormat() != Triple::UnknownObjectFormat)
+              ? Lhs.getObjectFormat() == Rhs.getObjectFormat()
+              : true);
+}
+}
+
 namespace clang {
 namespace cross_tu {
 
@@ -55,6 +85,10 @@
       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.");
   }
@@ -166,6 +200,30 @@
   assert(&Unit->getFileManager() ==
          &Unit->getASTContext().getSourceManager().getFileManager());
 
+  const auto& TripleTo = Context.getTargetInfo().getTriple();
+  const auto& 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
+    Context.getDiagnostics().Report(diag::err_ctu_incompat_triple)
+        << Unit->getMainFileName() << TripleTo.str() << TripleFrom.str();
+    // TODO Add statistics here
+    return llvm::make_error<IndexError>(index_error_code::triple_mismatch);
+  }
+
+  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) {
+    // TODO Add statistics here.
+    return llvm::make_error<IndexError>(index_error_code::lang_mismatch);
+  }
+
   TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
   if (const FunctionDecl *ResultDecl =
           findFunctionInDeclContext(TU, LookupFnName))
Index: include/clang/CrossTU/CrossTranslationUnit.h
===================================================================
--- include/clang/CrossTU/CrossTranslationUnit.h
+++ include/clang/CrossTU/CrossTranslationUnit.h
@@ -41,7 +41,9 @@
   missing_definition,
   failed_import,
   failed_to_get_external_ast,
-  failed_to_generate_usr
+  failed_to_generate_usr,
+  triple_mismatch,
+  lang_mismatch
 };
 
 class IndexError : public llvm::ErrorInfo<IndexError> {
Index: include/clang/Basic/DiagnosticCrossTUKinds.td
===================================================================
--- include/clang/Basic/DiagnosticCrossTUKinds.td
+++ include/clang/Basic/DiagnosticCrossTUKinds.td
@@ -15,4 +15,7 @@
 
 def err_multiple_def_index : Error<
   "multiple definitions are found for the same key in index ">;
+
+def err_ctu_incompat_triple : Error<
+  "imported AST from '%0' had been generated for a different target, current: %1, imported: %2">;
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to