[clang] e63b81d - [analyzer][ctu] Only import const and trivial VarDecls

Gabor Marton via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 1 04:54:17 PDT 2022


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 at intns@extInt ctu-other.cpp.ast
 7:c:@extS ctu-other.cpp.ast
+9:c:@extNTS ctu-other.cpp.ast
 8:c:@S at A@a ctu-other.cpp.ast
 8:c:@extSC ctu-other.cpp.ast
 10:c:@S at 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());
   }


        


More information about the cfe-commits mailing list