23 #include "llvm/ADT/Triple.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/ManagedStatic.h" 26 #include "llvm/Support/Path.h" 27 #include "llvm/Support/raw_ostream.h" 36 class IndexErrorCategory :
public std::error_category {
38 const char *name() const noexcept
override {
return "clang.index"; }
40 std::string message(
int Condition)
const override {
41 switch (static_cast<index_error_code>(Condition)) {
43 return "An unknown error has occurred.";
45 return "The index file is missing.";
47 return "Invalid index file format.";
49 return "Multiple definitions in the index file.";
51 return "Missing definition from the index file.";
53 return "Failed to import the definition.";
55 return "Failed to load external AST source.";
57 return "Failed to generate USR.";
59 llvm_unreachable(
"Unrecognized index_error_code.");
63 static llvm::ManagedStatic<IndexErrorCategory>
Category;
69 OS <<
Category->message(static_cast<int>(Code)) <<
'\n';
73 return std::error_code(static_cast<int>(Code), *
Category);
78 std::ifstream ExternalFnMapFile(IndexPath);
79 if (!ExternalFnMapFile)
83 llvm::StringMap<std::string> Result;
86 while (std::getline(ExternalFnMapFile, Line)) {
87 const size_t Pos = Line.find(
" ");
88 if (Pos > 0 && Pos != std::string::npos) {
89 StringRef LineRef{Line};
90 StringRef FunctionLookupName = LineRef.substr(0, Pos);
91 if (Result.count(FunctionLookupName))
92 return llvm::make_error<IndexError>(
94 StringRef FileName = LineRef.substr(Pos + 1);
96 llvm::sys::path::append(FilePath, FileName);
97 Result[FunctionLookupName] = FilePath.str().str();
99 return llvm::make_error<IndexError>(
108 std::ostringstream Result;
109 for (
const auto &E : Index)
110 Result << E.getKey().str() <<
" " << E.getValue() <<
'\n';
115 : CI(CI), Context(CI.getASTContext()) {}
122 assert(!Ret &&
"Unable to generate USR");
123 return DeclUSR.str();
129 CrossTranslationUnitContext::findFunctionInDeclContext(
const DeclContext *DC,
130 StringRef LookupFnName) {
131 assert(DC &&
"Declaration Context must not be null");
135 if (
const auto *FD = findFunctionInDeclContext(SubDC, LookupFnName))
140 if (!ND || !ND->hasBody(ResultDecl))
151 StringRef CrossTUDir,
152 StringRef IndexName) {
153 assert(!FD->
hasBody() &&
"FD has a definition in current translation unit!");
155 if (LookupFnName.empty())
156 return llvm::make_error<IndexError>(
161 return ASTUnitOrError.takeError();
162 ASTUnit *Unit = *ASTUnitOrError;
164 return llvm::make_error<IndexError>(
171 findFunctionInDeclContext(TU, LookupFnName))
180 << IE.
getFileName() <<
"required by the CrossTU functionality";
196 StringRef LookupName, StringRef CrossTUDir, StringRef IndexName) {
202 auto FnUnitCacheEntry = FunctionASTUnitMap.find(LookupName);
203 if (FnUnitCacheEntry == FunctionASTUnitMap.end()) {
204 if (FunctionFileMap.empty()) {
206 if (llvm::sys::path::is_absolute(IndexName))
207 IndexFile = IndexName;
209 llvm::sys::path::append(IndexFile, IndexName);
213 FunctionFileMap = *IndexOrErr;
215 return IndexOrErr.takeError();
218 auto It = FunctionFileMap.find(LookupName);
219 if (It == FunctionFileMap.end())
221 StringRef ASTFileName = It->second;
222 auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName);
223 if (ASTCacheEntry == FileASTUnitMap.end()) {
234 Unit = LoadedUnit.get();
235 FileASTUnitMap[ASTFileName] = std::move(LoadedUnit);
237 Unit = ASTCacheEntry->second.get();
239 FunctionASTUnitMap[LookupName] = Unit;
241 Unit = FnUnitCacheEntry->second;
250 cast<FunctionDecl>(Importer.
Import(const_cast<FunctionDecl *>(FD)));
251 assert(ToDecl->hasBody());
252 assert(FD->
hasBody() &&
"Functions already imported should have body.");
257 CrossTranslationUnitContext::getOrCreateASTImporter(
ASTContext &From) {
259 if (I != ASTUnitImporterMap.end())
Represents a function declaration or definition.
CrossTranslationUnitContext(CompilerInstance &CI)
Load everything, including Sema.
std::shared_ptr< PCHContainerOperations > getPCHContainerOperations() const
Decl - This represents one declaration (or definition), e.g.
const FileManager & getFileManager() const
void log(raw_ostream &OS) const override
DiagnosticsEngine & getDiagnostics() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
static std::unique_ptr< ASTUnit > LoadFromASTFile(const std::string &Filename, const PCHContainerReader &PCHContainerRdr, WhatToLoad ToLoad, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, const FileSystemOptions &FileSystemOpts, bool UseDebugInfo=false, bool OnlyLocalDecls=false, ArrayRef< RemappedFile > RemappedFiles=None, bool CaptureDiagnostics=false, bool AllowPCHWithCompilerErrors=false, bool UserFilesAreVolatile=false)
Create a ASTUnit from an AST file.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
QualType Import(QualType FromT)
Import the given type from the "from" context into the "to" context.
llvm::Expected< ASTUnit * > loadExternalAST(StringRef LookupName, StringRef CrossTUDir, StringRef IndexName)
This function loads a function definition from an external AST file.
FileManager & getFileManager() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Utility class for loading a ASTContext from an AST file.
Concrete class used by the front-end to report problems and issues.
const AnnotatedLine * Line
std::string createCrossTUIndexString(const llvm::StringMap< std::string > &Index)
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
std::string getFileName() const
llvm::Expected< llvm::StringMap< std::string > > parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir)
This function parses an index file that determines which translation unit contains which definition...
~CrossTranslationUnitContext()
FileSystemOptions & getFileSystemOpts()
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Options for controlling the compiler diagnostics engine.
ASTContext & getASTContext() const LLVM_READONLY
llvm::Expected< const FunctionDecl * > getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, StringRef IndexName)
This function loads a function definition from an external AST file and merge it into the original AS...
Dataflow Directional Tag Classes.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Used for handling and querying diagnostic IDs.
index_error_code getCode() const
Imports selected nodes from one AST context into another context, merging AST nodes where appropriate...
llvm::Expected< const FunctionDecl * > importDefinition(const FunctionDecl *FD)
This function merges a definition from a separate AST Unit into the current one which was created by ...
const ASTContext & getASTContext() const
SourceManager & getSourceManager()
std::error_code convertToErrorCode() const override
TranslationUnitDecl * getTranslationUnitDecl() const
Defines the clang::TargetInfo interface.
static std::string getLookupName(const NamedDecl *ND)
Get a name to identify a function.
void emitCrossTUDiagnostics(const IndexError &IE)
Emit diagnostics for the user for potential configuration errors.
The top declaration context.
bool generateUSRForDecl(const Decl *D, SmallVectorImpl< char > &Buf)
Generate a USR for a Decl, including the USR prefix.
This represents a decl that may have a name.