1 //===- Indexing.cpp - Higher level API functions --------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CIndexDiagnostic.h" 10 #include "CIndexer.h" 11 #include "CLog.h" 12 #include "CXCursor.h" 13 #include "CXIndexDataConsumer.h" 14 #include "CXSourceLocation.h" 15 #include "CXString.h" 16 #include "CXTranslationUnit.h" 17 #include "clang/AST/ASTConsumer.h" 18 #include "clang/Frontend/ASTUnit.h" 19 #include "clang/Frontend/CompilerInstance.h" 20 #include "clang/Frontend/CompilerInvocation.h" 21 #include "clang/Frontend/FrontendAction.h" 22 #include "clang/Frontend/MultiplexConsumer.h" 23 #include "clang/Frontend/Utils.h" 24 #include "clang/Index/IndexingAction.h" 25 #include "clang/Lex/HeaderSearch.h" 26 #include "clang/Lex/PPCallbacks.h" 27 #include "clang/Lex/PPConditionalDirectiveRecord.h" 28 #include "clang/Lex/Preprocessor.h" 29 #include "clang/Lex/PreprocessorOptions.h" 30 #include "llvm/Support/CrashRecoveryContext.h" 31 #include "llvm/Support/MemoryBuffer.h" 32 #include <cstdio> 33 #include <mutex> 34 #include <utility> 35 36 using namespace clang; 37 using namespace clang::index; 38 using namespace cxtu; 39 using namespace cxindex; 40 41 namespace { 42 43 //===----------------------------------------------------------------------===// 44 // Skip Parsed Bodies 45 //===----------------------------------------------------------------------===// 46 47 /// A "region" in source code identified by the file/offset of the 48 /// preprocessor conditional directive that it belongs to. 49 /// Multiple, non-consecutive ranges can be parts of the same region. 50 /// 51 /// As an example of different regions separated by preprocessor directives: 52 /// 53 /// \code 54 /// #1 55 /// #ifdef BLAH 56 /// #2 57 /// #ifdef CAKE 58 /// #3 59 /// #endif 60 /// #2 61 /// #endif 62 /// #1 63 /// \endcode 64 /// 65 /// There are 3 regions, with non-consecutive parts: 66 /// #1 is identified as the beginning of the file 67 /// #2 is identified as the location of "#ifdef BLAH" 68 /// #3 is identified as the location of "#ifdef CAKE" 69 /// 70 class PPRegion { 71 llvm::sys::fs::UniqueID UniqueID; 72 time_t ModTime; 73 unsigned Offset; 74 public: 75 PPRegion() : UniqueID(0, 0), ModTime(), Offset() {} 76 PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime) 77 : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {} 78 79 const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; } 80 unsigned getOffset() const { return Offset; } 81 time_t getModTime() const { return ModTime; } 82 83 bool isInvalid() const { return *this == PPRegion(); } 84 85 friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) { 86 return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset && 87 lhs.ModTime == rhs.ModTime; 88 } 89 }; 90 91 } // end anonymous namespace 92 93 namespace llvm { 94 95 template <> 96 struct DenseMapInfo<PPRegion> { 97 static inline PPRegion getEmptyKey() { 98 return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0); 99 } 100 static inline PPRegion getTombstoneKey() { 101 return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0); 102 } 103 104 static unsigned getHashValue(const PPRegion &S) { 105 llvm::FoldingSetNodeID ID; 106 const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID(); 107 ID.AddInteger(UniqueID.getFile()); 108 ID.AddInteger(UniqueID.getDevice()); 109 ID.AddInteger(S.getOffset()); 110 ID.AddInteger(S.getModTime()); 111 return ID.ComputeHash(); 112 } 113 114 static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) { 115 return LHS == RHS; 116 } 117 }; 118 } 119 120 namespace { 121 122 /// Keeps track of function bodies that have already been parsed. 123 /// 124 /// Is thread-safe. 125 class ThreadSafeParsedRegions { 126 mutable std::mutex Mutex; 127 llvm::DenseSet<PPRegion> ParsedRegions; 128 129 public: 130 ~ThreadSafeParsedRegions() = default; 131 132 llvm::DenseSet<PPRegion> getParsedRegions() const { 133 std::lock_guard<std::mutex> MG(Mutex); 134 return ParsedRegions; 135 } 136 137 void addParsedRegions(ArrayRef<PPRegion> Regions) { 138 std::lock_guard<std::mutex> MG(Mutex); 139 ParsedRegions.insert(Regions.begin(), Regions.end()); 140 } 141 }; 142 143 /// Provides information whether source locations have already been parsed in 144 /// another FrontendAction. 145 /// 146 /// Is NOT thread-safe. 147 class ParsedSrcLocationsTracker { 148 ThreadSafeParsedRegions &ParsedRegionsStorage; 149 PPConditionalDirectiveRecord &PPRec; 150 Preprocessor &PP; 151 152 /// Snapshot of the shared state at the point when this instance was 153 /// constructed. 154 llvm::DenseSet<PPRegion> ParsedRegionsSnapshot; 155 /// Regions that were queried during this instance lifetime. 156 SmallVector<PPRegion, 32> NewParsedRegions; 157 158 /// Caching the last queried region. 159 PPRegion LastRegion; 160 bool LastIsParsed; 161 162 public: 163 /// Creates snapshot of \p ParsedRegionsStorage. 164 ParsedSrcLocationsTracker(ThreadSafeParsedRegions &ParsedRegionsStorage, 165 PPConditionalDirectiveRecord &ppRec, 166 Preprocessor &pp) 167 : ParsedRegionsStorage(ParsedRegionsStorage), PPRec(ppRec), PP(pp), 168 ParsedRegionsSnapshot(ParsedRegionsStorage.getParsedRegions()) {} 169 170 /// \returns true iff \p Loc has already been parsed. 171 /// 172 /// Can provide false-negative in case the location was parsed after this 173 /// instance had been constructed. 174 bool hasAlredyBeenParsed(SourceLocation Loc, FileID FID, 175 const FileEntry *FE) { 176 assert(FE); 177 PPRegion region = getRegion(Loc, FID, FE); 178 if (region.isInvalid()) 179 return false; 180 181 // Check common case, consecutive functions in the same region. 182 if (LastRegion == region) 183 return LastIsParsed; 184 185 LastRegion = region; 186 // Source locations can't be revisited during single TU parsing. 187 // That means if we hit the same region again, it's a different location in 188 // the same region and so the "is parsed" value from the snapshot is still 189 // correct. 190 LastIsParsed = ParsedRegionsSnapshot.count(region); 191 if (!LastIsParsed) 192 NewParsedRegions.emplace_back(std::move(region)); 193 return LastIsParsed; 194 } 195 196 /// Updates ParsedRegionsStorage with newly parsed regions. 197 void syncWithStorage() { 198 ParsedRegionsStorage.addParsedRegions(NewParsedRegions); 199 } 200 201 private: 202 PPRegion getRegion(SourceLocation Loc, FileID FID, const FileEntry *FE) { 203 assert(FE); 204 auto Bail = [this, FE]() { 205 if (isParsedOnceInclude(FE)) { 206 const llvm::sys::fs::UniqueID &ID = FE->getUniqueID(); 207 return PPRegion(ID, 0, FE->getModificationTime()); 208 } 209 return PPRegion(); 210 }; 211 212 SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc); 213 assert(RegionLoc.isFileID()); 214 if (RegionLoc.isInvalid()) 215 return Bail(); 216 217 FileID RegionFID; 218 unsigned RegionOffset; 219 std::tie(RegionFID, RegionOffset) = 220 PPRec.getSourceManager().getDecomposedLoc(RegionLoc); 221 222 if (RegionFID != FID) 223 return Bail(); 224 225 const llvm::sys::fs::UniqueID &ID = FE->getUniqueID(); 226 return PPRegion(ID, RegionOffset, FE->getModificationTime()); 227 } 228 229 bool isParsedOnceInclude(const FileEntry *FE) { 230 return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE) || 231 PP.getHeaderSearchInfo().hasFileBeenImported(FE); 232 } 233 }; 234 235 //===----------------------------------------------------------------------===// 236 // IndexPPCallbacks 237 //===----------------------------------------------------------------------===// 238 239 class IndexPPCallbacks : public PPCallbacks { 240 Preprocessor &PP; 241 CXIndexDataConsumer &DataConsumer; 242 bool IsMainFileEntered; 243 244 public: 245 IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer) 246 : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { } 247 248 void FileChanged(SourceLocation Loc, FileChangeReason Reason, 249 SrcMgr::CharacteristicKind FileType, FileID PrevFID) override { 250 if (IsMainFileEntered) 251 return; 252 253 SourceManager &SM = PP.getSourceManager(); 254 SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID()); 255 256 if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) { 257 IsMainFileEntered = true; 258 DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID())); 259 } 260 } 261 262 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, 263 StringRef FileName, bool IsAngled, 264 CharSourceRange FilenameRange, 265 OptionalFileEntryRef File, StringRef SearchPath, 266 StringRef RelativePath, const Module *Imported, 267 SrcMgr::CharacteristicKind FileType) override { 268 bool isImport = (IncludeTok.is(tok::identifier) && 269 IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import); 270 DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled, 271 Imported); 272 } 273 274 /// MacroDefined - This hook is called whenever a macro definition is seen. 275 void MacroDefined(const Token &Id, const MacroDirective *MD) override {} 276 277 /// MacroUndefined - This hook is called whenever a macro #undef is seen. 278 /// MI is released immediately following this callback. 279 void MacroUndefined(const Token &MacroNameTok, 280 const MacroDefinition &MD, 281 const MacroDirective *UD) override {} 282 283 /// MacroExpands - This is called by when a macro invocation is found. 284 void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, 285 SourceRange Range, const MacroArgs *Args) override {} 286 287 /// SourceRangeSkipped - This hook is called when a source range is skipped. 288 /// \param Range The SourceRange that was skipped. The range begins at the 289 /// #if/#else directive and ends after the #endif/#else directive. 290 void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override { 291 } 292 }; 293 294 //===----------------------------------------------------------------------===// 295 // IndexingConsumer 296 //===----------------------------------------------------------------------===// 297 298 class IndexingConsumer : public ASTConsumer { 299 CXIndexDataConsumer &DataConsumer; 300 301 public: 302 IndexingConsumer(CXIndexDataConsumer &dataConsumer, 303 ParsedSrcLocationsTracker *parsedLocsTracker) 304 : DataConsumer(dataConsumer) {} 305 306 void Initialize(ASTContext &Context) override { 307 DataConsumer.setASTContext(Context); 308 DataConsumer.startedTranslationUnit(); 309 } 310 311 bool HandleTopLevelDecl(DeclGroupRef DG) override { 312 return !DataConsumer.shouldAbort(); 313 } 314 }; 315 316 //===----------------------------------------------------------------------===// 317 // CaptureDiagnosticConsumer 318 //===----------------------------------------------------------------------===// 319 320 class CaptureDiagnosticConsumer : public DiagnosticConsumer { 321 SmallVector<StoredDiagnostic, 4> Errors; 322 public: 323 324 void HandleDiagnostic(DiagnosticsEngine::Level level, 325 const Diagnostic &Info) override { 326 if (level >= DiagnosticsEngine::Error) 327 Errors.push_back(StoredDiagnostic(level, Info)); 328 } 329 }; 330 331 //===----------------------------------------------------------------------===// 332 // IndexingFrontendAction 333 //===----------------------------------------------------------------------===// 334 335 class IndexingFrontendAction : public ASTFrontendAction { 336 std::shared_ptr<CXIndexDataConsumer> DataConsumer; 337 IndexingOptions Opts; 338 339 ThreadSafeParsedRegions *SKData; 340 std::unique_ptr<ParsedSrcLocationsTracker> ParsedLocsTracker; 341 342 public: 343 IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer, 344 const IndexingOptions &Opts, 345 ThreadSafeParsedRegions *skData) 346 : DataConsumer(std::move(dataConsumer)), Opts(Opts), SKData(skData) {} 347 348 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 349 StringRef InFile) override { 350 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 351 352 if (!PPOpts.ImplicitPCHInclude.empty()) { 353 auto File = CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude); 354 if (File) 355 DataConsumer->importedPCH(*File); 356 } 357 358 DataConsumer->setASTContext(CI.getASTContext()); 359 Preprocessor &PP = CI.getPreprocessor(); 360 PP.addPPCallbacks(std::make_unique<IndexPPCallbacks>(PP, *DataConsumer)); 361 DataConsumer->setPreprocessor(CI.getPreprocessorPtr()); 362 363 if (SKData) { 364 auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager()); 365 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec)); 366 ParsedLocsTracker = 367 std::make_unique<ParsedSrcLocationsTracker>(*SKData, *PPRec, PP); 368 } 369 370 std::vector<std::unique_ptr<ASTConsumer>> Consumers; 371 Consumers.push_back(std::make_unique<IndexingConsumer>( 372 *DataConsumer, ParsedLocsTracker.get())); 373 Consumers.push_back(createIndexingASTConsumer( 374 DataConsumer, Opts, CI.getPreprocessorPtr(), 375 [this](const Decl *D) { return this->shouldSkipFunctionBody(D); })); 376 return std::make_unique<MultiplexConsumer>(std::move(Consumers)); 377 } 378 379 bool shouldSkipFunctionBody(const Decl *D) { 380 if (!ParsedLocsTracker) { 381 // Always skip bodies. 382 return true; 383 } 384 385 const SourceManager &SM = D->getASTContext().getSourceManager(); 386 SourceLocation Loc = D->getLocation(); 387 if (Loc.isMacroID()) 388 return false; 389 if (SM.isInSystemHeader(Loc)) 390 return true; // always skip bodies from system headers. 391 392 FileID FID; 393 unsigned Offset; 394 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); 395 // Don't skip bodies from main files; this may be revisited. 396 if (SM.getMainFileID() == FID) 397 return false; 398 const FileEntry *FE = SM.getFileEntryForID(FID); 399 if (!FE) 400 return false; 401 402 return ParsedLocsTracker->hasAlredyBeenParsed(Loc, FID, FE); 403 } 404 405 TranslationUnitKind getTranslationUnitKind() override { 406 if (DataConsumer->shouldIndexImplicitTemplateInsts()) 407 return TU_Complete; 408 else 409 return TU_Prefix; 410 } 411 bool hasCodeCompletionSupport() const override { return false; } 412 413 void EndSourceFileAction() override { 414 if (ParsedLocsTracker) 415 ParsedLocsTracker->syncWithStorage(); 416 } 417 }; 418 419 //===----------------------------------------------------------------------===// 420 // clang_indexSourceFileUnit Implementation 421 //===----------------------------------------------------------------------===// 422 423 static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) { 424 IndexingOptions IdxOpts; 425 if (index_options & CXIndexOpt_IndexFunctionLocalSymbols) 426 IdxOpts.IndexFunctionLocals = true; 427 if (index_options & CXIndexOpt_IndexImplicitTemplateInstantiations) 428 IdxOpts.IndexImplicitInstantiation = true; 429 return IdxOpts; 430 } 431 432 struct IndexSessionData { 433 CXIndex CIdx; 434 std::unique_ptr<ThreadSafeParsedRegions> SkipBodyData = 435 std::make_unique<ThreadSafeParsedRegions>(); 436 437 explicit IndexSessionData(CXIndex cIdx) : CIdx(cIdx) {} 438 }; 439 440 } // anonymous namespace 441 442 static CXErrorCode clang_indexSourceFile_Impl( 443 CXIndexAction cxIdxAction, CXClientData client_data, 444 IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, 445 unsigned index_options, const char *source_filename, 446 const char *const *command_line_args, int num_command_line_args, 447 ArrayRef<CXUnsavedFile> unsaved_files, CXTranslationUnit *out_TU, 448 unsigned TU_options) { 449 if (out_TU) 450 *out_TU = nullptr; 451 bool requestedToGetTU = (out_TU != nullptr); 452 453 if (!cxIdxAction) { 454 return CXError_InvalidArguments; 455 } 456 if (!client_index_callbacks || index_callbacks_size == 0) { 457 return CXError_InvalidArguments; 458 } 459 460 IndexerCallbacks CB; 461 memset(&CB, 0, sizeof(CB)); 462 unsigned ClientCBSize = index_callbacks_size < sizeof(CB) 463 ? index_callbacks_size : sizeof(CB); 464 memcpy(&CB, client_index_callbacks, ClientCBSize); 465 466 IndexSessionData *IdxSession = static_cast<IndexSessionData *>(cxIdxAction); 467 CIndexer *CXXIdx = static_cast<CIndexer *>(IdxSession->CIdx); 468 469 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) 470 setThreadBackgroundPriority(); 471 472 CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::All; 473 if (TU_options & CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles) 474 CaptureDiagnostics = CaptureDiagsKind::AllWithoutNonErrorsFromIncludes; 475 if (Logger::isLoggingEnabled()) 476 CaptureDiagnostics = CaptureDiagsKind::None; 477 478 CaptureDiagnosticConsumer *CaptureDiag = nullptr; 479 if (CaptureDiagnostics != CaptureDiagsKind::None) 480 CaptureDiag = new CaptureDiagnosticConsumer(); 481 482 // Configure the diagnostics. 483 IntrusiveRefCntPtr<DiagnosticsEngine> 484 Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions, 485 CaptureDiag, 486 /*ShouldOwnClient=*/true)); 487 488 // Recover resources if we crash before exiting this function. 489 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, 490 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > 491 DiagCleanup(Diags.get()); 492 493 std::unique_ptr<std::vector<const char *>> Args( 494 new std::vector<const char *>()); 495 496 // Recover resources if we crash before exiting this method. 497 llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> > 498 ArgsCleanup(Args.get()); 499 500 Args->insert(Args->end(), command_line_args, 501 command_line_args + num_command_line_args); 502 503 // The 'source_filename' argument is optional. If the caller does not 504 // specify it then it is assumed that the source file is specified 505 // in the actual argument list. 506 // Put the source file after command_line_args otherwise if '-x' flag is 507 // present it will be unused. 508 if (source_filename) 509 Args->push_back(source_filename); 510 511 CreateInvocationOptions CIOpts; 512 CIOpts.Diags = Diags; 513 CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed? 514 std::shared_ptr<CompilerInvocation> CInvok = 515 createInvocation(*Args, std::move(CIOpts)); 516 517 if (!CInvok) 518 return CXError_Failure; 519 520 // Recover resources if we crash before exiting this function. 521 llvm::CrashRecoveryContextCleanupRegistrar< 522 std::shared_ptr<CompilerInvocation>, 523 llvm::CrashRecoveryContextDestructorCleanup< 524 std::shared_ptr<CompilerInvocation>>> 525 CInvokCleanup(&CInvok); 526 527 if (CInvok->getFrontendOpts().Inputs.empty()) 528 return CXError_Failure; 529 530 typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner; 531 std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner); 532 533 // Recover resources if we crash before exiting this method. 534 llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup( 535 BufOwner.get()); 536 537 for (auto &UF : unsaved_files) { 538 std::unique_ptr<llvm::MemoryBuffer> MB = 539 llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); 540 CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get()); 541 BufOwner->push_back(std::move(MB)); 542 } 543 544 // Since libclang is primarily used by batch tools dealing with 545 // (often very broken) source code, where spell-checking can have a 546 // significant negative impact on performance (particularly when 547 // precompiled headers are involved), we disable it. 548 CInvok->getLangOpts()->SpellChecking = false; 549 550 if (index_options & CXIndexOpt_SuppressWarnings) 551 CInvok->getDiagnosticOpts().IgnoreWarnings = true; 552 553 // Make sure to use the raw module format. 554 CInvok->getHeaderSearchOpts().ModuleFormat = std::string( 555 CXXIdx->getPCHContainerOperations()->getRawReader().getFormat()); 556 557 auto Unit = ASTUnit::create(CInvok, Diags, CaptureDiagnostics, 558 /*UserFilesAreVolatile=*/true); 559 if (!Unit) 560 return CXError_InvalidArguments; 561 562 auto *UPtr = Unit.get(); 563 std::unique_ptr<CXTUOwner> CXTU( 564 new CXTUOwner(MakeCXTranslationUnit(CXXIdx, std::move(Unit)))); 565 566 // Recover resources if we crash before exiting this method. 567 llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner> 568 CXTUCleanup(CXTU.get()); 569 570 // Enable the skip-parsed-bodies optimization only for C++; this may be 571 // revisited. 572 bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) && 573 CInvok->getLangOpts()->CPlusPlus; 574 if (SkipBodies) 575 CInvok->getFrontendOpts().SkipFunctionBodies = true; 576 577 auto DataConsumer = 578 std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options, 579 CXTU->getTU()); 580 auto IndexAction = std::make_unique<IndexingFrontendAction>( 581 DataConsumer, getIndexingOptionsFromCXOptions(index_options), 582 SkipBodies ? IdxSession->SkipBodyData.get() : nullptr); 583 584 // Recover resources if we crash before exiting this method. 585 llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction> 586 IndexActionCleanup(IndexAction.get()); 587 588 bool Persistent = requestedToGetTU; 589 bool OnlyLocalDecls = false; 590 bool PrecompilePreamble = false; 591 bool CreatePreambleOnFirstParse = false; 592 bool CacheCodeCompletionResults = false; 593 PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); 594 PPOpts.AllowPCHWithCompilerErrors = true; 595 596 if (requestedToGetTU) { 597 OnlyLocalDecls = CXXIdx->getOnlyLocalDecls(); 598 PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble; 599 CreatePreambleOnFirstParse = 600 TU_options & CXTranslationUnit_CreatePreambleOnFirstParse; 601 // FIXME: Add a flag for modules. 602 CacheCodeCompletionResults 603 = TU_options & CXTranslationUnit_CacheCompletionResults; 604 } 605 606 if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) { 607 PPOpts.DetailedRecord = true; 608 } 609 610 if (!requestedToGetTU && !CInvok->getLangOpts()->Modules) 611 PPOpts.DetailedRecord = false; 612 613 // Unless the user specified that they want the preamble on the first parse 614 // set it up to be created on the first reparse. This makes the first parse 615 // faster, trading for a slower (first) reparse. 616 unsigned PrecompilePreambleAfterNParses = 617 !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse; 618 DiagnosticErrorTrap DiagTrap(*Diags); 619 bool Success = ASTUnit::LoadFromCompilerInvocationAction( 620 std::move(CInvok), CXXIdx->getPCHContainerOperations(), Diags, 621 IndexAction.get(), UPtr, Persistent, CXXIdx->getClangResourcesPath(), 622 OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses, 623 CacheCodeCompletionResults, /*UserFilesAreVolatile=*/true); 624 if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics()) 625 printDiagsToStderr(UPtr); 626 627 if (isASTReadError(UPtr)) 628 return CXError_ASTReadError; 629 630 if (!Success) 631 return CXError_Failure; 632 633 if (out_TU) 634 *out_TU = CXTU->takeTU(); 635 636 return CXError_Success; 637 } 638 639 //===----------------------------------------------------------------------===// 640 // clang_indexTranslationUnit Implementation 641 //===----------------------------------------------------------------------===// 642 643 static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) { 644 Preprocessor &PP = Unit.getPreprocessor(); 645 if (!PP.getPreprocessingRecord()) 646 return; 647 648 // FIXME: Only deserialize inclusion directives. 649 650 bool isModuleFile = Unit.isModuleFile(); 651 for (PreprocessedEntity *PPE : Unit.getLocalPreprocessingEntities()) { 652 if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) { 653 SourceLocation Loc = ID->getSourceRange().getBegin(); 654 // Modules have synthetic main files as input, give an invalid location 655 // if the location points to such a file. 656 if (isModuleFile && Unit.isInMainFileID(Loc)) 657 Loc = SourceLocation(); 658 IdxCtx.ppIncludedFile(Loc, ID->getFileName(), 659 ID->getFile(), 660 ID->getKind() == InclusionDirective::Import, 661 !ID->wasInQuotes(), ID->importedModule()); 662 } 663 } 664 } 665 666 static CXErrorCode clang_indexTranslationUnit_Impl( 667 CXIndexAction idxAction, CXClientData client_data, 668 IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, 669 unsigned index_options, CXTranslationUnit TU) { 670 // Check arguments. 671 if (isNotUsableTU(TU)) { 672 LOG_BAD_TU(TU); 673 return CXError_InvalidArguments; 674 } 675 if (!client_index_callbacks || index_callbacks_size == 0) { 676 return CXError_InvalidArguments; 677 } 678 679 CIndexer *CXXIdx = TU->CIdx; 680 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) 681 setThreadBackgroundPriority(); 682 683 IndexerCallbacks CB; 684 memset(&CB, 0, sizeof(CB)); 685 unsigned ClientCBSize = index_callbacks_size < sizeof(CB) 686 ? index_callbacks_size : sizeof(CB); 687 memcpy(&CB, client_index_callbacks, ClientCBSize); 688 689 CXIndexDataConsumer DataConsumer(client_data, CB, index_options, TU); 690 691 ASTUnit *Unit = cxtu::getASTUnit(TU); 692 if (!Unit) 693 return CXError_Failure; 694 695 ASTUnit::ConcurrencyCheck Check(*Unit); 696 697 if (const FileEntry *PCHFile = Unit->getPCHFile()) 698 DataConsumer.importedPCH(PCHFile); 699 700 FileManager &FileMgr = Unit->getFileManager(); 701 702 if (Unit->getOriginalSourceFileName().empty()) 703 DataConsumer.enteredMainFile(nullptr); 704 else if (auto MainFile = FileMgr.getFile(Unit->getOriginalSourceFileName())) 705 DataConsumer.enteredMainFile(*MainFile); 706 else 707 DataConsumer.enteredMainFile(nullptr); 708 709 DataConsumer.setASTContext(Unit->getASTContext()); 710 DataConsumer.startedTranslationUnit(); 711 712 indexPreprocessingRecord(*Unit, DataConsumer); 713 indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options)); 714 DataConsumer.indexDiagnostics(); 715 716 return CXError_Success; 717 } 718 719 //===----------------------------------------------------------------------===// 720 // libclang public APIs. 721 //===----------------------------------------------------------------------===// 722 723 int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) { 724 return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory; 725 } 726 727 const CXIdxObjCContainerDeclInfo * 728 clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) { 729 if (!DInfo) 730 return nullptr; 731 732 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 733 if (const ObjCContainerDeclInfo * 734 ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI)) 735 return &ContInfo->ObjCContDeclInfo; 736 737 return nullptr; 738 } 739 740 const CXIdxObjCInterfaceDeclInfo * 741 clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) { 742 if (!DInfo) 743 return nullptr; 744 745 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 746 if (const ObjCInterfaceDeclInfo * 747 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 748 return &InterInfo->ObjCInterDeclInfo; 749 750 return nullptr; 751 } 752 753 const CXIdxObjCCategoryDeclInfo * 754 clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){ 755 if (!DInfo) 756 return nullptr; 757 758 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 759 if (const ObjCCategoryDeclInfo * 760 CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 761 return &CatInfo->ObjCCatDeclInfo; 762 763 return nullptr; 764 } 765 766 const CXIdxObjCProtocolRefListInfo * 767 clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) { 768 if (!DInfo) 769 return nullptr; 770 771 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 772 773 if (const ObjCInterfaceDeclInfo * 774 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 775 return InterInfo->ObjCInterDeclInfo.protocols; 776 777 if (const ObjCProtocolDeclInfo * 778 ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI)) 779 return &ProtInfo->ObjCProtoRefListInfo; 780 781 if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 782 return CatInfo->ObjCCatDeclInfo.protocols; 783 784 return nullptr; 785 } 786 787 const CXIdxObjCPropertyDeclInfo * 788 clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) { 789 if (!DInfo) 790 return nullptr; 791 792 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 793 if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI)) 794 return &PropInfo->ObjCPropDeclInfo; 795 796 return nullptr; 797 } 798 799 const CXIdxIBOutletCollectionAttrInfo * 800 clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) { 801 if (!AInfo) 802 return nullptr; 803 804 const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo); 805 if (const IBOutletCollectionInfo * 806 IBInfo = dyn_cast<IBOutletCollectionInfo>(DI)) 807 return &IBInfo->IBCollInfo; 808 809 return nullptr; 810 } 811 812 const CXIdxCXXClassDeclInfo * 813 clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) { 814 if (!DInfo) 815 return nullptr; 816 817 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 818 if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI)) 819 return &ClassInfo->CXXClassInfo; 820 821 return nullptr; 822 } 823 824 CXIdxClientContainer 825 clang_index_getClientContainer(const CXIdxContainerInfo *info) { 826 if (!info) 827 return nullptr; 828 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 829 return Container->IndexCtx->getClientContainerForDC(Container->DC); 830 } 831 832 void clang_index_setClientContainer(const CXIdxContainerInfo *info, 833 CXIdxClientContainer client) { 834 if (!info) 835 return; 836 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 837 Container->IndexCtx->addContainerInMap(Container->DC, client); 838 } 839 840 CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) { 841 if (!info) 842 return nullptr; 843 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 844 return Entity->IndexCtx->getClientEntity(Entity->Dcl); 845 } 846 847 void clang_index_setClientEntity(const CXIdxEntityInfo *info, 848 CXIdxClientEntity client) { 849 if (!info) 850 return; 851 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 852 Entity->IndexCtx->setClientEntity(Entity->Dcl, client); 853 } 854 855 CXIndexAction clang_IndexAction_create(CXIndex CIdx) { 856 return new IndexSessionData(CIdx); 857 } 858 859 void clang_IndexAction_dispose(CXIndexAction idxAction) { 860 if (idxAction) 861 delete static_cast<IndexSessionData *>(idxAction); 862 } 863 864 int clang_indexSourceFile(CXIndexAction idxAction, 865 CXClientData client_data, 866 IndexerCallbacks *index_callbacks, 867 unsigned index_callbacks_size, 868 unsigned index_options, 869 const char *source_filename, 870 const char * const *command_line_args, 871 int num_command_line_args, 872 struct CXUnsavedFile *unsaved_files, 873 unsigned num_unsaved_files, 874 CXTranslationUnit *out_TU, 875 unsigned TU_options) { 876 SmallVector<const char *, 4> Args; 877 Args.push_back("clang"); 878 Args.append(command_line_args, command_line_args + num_command_line_args); 879 return clang_indexSourceFileFullArgv( 880 idxAction, client_data, index_callbacks, index_callbacks_size, 881 index_options, source_filename, Args.data(), Args.size(), unsaved_files, 882 num_unsaved_files, out_TU, TU_options); 883 } 884 885 int clang_indexSourceFileFullArgv( 886 CXIndexAction idxAction, CXClientData client_data, 887 IndexerCallbacks *index_callbacks, unsigned index_callbacks_size, 888 unsigned index_options, const char *source_filename, 889 const char *const *command_line_args, int num_command_line_args, 890 struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files, 891 CXTranslationUnit *out_TU, unsigned TU_options) { 892 LOG_FUNC_SECTION { 893 *Log << source_filename << ": "; 894 for (int i = 0; i != num_command_line_args; ++i) 895 *Log << command_line_args[i] << " "; 896 } 897 898 if (num_unsaved_files && !unsaved_files) 899 return CXError_InvalidArguments; 900 901 CXErrorCode result = CXError_Failure; 902 auto IndexSourceFileImpl = [=, &result]() { 903 result = clang_indexSourceFile_Impl( 904 idxAction, client_data, index_callbacks, index_callbacks_size, 905 index_options, source_filename, command_line_args, 906 num_command_line_args, llvm::ArrayRef(unsaved_files, num_unsaved_files), 907 out_TU, TU_options); 908 }; 909 910 llvm::CrashRecoveryContext CRC; 911 912 if (!RunSafely(CRC, IndexSourceFileImpl)) { 913 fprintf(stderr, "libclang: crash detected during indexing source file: {\n"); 914 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename); 915 fprintf(stderr, " 'command_line_args' : ["); 916 for (int i = 0; i != num_command_line_args; ++i) { 917 if (i) 918 fprintf(stderr, ", "); 919 fprintf(stderr, "'%s'", command_line_args[i]); 920 } 921 fprintf(stderr, "],\n"); 922 fprintf(stderr, " 'unsaved_files' : ["); 923 for (unsigned i = 0; i != num_unsaved_files; ++i) { 924 if (i) 925 fprintf(stderr, ", "); 926 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename, 927 unsaved_files[i].Length); 928 } 929 fprintf(stderr, "],\n"); 930 fprintf(stderr, " 'options' : %d,\n", TU_options); 931 fprintf(stderr, "}\n"); 932 933 return 1; 934 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) { 935 if (out_TU) 936 PrintLibclangResourceUsage(*out_TU); 937 } 938 939 return result; 940 } 941 942 int clang_indexTranslationUnit(CXIndexAction idxAction, 943 CXClientData client_data, 944 IndexerCallbacks *index_callbacks, 945 unsigned index_callbacks_size, 946 unsigned index_options, 947 CXTranslationUnit TU) { 948 LOG_FUNC_SECTION { 949 *Log << TU; 950 } 951 952 CXErrorCode result; 953 auto IndexTranslationUnitImpl = [=, &result]() { 954 result = clang_indexTranslationUnit_Impl( 955 idxAction, client_data, index_callbacks, index_callbacks_size, 956 index_options, TU); 957 }; 958 959 llvm::CrashRecoveryContext CRC; 960 961 if (!RunSafely(CRC, IndexTranslationUnitImpl)) { 962 fprintf(stderr, "libclang: crash detected during indexing TU\n"); 963 964 return 1; 965 } 966 967 return result; 968 } 969 970 void clang_indexLoc_getFileLocation(CXIdxLoc location, 971 CXIdxClientFile *indexFile, 972 CXFile *file, 973 unsigned *line, 974 unsigned *column, 975 unsigned *offset) { 976 if (indexFile) *indexFile = nullptr; 977 if (file) *file = nullptr; 978 if (line) *line = 0; 979 if (column) *column = 0; 980 if (offset) *offset = 0; 981 982 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 983 if (!location.ptr_data[0] || Loc.isInvalid()) 984 return; 985 986 CXIndexDataConsumer &DataConsumer = 987 *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]); 988 DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset); 989 } 990 991 CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { 992 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 993 if (!location.ptr_data[0] || Loc.isInvalid()) 994 return clang_getNullLocation(); 995 996 CXIndexDataConsumer &DataConsumer = 997 *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]); 998 return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc); 999 } 1000