Index: include/clang/CrossTU/CrossTranslationUnit.h =================================================================== --- include/clang/CrossTU/CrossTranslationUnit.h +++ include/clang/CrossTU/CrossTranslationUnit.h @@ -28,6 +28,7 @@ class ASTUnit; class DeclContext; class FunctionDecl; +class VarDecl; class NamedDecl; class TranslationUnitDecl; @@ -109,6 +110,9 @@ llvm::Expected getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, StringRef IndexName); + llvm::Expected + getCrossTUDefinition(const VarDecl *VD, StringRef CrossTUDir, + StringRef IndexName); /// \brief This function loads a function definition from an external AST /// file. @@ -132,8 +136,9 @@ /// /// \return Returns the resulting definition or an error. llvm::Expected importDefinition(const FunctionDecl *FD); + llvm::Expected importDefinition(const VarDecl *VD); - /// \brief Get a name to identify a function. + /// \brief Get a name to identify a named decl. static std::string getLookupName(const NamedDecl *ND); /// \brief Emit diagnostics for the user for potential configuration errors. @@ -141,8 +146,15 @@ private: ASTImporter &getOrCreateASTImporter(ASTContext &From); - const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC, - StringRef LookupFnName); + template + llvm::Expected getCrossTUDefinitionImpl(const T *D, + StringRef CrossTUDir, + StringRef IndexName); + template + const T *findDefInDeclContext(const DeclContext *DC, + StringRef LookupFnName); + template + llvm::Expected importDefinitionImpl(const T *D); llvm::StringMap> FileASTUnitMap; llvm::StringMap FunctionASTUnitMap; Index: lib/CrossTU/CrossTranslationUnit.cpp =================================================================== --- lib/CrossTU/CrossTranslationUnit.cpp +++ lib/CrossTU/CrossTranslationUnit.cpp @@ -111,6 +111,17 @@ return Result.str(); } +bool HasDefinition(const FunctionDecl *D, const FunctionDecl *&DefD) { + return D->hasBody(DefD); +} +bool HasDefinition(const VarDecl *D, const VarDecl *&DefD) { + return D->getAnyInitializer(DefD) != nullptr; +} +template bool HasDefinition(const T *D) { + const T *Unused; + return HasDefinition(D, Unused); +} + CrossTranslationUnitContext::CrossTranslationUnitContext(CompilerInstance &CI) : CI(CI), Context(CI.getASTContext()) {} @@ -118,26 +129,28 @@ 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) { +template +const T * +CrossTranslationUnitContext::findDefInDeclContext(const DeclContext *DC, + StringRef LookupFnName) { assert(DC && "Declaration Context must not be null"); for (const Decl *D : DC->decls()) { const auto *SubDC = dyn_cast(D); if (SubDC) - if (const auto *FD = findFunctionInDeclContext(SubDC, LookupFnName)) - return FD; + if (const auto *ND = findDefInDeclContext(SubDC, LookupFnName)) + return ND; - const auto *ND = dyn_cast(D); - const FunctionDecl *ResultDecl; - if (!ND || !ND->hasBody(ResultDecl)) + const auto *ND = dyn_cast(D); + const T *ResultDecl; + if (!ND || !HasDefinition(ND, ResultDecl)) continue; if (getLookupName(ResultDecl) != LookupFnName) continue; @@ -146,17 +159,17 @@ return nullptr; } -llvm::Expected -CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD, - StringRef CrossTUDir, - StringRef IndexName) { - assert(!FD->hasBody() && "FD has a definition in current translation unit!"); - const std::string LookupFnName = getLookupName(FD); - if (LookupFnName.empty()) +template +llvm::Expected CrossTranslationUnitContext::getCrossTUDefinitionImpl( + const T *D, StringRef CrossTUDir, StringRef IndexName) { + assert(!HasDefinition(D) && + "D has a definition in current translation unit!"); + const std::string LookupName = getLookupName(D); + if (LookupName.empty()) return llvm::make_error( index_error_code::failed_to_generate_usr); llvm::Expected ASTUnitOrError = - loadExternalAST(LookupFnName, CrossTUDir, IndexName); + loadExternalAST(LookupName, CrossTUDir, IndexName); if (!ASTUnitOrError) return ASTUnitOrError.takeError(); ASTUnit *Unit = *ASTUnitOrError; @@ -167,12 +180,25 @@ &Unit->getASTContext().getSourceManager().getFileManager()); TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); - if (const FunctionDecl *ResultDecl = - findFunctionInDeclContext(TU, LookupFnName)) + if (const T *ResultDecl = findDefInDeclContext(TU, LookupName)) return importDefinition(ResultDecl); return llvm::make_error(index_error_code::failed_import); } +llvm::Expected +CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD, + StringRef CrossTUDir, + StringRef IndexName) { + return getCrossTUDefinitionImpl(FD, CrossTUDir, IndexName); +} + +llvm::Expected +CrossTranslationUnitContext::getCrossTUDefinition(const VarDecl *VD, + StringRef CrossTUDir, + StringRef IndexName) { + return getCrossTUDefinitionImpl(VD, CrossTUDir, IndexName); +} + void CrossTranslationUnitContext::emitCrossTUDiagnostics(const IndexError &IE) { switch (IE.getCode()) { case index_error_code::missing_index_file: @@ -243,14 +269,25 @@ return Unit; } +template +llvm::Expected +CrossTranslationUnitContext::importDefinitionImpl(const T *D) { + ASTImporter &Importer = getOrCreateASTImporter(D->getASTContext()); + auto *ToDecl = cast(Importer.Import(const_cast(D))); + assert(HasDefinition(ToDecl)); + assert(HasDefinition(D) && + "Decls already imported should have a definition."); + return ToDecl; +} + llvm::Expected CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) { - ASTImporter &Importer = getOrCreateASTImporter(FD->getASTContext()); - auto *ToDecl = - cast(Importer.Import(const_cast(FD))); - assert(ToDecl->hasBody()); - assert(FD->hasBody() && "Functions already imported should have body."); - return ToDecl; + return importDefinitionImpl(FD); +} + +llvm::Expected +CrossTranslationUnitContext::importDefinition(const VarDecl *VD) { + return importDefinitionImpl(VD); } ASTImporter & Index: lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp =================================================================== --- lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -346,6 +346,27 @@ return true; } + bool VisitVarDecl(VarDecl *VD) { + if (!Opts->naiveCTUEnabled()) + return true; + + if (!VD->hasExternalStorage() || + VD->getAnyInitializer() != nullptr) + return true; + + llvm::Expected CTUDeclOrError = + CTU.getCrossTUDefinition(VD, Opts->getCTUDir(), Opts->getCTUIndexName()); + + 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")) Index: tools/clang-func-mapping/ClangFnMapGen.cpp =================================================================== --- tools/clang-func-mapping/ClangFnMapGen.cpp +++ tools/clang-func-mapping/ClangFnMapGen.cpp @@ -54,6 +54,7 @@ private: void handleDecl(const Decl *D); + void addIfInMain(const DeclaratorDecl *DD, SourceLocation defStart); ASTContext &Ctx; llvm::StringMap Index; @@ -65,28 +66,13 @@ return; if (const auto *FD = dyn_cast(D)) { - if (FD->isThisDeclarationADefinition()) { - if (const Stmt *Body = FD->getBody()) { - std::string LookupName = CrossTranslationUnitContext::getLookupName(FD); - const SourceManager &SM = Ctx.getSourceManager(); - 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->getLocStart())) - Index[LookupName] = CurrentFileName; - default: - break; - } - } - } + if (FD->isThisDeclarationADefinition()) + if (const Stmt *Body = FD->getBody()) + addIfInMain(FD, Body->getLocStart()); + } else if (const auto *VD = dyn_cast(D)) { + if (VD->hasInit()) + if (const Expr *Init = VD->getInit()) + addIfInMain(VD, Init->getLocStart()); } if (const auto *DC = dyn_cast(D)) @@ -94,6 +80,28 @@ handleDecl(D); } +void MapFunctionNamesConsumer::addIfInMain(const DeclaratorDecl *DD, + SourceLocation defStart) { + std::string LookupName = CrossTranslationUnitContext::getLookupName(DD); + const SourceManager &SM = Ctx.getSourceManager(); + 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 MapFunctionNamesAction : public ASTFrontendAction { protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI,