r358968 - [analyzer][CrossTU] Extend CTU to VarDecls with initializer

Rafael Stahl via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 23 04:04:42 PDT 2019


Author: r.stahl
Date: Tue Apr 23 04:04:41 2019
New Revision: 358968

URL: http://llvm.org/viewvc/llvm-project?rev=358968&view=rev
Log:
[analyzer][CrossTU] Extend CTU to VarDecls with initializer

Summary:
The existing CTU mechanism imports `FunctionDecl`s where the definition is available in another TU. This patch extends that to VarDecls, to bind more constants.

- Add VarDecl importing functionality to CrossTranslationUnitContext
- Import Decls while traversing them in AnalysisConsumer
- Add VarDecls to CTU external mappings generator
- Name changes from "external function map" to "external definition map"

Reviewers: NoQ, dcoughlin, xazax.hun, george.karpenkov, martong

Reviewed By: xazax.hun

Subscribers: Charusso, baloghadamsoftware, mikhail.ramalho, Szelethus, donat.nagy, dkrupp, george.karpenkov, mgorny, whisperity, szepet, rnkovacs, a.sidorin, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D46421

Added:
    cfe/trunk/test/Analysis/redecl.c
Modified:
    cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h
    cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
    cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
    cfe/trunk/test/Analysis/Inputs/ctu-other.cpp
    cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
    cfe/trunk/test/Analysis/ctu-main.cpp
    cfe/trunk/test/Analysis/func-mapping-test.cpp
    cfe/trunk/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp

Modified: cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h (original)
+++ cfe/trunk/include/clang/CrossTU/CrossTranslationUnit.h Tue Apr 23 04:04:41 2019
@@ -28,6 +28,7 @@ class ASTImporter;
 class ASTUnit;
 class DeclContext;
 class FunctionDecl;
+class VarDecl;
 class NamedDecl;
 class TranslationUnitDecl;
 
@@ -87,6 +88,9 @@ parseCrossTUIndex(StringRef IndexPath, S
 
 std::string createCrossTUIndexString(const llvm::StringMap<std::string> &Index);
 
+// Returns true if the variable or any field of a record variable is const.
+bool containsConst(const VarDecl *VD, const ASTContext &ACtx);
+
 /// This class is used for tools that requires cross translation
 ///        unit capability.
 ///
@@ -102,16 +106,16 @@ public:
   CrossTranslationUnitContext(CompilerInstance &CI);
   ~CrossTranslationUnitContext();
 
-  /// This function loads a function definition from an external AST
-  ///        file and merge it into the original AST.
+  /// This function loads a function or variable definition from an
+  ///        external AST file and merges it into the original AST.
   ///
-  /// This method should only be used on functions that have no definitions in
+  /// This method should only be used on functions that have no definitions or
+  /// variables that have no initializer in
   /// the current translation unit. A function definition with the same
   /// declaration will be looked up in the index file which should be in the
   /// \p CrossTUDir directory, called \p IndexName. In case the declaration is
   /// found in the index the corresponding AST file will be loaded and the
-  /// definition of the function will be merged into the original AST using
-  /// the AST Importer.
+  /// definition will be merged into the original AST using the AST Importer.
   ///
   /// \return The declaration with the definition will be returned.
   /// If no suitable definition is found in the index file or multiple
@@ -121,17 +125,19 @@ public:
   llvm::Expected<const FunctionDecl *>
   getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir,
                        StringRef IndexName, bool DisplayCTUProgress = false);
+  llvm::Expected<const VarDecl *>
+  getCrossTUDefinition(const VarDecl *VD, StringRef CrossTUDir,
+                       StringRef IndexName, bool DisplayCTUProgress = false);
 
-  /// This function loads a function definition from an external AST
-  ///        file.
+  /// This function loads a definition from an external AST file.
   ///
-  /// A function definition with the same declaration will be looked up in the
+  /// A definition with the same declaration will be looked up in the
   /// index file which should be in the \p CrossTUDir directory, called
   /// \p IndexName. In case the declaration is found in the index the
   /// corresponding AST file will be loaded.
   ///
   /// \return Returns a pointer to the ASTUnit that contains the definition of
-  /// the looked up function or an Error.
+  /// the looked up name or an Error.
   /// The returned pointer is never a nullptr.
   ///
   /// Note that the AST files should also be in the \p CrossTUDir.
@@ -146,8 +152,9 @@ public:
   ///
   /// \return Returns the resulting definition or an error.
   llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD);
+  llvm::Expected<const VarDecl *> importDefinition(const VarDecl *VD);
 
-  /// Get a name to identify a function.
+  /// Get a name to identify a named decl.
   static std::string getLookupName(const NamedDecl *ND);
 
   /// Emit diagnostics for the user for potential configuration errors.
@@ -156,12 +163,20 @@ public:
 private:
   void lazyInitLookupTable(TranslationUnitDecl *ToTU);
   ASTImporter &getOrCreateASTImporter(ASTContext &From);
-  const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC,
-                                                StringRef LookupFnName);
+  template <typename T>
+  llvm::Expected<const T *> getCrossTUDefinitionImpl(const T *D,
+                                                     StringRef CrossTUDir,
+                                                     StringRef IndexName,
+                                                     bool DisplayCTUProgress);
+  template <typename T>
+  const T *findDefInDeclContext(const DeclContext *DC,
+                                StringRef LookupName);
+  template <typename T>
+  llvm::Expected<const T *> importDefinitionImpl(const T *D);
 
   llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap;
-  llvm::StringMap<clang::ASTUnit *> FunctionASTUnitMap;
-  llvm::StringMap<std::string> FunctionFileMap;
+  llvm::StringMap<clang::ASTUnit *> NameASTUnitMap;
+  llvm::StringMap<std::string> NameFileMap;
   llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>>
       ASTUnitImporterMap;
   CompilerInstance &CI;

Modified: cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp (original)
+++ cfe/trunk/lib/CrossTU/CrossTranslationUnit.cpp Tue Apr 23 04:04:41 2019
@@ -158,6 +158,27 @@ createCrossTUIndexString(const llvm::Str
   return Result.str();
 }
 
+bool containsConst(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;
+}
+
+static bool hasBodyOrInit(const FunctionDecl *D, const FunctionDecl *&DefD) {
+  return D->hasBody(DefD);
+}
+static bool hasBodyOrInit(const VarDecl *D, const VarDecl *&DefD) {
+  return D->getAnyInitializer(DefD);
+}
+template <typename T> static bool hasBodyOrInit(const T *D) {
+  const T *Unused;
+  return hasBodyOrInit(D, Unused);
+}
+
 CrossTranslationUnitContext::CrossTranslationUnitContext(CompilerInstance &CI)
     : CI(CI), Context(CI.getASTContext()) {}
 
@@ -165,48 +186,50 @@ CrossTranslationUnitContext::~CrossTrans
 
 std::string CrossTranslationUnitContext::getLookupName(const NamedDecl *ND) {
   SmallString<128> DeclUSR;
-  bool Ret = index::generateUSRForDecl(ND, DeclUSR); (void)Ret;
+  bool Ret = index::generateUSRForDecl(ND, DeclUSR);
+  (void)Ret;
   assert(!Ret && "Unable to generate USR");
   return DeclUSR.str();
 }
 
-/// Recursively visits the function decls of a DeclContext, and looks up a
-/// function based on USRs.
-const FunctionDecl *
-CrossTranslationUnitContext::findFunctionInDeclContext(const DeclContext *DC,
-                                                       StringRef LookupFnName) {
+/// Recursively visits the decls of a DeclContext, and returns one with the
+/// given USR.
+template <typename T>
+const T *
+CrossTranslationUnitContext::findDefInDeclContext(const DeclContext *DC,
+                                                  StringRef LookupName) {
   assert(DC && "Declaration Context must not be null");
   for (const Decl *D : DC->decls()) {
     const auto *SubDC = dyn_cast<DeclContext>(D);
     if (SubDC)
-      if (const auto *FD = findFunctionInDeclContext(SubDC, LookupFnName))
-        return FD;
+      if (const auto *ND = findDefInDeclContext<T>(SubDC, LookupName))
+        return ND;
 
-    const auto *ND = dyn_cast<FunctionDecl>(D);
-    const FunctionDecl *ResultDecl;
-    if (!ND || !ND->hasBody(ResultDecl))
+    const auto *ND = dyn_cast<T>(D);
+    const T *ResultDecl;
+    if (!ND || !hasBodyOrInit(ND, ResultDecl))
       continue;
-    if (getLookupName(ResultDecl) != LookupFnName)
+    if (getLookupName(ResultDecl) != LookupName)
       continue;
     return ResultDecl;
   }
   return nullptr;
 }
 
-llvm::Expected<const FunctionDecl *>
-CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
-                                                  StringRef CrossTUDir,
-                                                  StringRef IndexName,
-                                                  bool DisplayCTUProgress) {
-  assert(FD && "FD is missing, bad call to this function!");
-  assert(!FD->hasBody() && "FD has a definition in current translation unit!");
+template <typename T>
+llvm::Expected<const T *> CrossTranslationUnitContext::getCrossTUDefinitionImpl(
+    const T *D, StringRef CrossTUDir, StringRef IndexName,
+    bool DisplayCTUProgress) {
+  assert(D && "D is missing, bad call to this function!");
+  assert(!hasBodyOrInit(D) &&
+         "D has a body or init in current translation unit!");
   ++NumGetCTUCalled;
-  const std::string LookupFnName = getLookupName(FD);
-  if (LookupFnName.empty())
+  const std::string LookupName = getLookupName(D);
+  if (LookupName.empty())
     return llvm::make_error<IndexError>(
         index_error_code::failed_to_generate_usr);
   llvm::Expected<ASTUnit *> ASTUnitOrError =
-      loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress);
+      loadExternalAST(LookupName, CrossTUDir, IndexName, DisplayCTUProgress);
   if (!ASTUnitOrError)
     return ASTUnitOrError.takeError();
   ASTUnit *Unit = *ASTUnitOrError;
@@ -262,12 +285,29 @@ CrossTranslationUnitContext::getCrossTUD
   }
 
   TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl();
-  if (const FunctionDecl *ResultDecl =
-          findFunctionInDeclContext(TU, LookupFnName))
+  if (const T *ResultDecl = findDefInDeclContext<T>(TU, LookupName))
     return importDefinition(ResultDecl);
   return llvm::make_error<IndexError>(index_error_code::failed_import);
 }
 
+llvm::Expected<const FunctionDecl *>
+CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD,
+                                                  StringRef CrossTUDir,
+                                                  StringRef IndexName,
+                                                  bool DisplayCTUProgress) {
+  return getCrossTUDefinitionImpl(FD, CrossTUDir, IndexName,
+                                  DisplayCTUProgress);
+}
+
+llvm::Expected<const VarDecl *>
+CrossTranslationUnitContext::getCrossTUDefinition(const VarDecl *VD,
+                                                  StringRef CrossTUDir,
+                                                  StringRef IndexName,
+                                                  bool DisplayCTUProgress) {
+  return getCrossTUDefinitionImpl(VD, CrossTUDir, IndexName,
+                                  DisplayCTUProgress);
+}
+
 void CrossTranslationUnitContext::emitCrossTUDiagnostics(const IndexError &IE) {
   switch (IE.getCode()) {
   case index_error_code::missing_index_file:
@@ -294,14 +334,14 @@ void CrossTranslationUnitContext::emitCr
 llvm::Expected<ASTUnit *> CrossTranslationUnitContext::loadExternalAST(
     StringRef LookupName, StringRef CrossTUDir, StringRef IndexName,
     bool DisplayCTUProgress) {
-  // FIXME: The current implementation only supports loading functions with
+  // FIXME: The current implementation only supports loading decls with
   //        a lookup name from a single translation unit. If multiple
-  //        translation units contains functions with the same lookup name an
+  //        translation units contains decls with the same lookup name an
   //        error will be returned.
   ASTUnit *Unit = nullptr;
-  auto FnUnitCacheEntry = FunctionASTUnitMap.find(LookupName);
-  if (FnUnitCacheEntry == FunctionASTUnitMap.end()) {
-    if (FunctionFileMap.empty()) {
+  auto NameUnitCacheEntry = NameASTUnitMap.find(LookupName);
+  if (NameUnitCacheEntry == NameASTUnitMap.end()) {
+    if (NameFileMap.empty()) {
       SmallString<256> IndexFile = CrossTUDir;
       if (llvm::sys::path::is_absolute(IndexName))
         IndexFile = IndexName;
@@ -310,13 +350,13 @@ llvm::Expected<ASTUnit *> CrossTranslati
       llvm::Expected<llvm::StringMap<std::string>> IndexOrErr =
           parseCrossTUIndex(IndexFile, CrossTUDir);
       if (IndexOrErr)
-        FunctionFileMap = *IndexOrErr;
+        NameFileMap = *IndexOrErr;
       else
         return IndexOrErr.takeError();
     }
 
-    auto It = FunctionFileMap.find(LookupName);
-    if (It == FunctionFileMap.end()) {
+    auto It = NameFileMap.find(LookupName);
+    if (It == NameFileMap.end()) {
       ++NumNotInOtherTU;
       return llvm::make_error<IndexError>(index_error_code::missing_definition);
     }
@@ -342,9 +382,9 @@ llvm::Expected<ASTUnit *> CrossTranslati
     } else {
       Unit = ASTCacheEntry->second.get();
     }
-    FunctionASTUnitMap[LookupName] = Unit;
+    NameASTUnitMap[LookupName] = Unit;
   } else {
-    Unit = FnUnitCacheEntry->second;
+    Unit = NameUnitCacheEntry->second;
   }
   if (!Unit)
     return llvm::make_error<IndexError>(
@@ -352,12 +392,13 @@ llvm::Expected<ASTUnit *> CrossTranslati
   return Unit;
 }
 
-llvm::Expected<const FunctionDecl *>
-CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
-  assert(FD->hasBody() && "Functions to be imported should have body.");
+template <typename T>
+llvm::Expected<const T *>
+CrossTranslationUnitContext::importDefinitionImpl(const T *D) {
+  assert(hasBodyOrInit(D) && "Decls to be imported should have body or init.");
 
-  ASTImporter &Importer = getOrCreateASTImporter(FD->getASTContext());
-  auto ToDeclOrError = Importer.Import_New(FD);
+  ASTImporter &Importer = getOrCreateASTImporter(D->getASTContext());
+  auto ToDeclOrError = Importer.Import_New(D);
   if (!ToDeclOrError) {
     handleAllErrors(ToDeclOrError.takeError(),
                     [&](const ImportError &IE) {
@@ -375,13 +416,23 @@ CrossTranslationUnitContext::importDefin
                     });
     return llvm::make_error<IndexError>(index_error_code::failed_import);
   }
-  auto *ToDecl = cast<FunctionDecl>(*ToDeclOrError);  
-  assert(ToDecl->hasBody() && "Imported function should have body.");
+  auto *ToDecl = cast<T>(*ToDeclOrError);
+  assert(hasBodyOrInit(ToDecl) && "Imported Decl should have body or init.");
   ++NumGetCTUSuccess;
 
   return ToDecl;
 }
 
+llvm::Expected<const FunctionDecl *>
+CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) {
+  return importDefinitionImpl(FD);
+}
+
+llvm::Expected<const VarDecl *>
+CrossTranslationUnitContext::importDefinition(const VarDecl *VD) {
+  return importDefinitionImpl(VD);
+}
+
 void CrossTranslationUnitContext::lazyInitLookupTable(
     TranslationUnitDecl *ToTU) {
   if (!LookupTable)

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Tue Apr 23 04:04:41 2019
@@ -1655,7 +1655,7 @@ SVal RegionStoreManager::getBindingForEl
     const VarDecl *VD = VR->getDecl();
     // Either the array or the array element has to be const.
     if (VD->getType().isConstQualified() || R->getElementType().isConstQualified()) {
-      if (const Expr *Init = VD->getInit()) {
+      if (const Expr *Init = VD->getAnyInitializer()) {
         if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
           // The array index has to be known.
           if (auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
@@ -1745,7 +1745,7 @@ SVal RegionStoreManager::getBindingForFi
     unsigned Index = FD->getFieldIndex();
     // Either the record variable or the field has to be const qualified.
     if (RecordVarTy.isConstQualified() || Ty.isConstQualified())
-      if (const Expr *Init = VD->getInit())
+      if (const Expr *Init = VD->getAnyInitializer())
         if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
           if (Index < InitList->getNumInits()) {
             if (const Expr *FieldInit = InitList->getInit(Index))
@@ -1943,7 +1943,7 @@ SVal RegionStoreManager::getBindingForVa
 
   // Is 'VD' declared constant?  If so, retrieve the constant value.
   if (VD->getType().isConstQualified()) {
-    if (const Expr *Init = VD->getInit()) {
+    if (const Expr *Init = VD->getAnyInitializer()) {
       if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
         return *V;
 

Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Tue Apr 23 04:04:41 2019
@@ -342,6 +342,35 @@ public:
     return true;
   }
 
+  bool VisitVarDecl(VarDecl *VD) {
+    if (!Opts->IsNaiveCTUEnabled)
+      return true;
+
+    if (VD->hasExternalStorage() || VD->isStaticDataMember()) {
+      if (!cross_tu::containsConst(VD, *Ctx))
+        return true;
+    } else {
+      // Cannot be initialized in another TU.
+      return true;
+    }
+
+    if (VD->getAnyInitializer())
+      return true;
+
+    llvm::Expected<const VarDecl *> CTUDeclOrError =
+      CTU.getCrossTUDefinition(VD, Opts->CTUDir, Opts->CTUIndexName, 
+                               Opts->DisplayCTUProgress);
+
+    if (!CTUDeclOrError) {
+      handleAllErrors(CTUDeclOrError.takeError(),
+                      [&](const cross_tu::IndexError &IE) {
+                        CTU.emitCrossTUDiagnostics(IE);
+                      });
+    }
+
+    return true;
+  }
+
   bool VisitFunctionDecl(FunctionDecl *FD) {
     IdentifierInfo *II = FD->getIdentifier();
     if (II && II->getName().startswith("__inline"))

Modified: cfe/trunk/test/Analysis/Inputs/ctu-other.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/ctu-other.cpp?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/ctu-other.cpp (original)
+++ cfe/trunk/test/Analysis/Inputs/ctu-other.cpp Tue Apr 23 04:04:41 2019
@@ -80,3 +80,41 @@ int other_macro_diag(int x) {
   MACRODIAG();
   return x;
 }
+
+extern const int extInt = 2;
+namespace intns {
+extern const int extInt = 3;
+}
+struct S {
+  int a;
+};
+extern const S extS = {.a = 4};
+struct A {
+  static const int a;
+};
+const int A::a = 3;
+struct SC {
+  const int a;
+};
+SC extSC = {.a = 8};
+struct ST {
+  static struct SC sc;
+};
+struct SC ST::sc = {.a = 2};
+struct SCNest {
+  struct SCN {
+    const int a;
+  } scn;
+};
+SCNest extSCN = {.scn = {.a = 9}};
+SCNest::SCN extSubSCN = {.a = 1};
+struct SCC {
+  SCC(int c) : a(c) {}
+  const int a;
+};
+SCC extSCC{7};
+union U {
+  const int a;
+  const unsigned int b;
+};
+U extU = {.a = 4};

Modified: cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt (original)
+++ cfe/trunk/test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt Tue Apr 23 04:04:41 2019
@@ -13,3 +13,13 @@ c:@N at chns@S at chcls@F at chf4#I# ctu-chain.cp
 c:@N at chns@F at chf2#I# ctu-chain.cpp.ast
 c:@F at fun_using_anon_struct#I# ctu-other.cpp.ast
 c:@F at other_macro_diag#I# ctu-other.cpp.ast
+c:@extInt ctu-other.cpp.ast
+c:@N at intns@extInt ctu-other.cpp.ast
+c:@extS ctu-other.cpp.ast
+c:@S at A@a ctu-other.cpp.ast
+c:@extSC ctu-other.cpp.ast
+c:@S at ST@sc ctu-other.cpp.ast
+c:@extSCN ctu-other.cpp.ast
+c:@extSubSCN ctu-other.cpp.ast
+c:@extSCC ctu-other.cpp.ast
+c:@extU ctu-other.cpp.ast

Modified: cfe/trunk/test/Analysis/ctu-main.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/ctu-main.cpp?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/ctu-main.cpp (original)
+++ cfe/trunk/test/Analysis/ctu-main.cpp Tue Apr 23 04:04:41 2019
@@ -60,6 +60,44 @@ int chf1(int x);
 int fun_using_anon_struct(int);
 int other_macro_diag(int);
 
+extern const int extInt;
+namespace intns {
+extern const int extInt;
+}
+struct S {
+  int a;
+};
+extern const S extS;
+extern const int extHere;
+const int extHere = 6;
+struct A {
+  static const int a;
+};
+struct SC {
+  const int a;
+};
+extern SC extSC;
+struct ST {
+  static struct SC sc;
+};
+struct SCNest {
+  struct SCN {
+    const int a;
+  } scn;
+};
+extern SCNest extSCN;
+extern SCNest::SCN extSubSCN;
+struct SCC {
+  SCC(int c);
+  const int a;
+};
+extern SCC extSCC;
+union U {
+  const int a;
+  const unsigned int b;
+};
+extern U extU;
+
 int main() {
   clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}}
   clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}}
@@ -80,4 +118,16 @@ int main() {
   clang_analyzer_eval(other_macro_diag(1) == 1); // expected-warning{{TRUE}}
   // expected-warning at Inputs/ctu-other.cpp:80{{REACHABLE}}
   MACRODIAG(); // expected-warning{{REACHABLE}}
+
+  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(extHere == 6); // expected-warning{{TRUE}}
+  clang_analyzer_eval(A::a == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(extSC.a == 8); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ST::sc.a == 2); // expected-warning{{TRUE}}
+  // clang_analyzer_eval(extSCN.scn.a == 9); // TODO
+  clang_analyzer_eval(extSubSCN.a == 1); // expected-warning{{TRUE}}
+  // clang_analyzer_eval(extSCC.a == 7); // TODO
+  clang_analyzer_eval(extU.a == 4); // expected-warning{{TRUE}}
 }

Modified: cfe/trunk/test/Analysis/func-mapping-test.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/func-mapping-test.cpp?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/func-mapping-test.cpp (original)
+++ cfe/trunk/test/Analysis/func-mapping-test.cpp Tue Apr 23 04:04:41 2019
@@ -1,7 +1,43 @@
-// RUN: %clang_extdef_map %s -- | FileCheck %s
+// RUN: %clang_extdef_map %s -- | FileCheck --implicit-check-not "c:@y" --implicit-check-not "c:@z" %s
 
 int f(int) {
   return 0;
 }
+// CHECK-DAG: c:@F at f#I#
 
-// CHECK: c:@F at f#I#
+extern const int x = 5;
+// CHECK-DAG: c:@x
+
+// Non-const variables should not be collected.
+int y = 5;
+
+// In C++, const implies internal linkage, so not collected.
+const int z = 5;
+
+struct S {
+  int a;
+};
+extern S const s = {.a = 2};
+// CHECK-DAG: c:@s
+
+struct SF {
+  const int a;
+};
+SF sf = {.a = 2};
+// CHECK-DAG: c:@sf
+
+struct SStatic {
+  static const int a = 4;
+};
+const int SStatic::a;
+// CHECK-DAG: c:@S at SStatic@a
+
+extern int const arr[5] = { 0, 1 };
+// CHECK-DAG: c:@arr
+
+union U {
+  const int a;
+  const unsigned int b;
+};
+U u = {.a = 6};
+// CHECK-DAG: c:@u

Added: cfe/trunk/test/Analysis/redecl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/redecl.c?rev=358968&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/redecl.c (added)
+++ cfe/trunk/test/Analysis/redecl.c Tue Apr 23 04:04:41 2019
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
+// XFAIL: *
+
+void clang_analyzer_eval(int);
+
+extern const int extInt;
+
+int main()
+{
+    clang_analyzer_eval(extInt == 2); // expected-warning{{TRUE}}
+}
+
+extern const int extInt = 2;

Modified: cfe/trunk/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp?rev=358968&r1=358967&r2=358968&view=diff
==============================================================================
--- cfe/trunk/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp (original)
+++ cfe/trunk/tools/clang-extdef-mapping/ClangExtDefMapGen.cpp Tue Apr 23 04:04:41 2019
@@ -34,20 +34,22 @@ static cl::OptionCategory ClangExtDefMap
 class MapExtDefNamesConsumer : public ASTConsumer {
 public:
   MapExtDefNamesConsumer(ASTContext &Context)
-      : SM(Context.getSourceManager()) {}
+      : Ctx(Context), SM(Context.getSourceManager()) {}
 
   ~MapExtDefNamesConsumer() {
     // Flush results to standard output.
     llvm::outs() << createCrossTUIndexString(Index);
   }
 
-  void HandleTranslationUnit(ASTContext &Ctx) override {
-    handleDecl(Ctx.getTranslationUnitDecl());
+  void HandleTranslationUnit(ASTContext &Context) override {
+    handleDecl(Context.getTranslationUnitDecl());
   }
 
 private:
   void handleDecl(const Decl *D);
+  void addIfInMain(const DeclaratorDecl *DD, SourceLocation defStart);
 
+  ASTContext &Ctx;
   SourceManager &SM;
   llvm::StringMap<std::string> Index;
   std::string CurrentFileName;
@@ -58,30 +60,13 @@ void MapExtDefNamesConsumer::handleDecl(
     return;
 
   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
-    if (FD->isThisDeclarationADefinition()) {
-      if (const Stmt *Body = FD->getBody()) {
-        if (CurrentFileName.empty()) {
-          CurrentFileName =
-              SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName();
-          if (CurrentFileName.empty())
-            CurrentFileName = "invalid_file";
-        }
-
-        switch (FD->getLinkageInternal()) {
-        case ExternalLinkage:
-        case VisibleNoLinkage:
-        case UniqueExternalLinkage:
-          if (SM.isInMainFile(Body->getBeginLoc())) {
-            std::string LookupName =
-                CrossTranslationUnitContext::getLookupName(FD);
-            Index[LookupName] = CurrentFileName;
-          }
-          break;
-        default:
-          break;
-        }
-      }
-    }
+    if (FD->isThisDeclarationADefinition())
+      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 (const Expr *Init = VD->getInit())
+        addIfInMain(VD, Init->getBeginLoc());
   }
 
   if (const auto *DC = dyn_cast<DeclContext>(D))
@@ -89,6 +74,27 @@ void MapExtDefNamesConsumer::handleDecl(
       handleDecl(D);
 }
 
+void MapExtDefNamesConsumer::addIfInMain(const DeclaratorDecl *DD,
+                                         SourceLocation defStart) {
+  std::string LookupName = CrossTranslationUnitContext::getLookupName(DD);
+  if (CurrentFileName.empty()) {
+    CurrentFileName =
+        SM.getFileEntryForID(SM.getMainFileID())->tryGetRealPathName();
+    if (CurrentFileName.empty())
+      CurrentFileName = "invalid_file";
+  }
+
+  switch (DD->getLinkageInternal()) {
+  case ExternalLinkage:
+  case VisibleNoLinkage:
+  case UniqueExternalLinkage:
+    if (SM.isInMainFile(defStart))
+      Index[LookupName] = CurrentFileName;
+  default:
+    break;
+  }
+}
+
 class MapExtDefNamesAction : public ASTFrontendAction {
 protected:
   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,




More information about the cfe-commits mailing list