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 24 namespace clang { 25 class CompilerInstance; 26 class ASTContext; 27 class ASTImporter; 28 class ASTUnit; 29 class DeclContext; 30 class FunctionDecl; 31 class NamedDecl; 32 class TranslationUnitDecl; 33 34 namespace cross_tu { 35 36 enum 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 47 class IndexError : public llvm::ErrorInfo<IndexError> { 48 public: 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 59 private: 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. 73 llvm::Expected<llvm::StringMap<std::string>> 74 parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir); 75 76 std::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. 88 class CrossTranslationUnitContext { 89 public: 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 142 private: 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