Author: Gabor Marton Date: 2022-04-01T13:49:39+02:00 New Revision: e63b81d10e023b4d8e9f61ca29a678c74ce2c1cb
URL: https://github.com/llvm/llvm-project/commit/e63b81d10e023b4d8e9f61ca29a678c74ce2c1cb DIFF: https://github.com/llvm/llvm-project/commit/e63b81d10e023b4d8e9f61ca29a678c74ce2c1cb.diff LOG: [analyzer][ctu] Only import const and trivial VarDecls Do import the definition of objects from a foreign translation unit if that's type is const and trivial. Differential Revision: https://reviews.llvm.org/D122805 Added: Modified: clang/include/clang/CrossTU/CrossTranslationUnit.h clang/lib/CrossTU/CrossTranslationUnit.cpp clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp clang/test/Analysis/Inputs/ctu-other.cpp clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.ast-dump.txt clang/test/Analysis/ctu-main.cpp clang/test/Analysis/func-mapping-test.cpp clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp Removed: ################################################################################ diff --git a/clang/include/clang/CrossTU/CrossTranslationUnit.h b/clang/include/clang/CrossTU/CrossTranslationUnit.h index a09826f93afc0..a41c32d4068b2 100644 --- a/clang/include/clang/CrossTU/CrossTranslationUnit.h +++ b/clang/include/clang/CrossTU/CrossTranslationUnit.h @@ -109,8 +109,10 @@ llvm::Expected<InvocationListTy> parseInvocationList( StringRef FileContent, llvm::sys::path::Style PathStyle = llvm::sys::path::Style::posix); -// Returns true if the variable or any field of a record variable is const. -bool containsConst(const VarDecl *VD, const ASTContext &ACtx); +/// Returns true if it makes sense to import a foreign variable definition. +/// For instance, we don't want to import variables that have non-trivial types +/// because the constructor might have side-effects. +bool shouldImport(const VarDecl *VD, const ASTContext &ACtx); /// This class is used for tools that requires cross translation /// unit capability. diff --git a/clang/lib/CrossTU/CrossTranslationUnit.cpp b/clang/lib/CrossTU/CrossTranslationUnit.cpp index cbe07acb76fb1..ee6cc60f31e1d 100644 --- a/clang/lib/CrossTU/CrossTranslationUnit.cpp +++ b/clang/lib/CrossTU/CrossTranslationUnit.cpp @@ -220,14 +220,9 @@ createCrossTUIndexString(const llvm::StringMap<std::string> &Index) { return Result.str(); } -bool containsConst(const VarDecl *VD, const ASTContext &ACtx) { +bool shouldImport(const VarDecl *VD, const ASTContext &ACtx) { CanQualType CT = ACtx.getCanonicalType(VD->getType()); - if (!CT.isConstQualified()) { - const RecordType *RTy = CT->getAs<RecordType>(); - if (!RTy || !RTy->hasConstFields()) - return false; - } - return true; + return CT.isConstQualified() && VD->getType().isTrivialType(ACtx); } static bool hasBodyOrInit(const FunctionDecl *D, const FunctionDecl *&DefD) { diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 9e96e00011f4f..fcc73b3767d4b 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -289,7 +289,7 @@ class AnalysisConsumer : public AnalysisASTConsumer, return true; if (VD->hasExternalStorage() || VD->isStaticDataMember()) { - if (!cross_tu::containsConst(VD, *Ctx)) + if (!cross_tu::shouldImport(VD, *Ctx)) return true; } else { // Cannot be initialized in another TU. diff --git a/clang/test/Analysis/Inputs/ctu-other.cpp b/clang/test/Analysis/Inputs/ctu-other.cpp index ff37947d5b7e9..a7bf1cef65b92 100644 --- a/clang/test/Analysis/Inputs/ctu-other.cpp +++ b/clang/test/Analysis/Inputs/ctu-other.cpp @@ -102,6 +102,12 @@ struct S { int a; }; extern const S extS = {.a = 4}; +extern S extNonConstS = {.a = 4}; +struct NonTrivialS { + int a; + ~NonTrivialS(); +}; +extern const NonTrivialS extNTS = {.a = 4}; struct A { static const int a; }; @@ -109,18 +115,18 @@ const int A::a = 3; struct SC { const int a; }; -SC extSC = {.a = 8}; +extern const SC extSC = {.a = 8}; struct ST { - static struct SC sc; + static const struct SC sc; }; -struct SC ST::sc = {.a = 2}; +const struct SC ST::sc = {.a = 2}; struct SCNest { struct SCN { const int a; } scn; }; SCNest extSCN = {.scn = {.a = 9}}; -SCNest::SCN extSubSCN = {.a = 1}; +extern SCNest::SCN const extSubSCN = {.a = 1}; struct SCC { SCC(int c) : a(c) {} const int a; @@ -130,7 +136,7 @@ union U { const int a; const unsigned int b; }; -U extU = {.a = 4}; +extern const U extU = {.a = 4}; class TestAnonUnionUSR { public: diff --git a/clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.ast-dump.txt b/clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.ast-dump.txt index 476b8f1867042..439232333b609 100644 --- a/clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.ast-dump.txt +++ b/clang/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.ast-dump.txt @@ -18,6 +18,7 @@ 9:c:@extInt ctu-other.cpp.ast 17:c:@N@intns@extInt ctu-other.cpp.ast 7:c:@extS ctu-other.cpp.ast +9:c:@extNTS ctu-other.cpp.ast 8:c:@S@A@a ctu-other.cpp.ast 8:c:@extSC ctu-other.cpp.ast 10:c:@S@ST@sc ctu-other.cpp.ast diff --git a/clang/test/Analysis/ctu-main.cpp b/clang/test/Analysis/ctu-main.cpp index d76b3984401e0..5bf212a123e9f 100644 --- a/clang/test/Analysis/ctu-main.cpp +++ b/clang/test/Analysis/ctu-main.cpp @@ -74,6 +74,13 @@ struct S { int a; }; extern const S extS; +extern S extNonConstS; +struct NonTrivialS { + int a; + // User declaring a dtor makes it non-trivial. + ~NonTrivialS(); +}; +extern const NonTrivialS extNTS; extern const int extHere; const int extHere = 6; struct A { @@ -82,9 +89,9 @@ struct A { struct SC { const int a; }; -extern SC extSC; +extern const SC extSC; struct ST { - static struct SC sc; + static const struct SC sc; }; struct SCNest { struct SCN { @@ -92,7 +99,7 @@ struct SCNest { } scn; }; extern SCNest extSCN; -extern SCNest::SCN extSubSCN; +extern const SCNest::SCN extSubSCN; struct SCC { SCC(int c); const int a; @@ -102,7 +109,7 @@ union U { const int a; const unsigned int b; }; -extern U extU; +extern const U extU; void test_virtual_functions(mycls* obj) { // The dynamic type is known. @@ -153,6 +160,9 @@ int main() { clang_analyzer_eval(extInt == 2); // expected-warning{{TRUE}} clang_analyzer_eval(intns::extInt == 3); // expected-warning{{TRUE}} clang_analyzer_eval(extS.a == 4); // expected-warning{{TRUE}} + clang_analyzer_eval(extNonConstS.a == 4); // expected-warning{{TRUE}} expected-warning{{FALSE}} + // Do not import non-trivial classes' initializers. + clang_analyzer_eval(extNTS.a == 4); // expected-warning{{TRUE}} expected-warning{{FALSE}} clang_analyzer_eval(extHere == 6); // expected-warning{{TRUE}} clang_analyzer_eval(A::a == 3); // expected-warning{{TRUE}} clang_analyzer_eval(extSC.a == 8); // expected-warning{{TRUE}} diff --git a/clang/test/Analysis/func-mapping-test.cpp b/clang/test/Analysis/func-mapping-test.cpp index 44bbf85097201..a56c0075db1aa 100644 --- a/clang/test/Analysis/func-mapping-test.cpp +++ b/clang/test/Analysis/func-mapping-test.cpp @@ -23,7 +23,7 @@ extern S const s = {.a = 2}; struct SF { const int a; }; -SF sf = {.a = 2}; +extern const SF sf = {.a = 2}; // CHECK-DAG: 5:c:@sf struct SStatic { @@ -39,7 +39,7 @@ union U { const int a; const unsigned int b; }; -U u = {.a = 6}; +extern const U u = {.a = 6}; // CHECK-DAG: 4:c:@u // No USR can be generated for this. diff --git a/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp b/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp index 8aba1301ef9aa..bc8d2581c1b97 100644 --- a/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp +++ b/clang/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp @@ -64,7 +64,7 @@ void MapExtDefNamesConsumer::handleDecl(const Decl *D) { if (const Stmt *Body = FD->getBody()) addIfInMain(FD, Body->getBeginLoc()); } else if (const auto *VD = dyn_cast<VarDecl>(D)) { - if (cross_tu::containsConst(VD, Ctx) && VD->hasInit()) + if (cross_tu::shouldImport(VD, Ctx) && VD->hasInit()) if (const Expr *Init = VD->getInit()) addIfInMain(VD, Init->getBeginLoc()); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits