1//===--- CrossTranslationUnit.h - -------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file provides an interface to load binary AST dumps on demand. This 11// feature can be utilized for tools that require cross translation unit 12// support. 13// 14//===----------------------------------------------------------------------===// 15#ifndef LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H 16#define LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H 17 18#include "clang/Basic/LLVM.h" 19#include "llvm/ADT/DenseMap.h" 20#include "llvm/ADT/SmallPtrSet.h" 21#include "llvm/ADT/StringMap.h" 22#include "llvm/Support/Error.h" 23 24namespace clang { 25class CompilerInstance; 26class ASTContext; 27class ASTImporter; 28class ASTUnit; 29class DeclContext; 30class FunctionDecl; 31class NamedDecl; 32class TranslationUnitDecl; 33 34namespace cross_tu { 35 36enum class index_error_code { 37 unspecified = 1, 38 missing_index_file, 39 invalid_index_format, 40 multiple_definitions, 41 missing_definition, 42 failed_import, 43 failed_to_get_external_ast, 44 failed_to_generate_usr 45}; 46 47class IndexError : public llvm::ErrorInfo<IndexError> { 48public: 49 static char ID; 50 IndexError(index_error_code C) : Code(C), LineNo(0) {} 51 IndexError(index_error_code C, std::string FileName, int LineNo = 0) 52 : Code(C), FileName(std::move(FileName)), LineNo(LineNo) {} 53 void log(raw_ostream &OS) const override; 54 std::error_code convertToErrorCode() const override; 55 index_error_code getCode() const { return Code; } 56 int getLineNum() const { return LineNo; } 57 std::string getFileName() const { return FileName; } 58 59private: 60 index_error_code Code; 61 std::string FileName; 62 int LineNo; 63}; 64 65/// \brief This function parses an index file that determines which 66/// translation unit contains which definition. 67/// 68/// The index file format is the following: 69/// each line consists of an USR and a filepath separated by a space. 70/// 71/// \return Returns a map where the USR is the key and the filepath is the value 72/// or an error. 73llvm::Expected<llvm::StringMap<std::string>> 74parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir); 75 76std::string createCrossTUIndexString(const llvm::StringMap<std::string> &Index); 77 78/// \brief This class is used for tools that requires cross translation 79/// unit capability. 80/// 81/// This class can load function definitions from external AST files. 82/// The loaded definition will be merged back to the original AST using the 83/// AST Importer. 84/// In order to use this class, an index file is required that describes 85/// the locations of the AST files for each function definition. 86/// 87/// Note that this class also implements caching. 88class CrossTranslationUnitContext { 89public: 90 CrossTranslationUnitContext(CompilerInstance &CI); 91 ~CrossTranslationUnitContext(); 92 93 /// \brief This function loads a function definition from an external AST 94 /// file and merge it into the original AST. 95 /// 96 /// This method should only be used on functions that have no definitions in 97 /// the current translation unit. A function definition with the same 98 /// declaration will be looked up in the index file which should be in the 99 /// \p CrossTUDir directory, called \p IndexName. In case the declaration is 100 /// found in the index the corresponding AST file will be loaded and the 101 /// definition of the function will be merged into the original AST using 102 /// the AST Importer. 103 /// 104 /// \return The declaration with the definition will be returned. 105 /// If no suitable definition is found in the index file or multiple 106 /// definitions found error will be returned. 107 /// 108 /// Note that the AST files should also be in the \p CrossTUDir. 109 llvm::Expected<const FunctionDecl *> 110 getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, 111 StringRef IndexName); 112 113 /// \brief This function loads a function definition from an external AST 114 /// file. 115 /// 116 /// A function definition with the same declaration will be looked up in the 117 /// index file which should be in the \p CrossTUDir directory, called 118 /// \p IndexName. In case the declaration is found in the index the 119 /// corresponding AST file will be loaded. 120 /// 121 /// \return Returns an ASTUnit that contains the definition of the looked up 122 /// function. 123 /// 124 /// Note that the AST files should also be in the \p CrossTUDir. 125 llvm::Expected<ASTUnit *> loadExternalAST(StringRef LookupName, 126 StringRef CrossTUDir, 127 StringRef IndexName); 128 129 /// \brief This function merges a definition from a separate AST Unit into 130 /// the current one which was created by the compiler instance that 131 /// was passed to the constructor. 132 /// 133 /// \return Returns the resulting definition or an error. 134 llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD); 135 136 /// \brief Get a name to identify a function. 137 static std::string getLookupName(const NamedDecl *ND); 138 139 /// \brief Emit diagnostics for the user for potential configuration errors. 140 void emitCrossTUDiagnostics(const IndexError &IE); 141 142private: 143 ASTImporter &getOrCreateASTImporter(ASTContext &From); 144 const FunctionDecl *findFunctionInDeclContext(const DeclContext *DC, 145 StringRef LookupFnName); 146 147 llvm::StringMap<std::unique_ptr<clang::ASTUnit>> FileASTUnitMap; 148 llvm::StringMap<clang::ASTUnit *> FunctionASTUnitMap; 149 llvm::StringMap<std::string> FunctionFileMap; 150 llvm::DenseMap<TranslationUnitDecl *, std::unique_ptr<ASTImporter>> 151 ASTUnitImporterMap; 152 CompilerInstance &CI; 153 ASTContext &Context; 154}; 155 156} // namespace cross_tu 157} // namespace clang 158 159#endif // LLVM_CLANG_CROSSTU_CROSSTRANSLATIONUNIT_H 160