| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 1 | //===--- CrossTranslationUnit.cpp - -----------------------------*- 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 implements the CrossTranslationUnit interface. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 | #include "clang/CrossTU/CrossTranslationUnit.h" | 
|  | 14 | #include "clang/AST/ASTImporter.h" | 
|  | 15 | #include "clang/AST/Decl.h" | 
|  | 16 | #include "clang/Basic/TargetInfo.h" | 
|  | 17 | #include "clang/CrossTU/CrossTUDiagnostic.h" | 
|  | 18 | #include "clang/Frontend/ASTUnit.h" | 
|  | 19 | #include "clang/Frontend/CompilerInstance.h" | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 20 | #include "clang/Frontend/TextDiagnosticPrinter.h" | 
|  | 21 | #include "clang/Index/USRGeneration.h" | 
|  | 22 | #include "llvm/ADT/Triple.h" | 
| Gabor Marton | 700a29a | 2018-12-07 11:55:22 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/Statistic.h" | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 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" | 
|  | 28 | #include <fstream> | 
|  | 29 | #include <sstream> | 
|  | 30 |  | 
|  | 31 | namespace clang { | 
|  | 32 | namespace cross_tu { | 
|  | 33 |  | 
|  | 34 | namespace { | 
| Gabor Marton | 32aff2e | 2018-12-07 16:32:43 +0000 | [diff] [blame] | 35 |  | 
| Gabor Marton | 700a29a | 2018-12-07 11:55:22 +0000 | [diff] [blame] | 36 | #define DEBUG_TYPE "CrossTranslationUnit" | 
|  | 37 | STATISTIC(NumGetCTUCalled, "The # of getCTUDefinition function called"); | 
|  | 38 | STATISTIC( | 
|  | 39 | NumNotInOtherTU, | 
|  | 40 | "The # of getCTUDefinition called but the function is not in any other TU"); | 
|  | 41 | STATISTIC(NumGetCTUSuccess, | 
|  | 42 | "The # of getCTUDefinition successfully returned the " | 
|  | 43 | "requested function's body"); | 
| Gabor Marton | 32aff2e | 2018-12-07 16:32:43 +0000 | [diff] [blame] | 44 | STATISTIC(NumTripleMismatch, "The # of triple mismatches"); | 
|  | 45 | STATISTIC(NumLangMismatch, "The # of language mismatches"); | 
|  | 46 |  | 
|  | 47 | // Same as Triple's equality operator, but we check a field only if that is | 
|  | 48 | // known in both instances. | 
|  | 49 | bool hasEqualKnownFields(const llvm::Triple &Lhs, const llvm::Triple &Rhs) { | 
|  | 50 | using llvm::Triple; | 
|  | 51 | if (Lhs.getArch() != Triple::UnknownArch && | 
|  | 52 | Rhs.getArch() != Triple::UnknownArch && Lhs.getArch() != Rhs.getArch()) | 
|  | 53 | return false; | 
|  | 54 | if (Lhs.getSubArch() != Triple::NoSubArch && | 
|  | 55 | Rhs.getSubArch() != Triple::NoSubArch && | 
|  | 56 | Lhs.getSubArch() != Rhs.getSubArch()) | 
|  | 57 | return false; | 
|  | 58 | if (Lhs.getVendor() != Triple::UnknownVendor && | 
|  | 59 | Rhs.getVendor() != Triple::UnknownVendor && | 
|  | 60 | Lhs.getVendor() != Rhs.getVendor()) | 
|  | 61 | return false; | 
|  | 62 | if (!Lhs.isOSUnknown() && !Rhs.isOSUnknown() && | 
|  | 63 | Lhs.getOS() != Rhs.getOS()) | 
|  | 64 | return false; | 
|  | 65 | if (Lhs.getEnvironment() != Triple::UnknownEnvironment && | 
|  | 66 | Rhs.getEnvironment() != Triple::UnknownEnvironment && | 
|  | 67 | Lhs.getEnvironment() != Rhs.getEnvironment()) | 
|  | 68 | return false; | 
|  | 69 | if (Lhs.getObjectFormat() != Triple::UnknownObjectFormat && | 
|  | 70 | Rhs.getObjectFormat() != Triple::UnknownObjectFormat && | 
|  | 71 | Lhs.getObjectFormat() != Rhs.getObjectFormat()) | 
|  | 72 | return false; | 
|  | 73 | return true; | 
|  | 74 | } | 
| Gabor Marton | 700a29a | 2018-12-07 11:55:22 +0000 | [diff] [blame] | 75 |  | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 76 | // FIXME: This class is will be removed after the transition to llvm::Error. | 
|  | 77 | class IndexErrorCategory : public std::error_category { | 
|  | 78 | public: | 
|  | 79 | const char *name() const noexcept override { return "clang.index"; } | 
|  | 80 |  | 
|  | 81 | std::string message(int Condition) const override { | 
|  | 82 | switch (static_cast<index_error_code>(Condition)) { | 
|  | 83 | case index_error_code::unspecified: | 
|  | 84 | return "An unknown error has occurred."; | 
|  | 85 | case index_error_code::missing_index_file: | 
|  | 86 | return "The index file is missing."; | 
|  | 87 | case index_error_code::invalid_index_format: | 
|  | 88 | return "Invalid index file format."; | 
|  | 89 | case index_error_code::multiple_definitions: | 
|  | 90 | return "Multiple definitions in the index file."; | 
|  | 91 | case index_error_code::missing_definition: | 
|  | 92 | return "Missing definition from the index file."; | 
|  | 93 | case index_error_code::failed_import: | 
|  | 94 | return "Failed to import the definition."; | 
|  | 95 | case index_error_code::failed_to_get_external_ast: | 
|  | 96 | return "Failed to load external AST source."; | 
|  | 97 | case index_error_code::failed_to_generate_usr: | 
|  | 98 | return "Failed to generate USR."; | 
| Gabor Marton | 32aff2e | 2018-12-07 16:32:43 +0000 | [diff] [blame] | 99 | case index_error_code::triple_mismatch: | 
|  | 100 | return "Triple mismatch"; | 
|  | 101 | case index_error_code::lang_mismatch: | 
|  | 102 | return "Language mismatch"; | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 103 | } | 
|  | 104 | llvm_unreachable("Unrecognized index_error_code."); | 
|  | 105 | } | 
|  | 106 | }; | 
|  | 107 |  | 
|  | 108 | static llvm::ManagedStatic<IndexErrorCategory> Category; | 
|  | 109 | } // end anonymous namespace | 
|  | 110 |  | 
|  | 111 | char IndexError::ID; | 
|  | 112 |  | 
|  | 113 | void IndexError::log(raw_ostream &OS) const { | 
|  | 114 | OS << Category->message(static_cast<int>(Code)) << '\n'; | 
|  | 115 | } | 
|  | 116 |  | 
|  | 117 | std::error_code IndexError::convertToErrorCode() const { | 
|  | 118 | return std::error_code(static_cast<int>(Code), *Category); | 
|  | 119 | } | 
|  | 120 |  | 
|  | 121 | llvm::Expected<llvm::StringMap<std::string>> | 
|  | 122 | parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir) { | 
| Rafael Stahl | 8c48705 | 2019-01-10 17:44:04 +0000 | [diff] [blame^] | 123 | std::ifstream ExternalMapFile(IndexPath); | 
|  | 124 | if (!ExternalMapFile) | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 125 | return llvm::make_error<IndexError>(index_error_code::missing_index_file, | 
|  | 126 | IndexPath.str()); | 
|  | 127 |  | 
|  | 128 | llvm::StringMap<std::string> Result; | 
|  | 129 | std::string Line; | 
|  | 130 | unsigned LineNo = 1; | 
| Rafael Stahl | 8c48705 | 2019-01-10 17:44:04 +0000 | [diff] [blame^] | 131 | while (std::getline(ExternalMapFile, Line)) { | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 132 | const size_t Pos = Line.find(" "); | 
|  | 133 | if (Pos > 0 && Pos != std::string::npos) { | 
|  | 134 | StringRef LineRef{Line}; | 
| Rafael Stahl | 8c48705 | 2019-01-10 17:44:04 +0000 | [diff] [blame^] | 135 | StringRef LookupName = LineRef.substr(0, Pos); | 
|  | 136 | if (Result.count(LookupName)) | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 137 | return llvm::make_error<IndexError>( | 
|  | 138 | index_error_code::multiple_definitions, IndexPath.str(), LineNo); | 
|  | 139 | StringRef FileName = LineRef.substr(Pos + 1); | 
|  | 140 | SmallString<256> FilePath = CrossTUDir; | 
| Gabor Horvath | 724beac | 2017-10-27 12:53:37 +0000 | [diff] [blame] | 141 | llvm::sys::path::append(FilePath, FileName); | 
| Rafael Stahl | 8c48705 | 2019-01-10 17:44:04 +0000 | [diff] [blame^] | 142 | Result[LookupName] = FilePath.str().str(); | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 143 | } else | 
|  | 144 | return llvm::make_error<IndexError>( | 
|  | 145 | index_error_code::invalid_index_format, IndexPath.str(), LineNo); | 
|  | 146 | LineNo++; | 
|  | 147 | } | 
|  | 148 | return Result; | 
|  | 149 | } | 
|  | 150 |  | 
|  | 151 | std::string | 
|  | 152 | createCrossTUIndexString(const llvm::StringMap<std::string> &Index) { | 
|  | 153 | std::ostringstream Result; | 
|  | 154 | for (const auto &E : Index) | 
|  | 155 | Result << E.getKey().str() << " " << E.getValue() << '\n'; | 
|  | 156 | return Result.str(); | 
|  | 157 | } | 
|  | 158 |  | 
|  | 159 | CrossTranslationUnitContext::CrossTranslationUnitContext(CompilerInstance &CI) | 
|  | 160 | : CI(CI), Context(CI.getASTContext()) {} | 
|  | 161 |  | 
|  | 162 | CrossTranslationUnitContext::~CrossTranslationUnitContext() {} | 
|  | 163 |  | 
|  | 164 | std::string CrossTranslationUnitContext::getLookupName(const NamedDecl *ND) { | 
|  | 165 | SmallString<128> DeclUSR; | 
| Richard Trieu | 8bd58bf | 2017-09-22 22:16:13 +0000 | [diff] [blame] | 166 | bool Ret = index::generateUSRForDecl(ND, DeclUSR); (void)Ret; | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 167 | assert(!Ret && "Unable to generate USR"); | 
|  | 168 | return DeclUSR.str(); | 
|  | 169 | } | 
|  | 170 |  | 
|  | 171 | /// Recursively visits the function decls of a DeclContext, and looks up a | 
|  | 172 | /// function based on USRs. | 
|  | 173 | const FunctionDecl * | 
|  | 174 | CrossTranslationUnitContext::findFunctionInDeclContext(const DeclContext *DC, | 
|  | 175 | StringRef LookupFnName) { | 
|  | 176 | assert(DC && "Declaration Context must not be null"); | 
|  | 177 | for (const Decl *D : DC->decls()) { | 
|  | 178 | const auto *SubDC = dyn_cast<DeclContext>(D); | 
|  | 179 | if (SubDC) | 
|  | 180 | if (const auto *FD = findFunctionInDeclContext(SubDC, LookupFnName)) | 
|  | 181 | return FD; | 
|  | 182 |  | 
|  | 183 | const auto *ND = dyn_cast<FunctionDecl>(D); | 
|  | 184 | const FunctionDecl *ResultDecl; | 
|  | 185 | if (!ND || !ND->hasBody(ResultDecl)) | 
|  | 186 | continue; | 
|  | 187 | if (getLookupName(ResultDecl) != LookupFnName) | 
|  | 188 | continue; | 
|  | 189 | return ResultDecl; | 
|  | 190 | } | 
|  | 191 | return nullptr; | 
|  | 192 | } | 
|  | 193 |  | 
|  | 194 | llvm::Expected<const FunctionDecl *> | 
|  | 195 | CrossTranslationUnitContext::getCrossTUDefinition(const FunctionDecl *FD, | 
|  | 196 | StringRef CrossTUDir, | 
| Gabor Marton | 9419eb4 | 2018-12-07 14:56:02 +0000 | [diff] [blame] | 197 | StringRef IndexName, | 
|  | 198 | bool DisplayCTUProgress) { | 
| Gabor Marton | b7f30dd | 2018-12-07 12:21:43 +0000 | [diff] [blame] | 199 | assert(FD && "FD is missing, bad call to this function!"); | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 200 | assert(!FD->hasBody() && "FD has a definition in current translation unit!"); | 
| Gabor Marton | 700a29a | 2018-12-07 11:55:22 +0000 | [diff] [blame] | 201 | ++NumGetCTUCalled; | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 202 | const std::string LookupFnName = getLookupName(FD); | 
|  | 203 | if (LookupFnName.empty()) | 
|  | 204 | return llvm::make_error<IndexError>( | 
|  | 205 | index_error_code::failed_to_generate_usr); | 
|  | 206 | llvm::Expected<ASTUnit *> ASTUnitOrError = | 
| Gabor Marton | 9419eb4 | 2018-12-07 14:56:02 +0000 | [diff] [blame] | 207 | loadExternalAST(LookupFnName, CrossTUDir, IndexName, DisplayCTUProgress); | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 208 | if (!ASTUnitOrError) | 
|  | 209 | return ASTUnitOrError.takeError(); | 
|  | 210 | ASTUnit *Unit = *ASTUnitOrError; | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 211 | assert(&Unit->getFileManager() == | 
|  | 212 | &Unit->getASTContext().getSourceManager().getFileManager()); | 
|  | 213 |  | 
| Gabor Marton | 32aff2e | 2018-12-07 16:32:43 +0000 | [diff] [blame] | 214 | const llvm::Triple &TripleTo = Context.getTargetInfo().getTriple(); | 
|  | 215 | const llvm::Triple &TripleFrom = | 
|  | 216 | Unit->getASTContext().getTargetInfo().getTriple(); | 
|  | 217 | // The imported AST had been generated for a different target. | 
|  | 218 | // Some parts of the triple in the loaded ASTContext can be unknown while the | 
|  | 219 | // very same parts in the target ASTContext are known. Thus we check for the | 
|  | 220 | // known parts only. | 
|  | 221 | if (!hasEqualKnownFields(TripleTo, TripleFrom)) { | 
|  | 222 | // TODO: Pass the SourceLocation of the CallExpression for more precise | 
|  | 223 | // diagnostics. | 
|  | 224 | ++NumTripleMismatch; | 
|  | 225 | return llvm::make_error<IndexError>(index_error_code::triple_mismatch, | 
|  | 226 | Unit->getMainFileName(), TripleTo.str(), | 
|  | 227 | TripleFrom.str()); | 
|  | 228 | } | 
|  | 229 |  | 
|  | 230 | const auto &LangTo = Context.getLangOpts(); | 
|  | 231 | const auto &LangFrom = Unit->getASTContext().getLangOpts(); | 
|  | 232 | // FIXME: Currenty we do not support CTU across C++ and C and across | 
|  | 233 | // different dialects of C++. | 
|  | 234 | if (LangTo.CPlusPlus != LangFrom.CPlusPlus) { | 
|  | 235 | ++NumLangMismatch; | 
|  | 236 | return llvm::make_error<IndexError>(index_error_code::lang_mismatch); | 
|  | 237 | } | 
|  | 238 |  | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 239 | TranslationUnitDecl *TU = Unit->getASTContext().getTranslationUnitDecl(); | 
|  | 240 | if (const FunctionDecl *ResultDecl = | 
|  | 241 | findFunctionInDeclContext(TU, LookupFnName)) | 
|  | 242 | return importDefinition(ResultDecl); | 
|  | 243 | return llvm::make_error<IndexError>(index_error_code::failed_import); | 
|  | 244 | } | 
|  | 245 |  | 
|  | 246 | void CrossTranslationUnitContext::emitCrossTUDiagnostics(const IndexError &IE) { | 
|  | 247 | switch (IE.getCode()) { | 
|  | 248 | case index_error_code::missing_index_file: | 
| Richard Trieu | 0f25c74 | 2018-12-14 03:35:10 +0000 | [diff] [blame] | 249 | Context.getDiagnostics().Report(diag::err_ctu_error_opening) | 
|  | 250 | << IE.getFileName(); | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 251 | break; | 
|  | 252 | case index_error_code::invalid_index_format: | 
| Rafael Stahl | 8c48705 | 2019-01-10 17:44:04 +0000 | [diff] [blame^] | 253 | Context.getDiagnostics().Report(diag::err_extdefmap_parsing) | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 254 | << IE.getFileName() << IE.getLineNum(); | 
| Simon Pilgrim | 554ab53 | 2017-09-24 15:17:46 +0000 | [diff] [blame] | 255 | break; | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 256 | case index_error_code::multiple_definitions: | 
|  | 257 | Context.getDiagnostics().Report(diag::err_multiple_def_index) | 
|  | 258 | << IE.getLineNum(); | 
|  | 259 | break; | 
| Gabor Marton | 32aff2e | 2018-12-07 16:32:43 +0000 | [diff] [blame] | 260 | case index_error_code::triple_mismatch: | 
|  | 261 | Context.getDiagnostics().Report(diag::warn_ctu_incompat_triple) | 
|  | 262 | << IE.getFileName() << IE.getTripleToName() << IE.getTripleFromName(); | 
|  | 263 | break; | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 264 | default: | 
|  | 265 | break; | 
|  | 266 | } | 
|  | 267 | } | 
|  | 268 |  | 
|  | 269 | llvm::Expected<ASTUnit *> CrossTranslationUnitContext::loadExternalAST( | 
| Gabor Marton | 9419eb4 | 2018-12-07 14:56:02 +0000 | [diff] [blame] | 270 | StringRef LookupName, StringRef CrossTUDir, StringRef IndexName, | 
|  | 271 | bool DisplayCTUProgress) { | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 272 | // FIXME: The current implementation only supports loading functions with | 
|  | 273 | //        a lookup name from a single translation unit. If multiple | 
|  | 274 | //        translation units contains functions with the same lookup name an | 
|  | 275 | //        error will be returned. | 
|  | 276 | ASTUnit *Unit = nullptr; | 
|  | 277 | auto FnUnitCacheEntry = FunctionASTUnitMap.find(LookupName); | 
|  | 278 | if (FnUnitCacheEntry == FunctionASTUnitMap.end()) { | 
|  | 279 | if (FunctionFileMap.empty()) { | 
|  | 280 | SmallString<256> IndexFile = CrossTUDir; | 
|  | 281 | if (llvm::sys::path::is_absolute(IndexName)) | 
|  | 282 | IndexFile = IndexName; | 
|  | 283 | else | 
|  | 284 | llvm::sys::path::append(IndexFile, IndexName); | 
|  | 285 | llvm::Expected<llvm::StringMap<std::string>> IndexOrErr = | 
|  | 286 | parseCrossTUIndex(IndexFile, CrossTUDir); | 
|  | 287 | if (IndexOrErr) | 
|  | 288 | FunctionFileMap = *IndexOrErr; | 
|  | 289 | else | 
|  | 290 | return IndexOrErr.takeError(); | 
|  | 291 | } | 
|  | 292 |  | 
|  | 293 | auto It = FunctionFileMap.find(LookupName); | 
| Gabor Marton | 700a29a | 2018-12-07 11:55:22 +0000 | [diff] [blame] | 294 | if (It == FunctionFileMap.end()) { | 
|  | 295 | ++NumNotInOtherTU; | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 296 | return llvm::make_error<IndexError>(index_error_code::missing_definition); | 
| Gabor Marton | 700a29a | 2018-12-07 11:55:22 +0000 | [diff] [blame] | 297 | } | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 298 | StringRef ASTFileName = It->second; | 
|  | 299 | auto ASTCacheEntry = FileASTUnitMap.find(ASTFileName); | 
|  | 300 | if (ASTCacheEntry == FileASTUnitMap.end()) { | 
|  | 301 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); | 
|  | 302 | TextDiagnosticPrinter *DiagClient = | 
|  | 303 | new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts); | 
|  | 304 | IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); | 
|  | 305 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags( | 
|  | 306 | new DiagnosticsEngine(DiagID, &*DiagOpts, DiagClient)); | 
|  | 307 |  | 
|  | 308 | std::unique_ptr<ASTUnit> LoadedUnit(ASTUnit::LoadFromASTFile( | 
|  | 309 | ASTFileName, CI.getPCHContainerOperations()->getRawReader(), | 
|  | 310 | ASTUnit::LoadEverything, Diags, CI.getFileSystemOpts())); | 
|  | 311 | Unit = LoadedUnit.get(); | 
|  | 312 | FileASTUnitMap[ASTFileName] = std::move(LoadedUnit); | 
| Gabor Marton | 9419eb4 | 2018-12-07 14:56:02 +0000 | [diff] [blame] | 313 | if (DisplayCTUProgress) { | 
|  | 314 | llvm::errs() << "CTU loaded AST file: " | 
|  | 315 | << ASTFileName << "\n"; | 
|  | 316 | } | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 317 | } else { | 
|  | 318 | Unit = ASTCacheEntry->second.get(); | 
|  | 319 | } | 
|  | 320 | FunctionASTUnitMap[LookupName] = Unit; | 
|  | 321 | } else { | 
|  | 322 | Unit = FnUnitCacheEntry->second; | 
|  | 323 | } | 
| Gabor Marton | 3081690 | 2019-01-07 14:05:19 +0000 | [diff] [blame] | 324 | if (!Unit) | 
|  | 325 | return llvm::make_error<IndexError>( | 
|  | 326 | index_error_code::failed_to_get_external_ast); | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 327 | return Unit; | 
|  | 328 | } | 
|  | 329 |  | 
|  | 330 | llvm::Expected<const FunctionDecl *> | 
|  | 331 | CrossTranslationUnitContext::importDefinition(const FunctionDecl *FD) { | 
| Gabor Marton | b7f30dd | 2018-12-07 12:21:43 +0000 | [diff] [blame] | 332 | assert(FD->hasBody() && "Functions to be imported should have body."); | 
|  | 333 |  | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 334 | ASTImporter &Importer = getOrCreateASTImporter(FD->getASTContext()); | 
|  | 335 | auto *ToDecl = | 
| Gabor Marton | b87251d | 2018-12-07 16:05:58 +0000 | [diff] [blame] | 336 | cast_or_null<FunctionDecl>(Importer.Import(const_cast<FunctionDecl *>(FD))); | 
|  | 337 | if (!ToDecl) | 
|  | 338 | return llvm::make_error<IndexError>(index_error_code::failed_import); | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 339 | assert(ToDecl->hasBody()); | 
|  | 340 | assert(FD->hasBody() && "Functions already imported should have body."); | 
| Gabor Marton | 700a29a | 2018-12-07 11:55:22 +0000 | [diff] [blame] | 341 | ++NumGetCTUSuccess; | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 342 | return ToDecl; | 
|  | 343 | } | 
|  | 344 |  | 
| Gabor Marton | 54058b5 | 2018-12-17 13:53:12 +0000 | [diff] [blame] | 345 | void CrossTranslationUnitContext::lazyInitLookupTable( | 
|  | 346 | TranslationUnitDecl *ToTU) { | 
|  | 347 | if (!LookupTable) | 
|  | 348 | LookupTable = llvm::make_unique<ASTImporterLookupTable>(*ToTU); | 
|  | 349 | } | 
|  | 350 |  | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 351 | ASTImporter & | 
|  | 352 | CrossTranslationUnitContext::getOrCreateASTImporter(ASTContext &From) { | 
|  | 353 | auto I = ASTUnitImporterMap.find(From.getTranslationUnitDecl()); | 
|  | 354 | if (I != ASTUnitImporterMap.end()) | 
|  | 355 | return *I->second; | 
| Gabor Marton | 54058b5 | 2018-12-17 13:53:12 +0000 | [diff] [blame] | 356 | lazyInitLookupTable(Context.getTranslationUnitDecl()); | 
|  | 357 | ASTImporter *NewImporter = new ASTImporter( | 
|  | 358 | Context, Context.getSourceManager().getFileManager(), From, | 
|  | 359 | From.getSourceManager().getFileManager(), false, LookupTable.get()); | 
| Gabor Horvath | e350b0a | 2017-09-22 11:11:01 +0000 | [diff] [blame] | 360 | ASTUnitImporterMap[From.getTranslationUnitDecl()].reset(NewImporter); | 
|  | 361 | return *NewImporter; | 
|  | 362 | } | 
|  | 363 |  | 
|  | 364 | } // namespace cross_tu | 
|  | 365 | } // namespace clang |