r.stahl updated this revision to Diff 181263.
r.stahl marked 12 inline comments as done.
r.stahl added a comment.
Strip name changes (see D56441 <https://reviews.llvm.org/D56441>); addressed
review comments
In my old version I seemed to get away with the tests, but they failed after
rebasing. It seems like earlier there was only a single VarDecl for the
imported ones with InitExpr. Now after importing there is one without init and
a redecl with the init. This is why I changed getInit() in RegionStore to
getAnyInititializer. I think these three should be enough, but I'm not sure
where else in the analyzer this would have to be changed.
I also noticed that nested struct inits don't work, but this is unrelated to
this patch, so I commented out the test for now and will send a separate patch.
Repository:
rC Clang
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D46421/new/
https://reviews.llvm.org/D46421
Files:
include/clang/CrossTU/CrossTranslationUnit.h
lib/CrossTU/CrossTranslationUnit.cpp
lib/StaticAnalyzer/Core/RegionStore.cpp
lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
test/Analysis/Inputs/ctu-other.cpp
test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
test/Analysis/ctu-main.cpp
test/Analysis/func-mapping-test.cpp
tools/clang-extdef-mapping/ClangExtDefMapGen.cpp
Index: tools/clang-extdef-mapping/ClangExtDefMapGen.cpp
===================================================================
--- tools/clang-extdef-mapping/ClangExtDefMapGen.cpp
+++ tools/clang-extdef-mapping/ClangExtDefMapGen.cpp
@@ -48,6 +48,7 @@
private:
void handleDecl(const Decl *D);
+ void addIfInMain(const DeclaratorDecl *DD, SourceLocation defStart);
SourceManager &SM;
llvm::StringMap<std::string> Index;
@@ -59,30 +60,19 @@
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)) {
+ QualType VTy = VD->getType();
+ bool containsConst = VTy.isConstQualified();
+ if (!containsConst && !VTy.isNull())
+ if (const RecordType *RTy = VTy->getAsStructureType())
+ containsConst = RTy->hasConstFields();
+
+ if (containsConst && VD->hasInit())
+ if (const Expr *Init = VD->getInit())
+ addIfInMain(VD, Init->getBeginLoc());
}
if (const auto *DC = dyn_cast<DeclContext>(D))
@@ -90,6 +80,27 @@
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,
Index: test/Analysis/func-mapping-test.cpp
===================================================================
--- test/Analysis/func-mapping-test.cpp
+++ test/Analysis/func-mapping-test.cpp
@@ -1,7 +1,36 @@
-// 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@f#I#
-// CHECK: c:@F@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@SStatic@a
+
+extern int const arr[5] = { 0, 1 };
+// CHECK-DAG: c:@arr
\ No newline at end of file
Index: test/Analysis/ctu-main.cpp
===================================================================
--- test/Analysis/ctu-main.cpp
+++ test/Analysis/ctu-main.cpp
@@ -60,6 +60,31 @@
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 SCNest {
+ struct SCN {
+ const int a;
+ } scn;
+};
+extern SCNest extSCN;
+extern SCNest::SCN extSubSCN;
+
int main() {
clang_analyzer_eval(f(3) == 2); // expected-warning{{TRUE}}
clang_analyzer_eval(f(4) == 3); // expected-warning{{TRUE}}
@@ -80,4 +105,13 @@
clang_analyzer_eval(other_macro_diag(1) == 1); // expected-warning{{TRUE}}
// expected-warning@Inputs/ctu-other.cpp:75{{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(extSCN.scn.a == 9); // TODO
+ clang_analyzer_eval(extSubSCN.a == 1); // expected-warning{{TRUE}}
}
Index: test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
===================================================================
--- test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
+++ test/Analysis/Inputs/ctu-other.cpp.externalDefMap.txt
@@ -13,3 +13,10 @@
c:@N@chns@F@chf2#I# ctu-chain.cpp.ast
c:@F@fun_using_anon_struct#I# ctu-other.cpp.ast
c:@F@other_macro_diag#I# ctu-other.cpp.ast
+c:@extInt ctu-other.cpp.ast
+c:@N@intns@extInt ctu-other.cpp.ast
+c:@extS ctu-other.cpp.ast
+c:@S@A@a ctu-other.cpp.ast
+c:@extSC ctu-other.cpp.ast
+c:@extSCN ctu-other.cpp.ast
+c:@extSubSCN ctu-other.cpp.ast
Index: test/Analysis/Inputs/ctu-other.cpp
===================================================================
--- test/Analysis/Inputs/ctu-other.cpp
+++ test/Analysis/Inputs/ctu-other.cpp
@@ -75,3 +75,27 @@
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 SCNest {
+ struct SCN {
+ const int a;
+ } scn;
+};
+SCNest extSCN = {.scn = {.a = 9}};
+SCNest::SCN extSubSCN = {.a = 1};
Index: lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
===================================================================
--- lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -343,6 +343,46 @@
return true;
}
+ bool VisitVarDecl(VarDecl *VD) {
+ if (!Opts->IsNaiveCTUEnabled)
+ return true;
+
+ if (VD->hasExternalStorage()) {
+ // Only import if const or has const fields.
+ CanQualType CT = Ctx->getCanonicalType(VD->getType());
+ if (!CT.isConstQualified()) {
+ const RecordType *RTy = CT->getAs<RecordType>();
+ if (!RTy)
+ return true;
+ if (!RTy->hasConstFields())
+ return true;
+ }
+ } else if (VD->isStaticDataMember()) {
+ // Only import if const.
+ if (!Ctx->getCanonicalType(VD->getType()).isConstQualified())
+ return true;
+ } else {
+ // Cannot be initialized in another TU.
+ return true;
+ }
+
+ if (VD->getAnyInitializer() != nullptr)
+ 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"))
Index: lib/StaticAnalyzer/Core/RegionStore.cpp
===================================================================
--- lib/StaticAnalyzer/Core/RegionStore.cpp
+++ lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1660,7 +1660,7 @@
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>()) {
@@ -1750,7 +1750,7 @@
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))
@@ -1945,7 +1945,7 @@
// 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;
Index: lib/CrossTU/CrossTranslationUnit.cpp
===================================================================
--- lib/CrossTU/CrossTranslationUnit.cpp
+++ lib/CrossTU/CrossTranslationUnit.cpp
@@ -156,6 +156,17 @@
return Result.str();
}
+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) != nullptr;
+}
+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()) {}
@@ -163,48 +174,50 @@
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;
@@ -237,12 +250,29 @@
}
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:
@@ -269,14 +299,14 @@
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;
@@ -285,13 +315,13 @@
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);
}
@@ -317,9 +347,9 @@
} 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>(
@@ -327,21 +357,32 @@
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 *ToDecl =
- cast_or_null<FunctionDecl>(Importer.Import(const_cast<FunctionDecl *>(FD)));
+ ASTImporter &Importer = getOrCreateASTImporter(D->getASTContext());
+ auto *ToDecl = dyn_cast_or_null<T>(Importer.Import(const_cast<T *>(D)));
if (!ToDecl)
return llvm::make_error<IndexError>(index_error_code::failed_import);
- assert(ToDecl->hasBody());
- assert(FD->hasBody() && "Functions already imported should have body.");
+ assert(hasBodyOrInit(ToDecl));
+ assert(hasBodyOrInit(D) &&
+ "Decls already imported 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)
Index: include/clang/CrossTU/CrossTranslationUnit.h
===================================================================
--- include/clang/CrossTU/CrossTranslationUnit.h
+++ include/clang/CrossTU/CrossTranslationUnit.h
@@ -29,6 +29,7 @@
class ASTUnit;
class DeclContext;
class FunctionDecl;
+class VarDecl;
class NamedDecl;
class TranslationUnitDecl;
@@ -102,16 +103,16 @@
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 +122,19 @@
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 +149,9 @@
///
/// \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 +160,20 @@
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;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits