diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index dfcaa2962a39..864a5b6782de 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -235,5 +235,5 @@ def err_fnmap_absolute : Error< "error parsing CrossTU index file: '%0' line: %1 Path needs to be absolute " "in reparse mode">; def err_ctu_incompat_triple : Error< - "imported AST from '%0' had been generated for a different target">; + "imported AST from '%0' had been generated for a different target, current: %1, imported: %2">; } diff --git a/lib/Tooling/CrossTranslationUnit.cpp b/lib/Tooling/CrossTranslationUnit.cpp index 3c6c549c8c03..143d3a7e0226 100644 --- a/lib/Tooling/CrossTranslationUnit.cpp +++ b/lib/Tooling/CrossTranslationUnit.cpp @@ -43,6 +43,36 @@ STATISTIC(NumUnsupportedNodeFound, "The # of imports when the ASTImporter " "encountered an unsupported AST Node"); } +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 tooling { @@ -183,13 +213,19 @@ const FunctionDecl *CrossTranslationUnit::getCrossTUDefinition( << SourceFileName << "\n"; } + const auto& TripleTo = Context.getTargetInfo().getTriple(); + const auto& TripleFrom = Unit->getASTContext().getTargetInfo().getTriple(); // The imported AST had been generated for a different target - if (Context.getTargetInfo().getTriple() != - Unit->getASTContext().getTargetInfo().getTriple()) { + // TODO use equality operator. Note, for some unknown reason when we do + // in-memory/on-the-fly CTU (i.e when the compilation db is given) 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) - << ASTFileName; + << ASTFileName << TripleTo.str() << TripleFrom.str(); return nullptr; } diff --git a/test/Analysis/xtu-different-triples.c b/test/Analysis/xtu-different-triples.c index a09760b9517d..1c873a057f74 100644 --- a/test/Analysis/xtu-different-triples.c +++ b/test/Analysis/xtu-different-triples.c @@ -4,7 +4,7 @@ // RUN: %clang_cc1 -triple powerpc64-montavista-linux-gnu -fsyntax-only -std=c89 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config xtu-dir=%T/xtudir3 -verify %s // We expect an error in this file, but without a location. -// expected-error-re@./xtu-different-triples.c:*{{imported AST from {{.*}} had been generated for a different target}} +// expected-error-re@./xtu-different-triples.c:*{{imported AST from {{.*}} had been generated for a different target, current: powerpc64-montavista-linux-gnu, imported: x86_64-pc-linux-gnu}} int f(int); diff --git a/test/Analysis/xtu-unknown-parts-in-triples.c b/test/Analysis/xtu-unknown-parts-in-triples.c new file mode 100644 index 000000000000..30335dc77750 --- /dev/null +++ b/test/Analysis/xtu-unknown-parts-in-triples.c @@ -0,0 +1,15 @@ +// We do not expect any error when one part of the triple is unknown, but other +// known parts are equal. + +// RUN: mkdir -p %T/xtudir3 +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-pch -o %T/xtudir3/xtu-other.c.ast %S/Inputs/xtu-other.c +// RUN: cp %S/Inputs/externalFnMap2_usr.txt %T/xtudir3/externalFnMap.txt +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -std=c89 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-config xtu-dir=%T/xtudir3 -verify %s + +// expected-no-diagnostics + +int f(int); + +int main() { + return f(5); +}