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 "llvm/Support/VirtualFileSystem.h" 33 #include <cstdio> 34 #include <mutex> 35 #include <utility> 36 37 using namespace clang; 38 using namespace clang::index; 39 using namespace cxtu; 40 using namespace cxindex; 41 42 namespace { 43 44 //===----------------------------------------------------------------------===// 45 // Skip Parsed Bodies 46 //===----------------------------------------------------------------------===// 47 48 /// A "region" in source code identified by the file/offset of the 49 /// preprocessor conditional directive that it belongs to. 50 /// Multiple, non-consecutive ranges can be parts of the same region. 51 /// 52 /// As an example of different regions separated by preprocessor directives: 53 /// 54 /// \code 55 /// #1 56 /// #ifdef BLAH 57 /// #2 58 /// #ifdef CAKE 59 /// #3 60 /// #endif 61 /// #2 62 /// #endif 63 /// #1 64 /// \endcode 65 /// 66 /// There are 3 regions, with non-consecutive parts: 67 /// #1 is identified as the beginning of the file 68 /// #2 is identified as the location of "#ifdef BLAH" 69 /// #3 is identified as the location of "#ifdef CAKE" 70 /// 71 class PPRegion { 72 llvm::sys::fs::UniqueID UniqueID; 73 time_t ModTime; 74 unsigned Offset; 75 public: 76 PPRegion() : UniqueID(0, 0), ModTime(), Offset() {} 77 PPRegion(llvm::sys::fs::UniqueID UniqueID, unsigned offset, time_t modTime) 78 : UniqueID(UniqueID), ModTime(modTime), Offset(offset) {} 79 80 const llvm::sys::fs::UniqueID &getUniqueID() const { return UniqueID; } 81 unsigned getOffset() const { return Offset; } 82 time_t getModTime() const { return ModTime; } 83 84 bool isInvalid() const { return *this == PPRegion(); } 85 86 friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) { 87 return lhs.UniqueID == rhs.UniqueID && lhs.Offset == rhs.Offset && 88 lhs.ModTime == rhs.ModTime; 89 } 90 }; 91 92 } // end anonymous namespace 93 94 namespace llvm { 95 96 template <> 97 struct DenseMapInfo<PPRegion> { 98 static inline PPRegion getEmptyKey() { 99 return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-1), 0); 100 } 101 static inline PPRegion getTombstoneKey() { 102 return PPRegion(llvm::sys::fs::UniqueID(0, 0), unsigned(-2), 0); 103 } 104 105 static unsigned getHashValue(const PPRegion &S) { 106 llvm::FoldingSetNodeID ID; 107 const llvm::sys::fs::UniqueID &UniqueID = S.getUniqueID(); 108 ID.AddInteger(UniqueID.getFile()); 109 ID.AddInteger(UniqueID.getDevice()); 110 ID.AddInteger(S.getOffset()); 111 ID.AddInteger(S.getModTime()); 112 return ID.ComputeHash(); 113 } 114 115 static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) { 116 return LHS == RHS; 117 } 118 }; 119 } 120 121 namespace { 122 123 /// Keeps track of function bodies that have already been parsed. 124 /// 125 /// Is thread-safe. 126 class ThreadSafeParsedRegions { 127 mutable std::mutex Mutex; 128 llvm::DenseSet<PPRegion> ParsedRegions; 129 130 public: 131 ~ThreadSafeParsedRegions() = default; 132 133 llvm::DenseSet<PPRegion> getParsedRegions() const { 134 std::lock_guard<std::mutex> MG(Mutex); 135 return ParsedRegions; 136 } 137 138 void addParsedRegions(ArrayRef<PPRegion> Regions) { 139 std::lock_guard<std::mutex> MG(Mutex); 140 ParsedRegions.insert(Regions.begin(), Regions.end()); 141 } 142 }; 143 144 /// Provides information whether source locations have already been parsed in 145 /// another FrontendAction. 146 /// 147 /// Is NOT thread-safe. 148 class ParsedSrcLocationsTracker { 149 ThreadSafeParsedRegions &ParsedRegionsStorage; 150 PPConditionalDirectiveRecord &PPRec; 151 Preprocessor &PP; 152 153 /// Snapshot of the shared state at the point when this instance was 154 /// constructed. 155 llvm::DenseSet<PPRegion> ParsedRegionsSnapshot; 156 /// Regions that were queried during this instance lifetime. 157 SmallVector<PPRegion, 32> NewParsedRegions; 158 159 /// Caching the last queried region. 160 PPRegion LastRegion; 161 bool LastIsParsed; 162 163 public: 164 /// Creates snapshot of \p ParsedRegionsStorage. 165 ParsedSrcLocationsTracker(ThreadSafeParsedRegions &ParsedRegionsStorage, 166 PPConditionalDirectiveRecord &ppRec, 167 Preprocessor &pp) 168 : ParsedRegionsStorage(ParsedRegionsStorage), PPRec(ppRec), PP(pp), 169 ParsedRegionsSnapshot(ParsedRegionsStorage.getParsedRegions()) {} 170 171 /// \returns true iff \p Loc has already been parsed. 172 /// 173 /// Can provide false-negative in case the location was parsed after this 174 /// instance had been constructed. 175 bool hasAlredyBeenParsed(SourceLocation Loc, FileID FID, FileEntryRef FE) { 176 PPRegion region = getRegion(Loc, FID, FE); 177 if (region.isInvalid()) 178 return false; 179 180 // Check common case, consecutive functions in the same region. 181 if (LastRegion == region) 182 return LastIsParsed; 183 184 LastRegion = region; 185 // Source locations can't be revisited during single TU parsing. 186 // That means if we hit the same region again, it's a different location in 187 // the same region and so the "is parsed" value from the snapshot is still 188 // correct. 189 LastIsParsed = ParsedRegionsSnapshot.count(region); 190 if (!LastIsParsed) 191 NewParsedRegions.emplace_back(std::move(region)); 192 return LastIsParsed; 193 } 194 195 /// Updates ParsedRegionsStorage with newly parsed regions. 196 void syncWithStorage() { 197 ParsedRegionsStorage.addParsedRegions(NewParsedRegions); 198 } 199 200 private: 201 PPRegion getRegion(SourceLocation Loc, FileID FID, FileEntryRef FE) { 202 auto Bail = [this, FE]() { 203 if (isParsedOnceInclude(FE)) { 204 const llvm::sys::fs::UniqueID &ID = FE.getUniqueID(); 205 return PPRegion(ID, 0, FE.getModificationTime()); 206 } 207 return PPRegion(); 208 }; 209 210 SourceLocation RegionLoc = PPRec.findConditionalDirectiveRegionLoc(Loc); 211 assert(RegionLoc.isFileID()); 212 if (RegionLoc.isInvalid()) 213 return Bail(); 214 215 FileID RegionFID; 216 unsigned RegionOffset; 217 std::tie(RegionFID, RegionOffset) = 218 PPRec.getSourceManager().getDecomposedLoc(RegionLoc); 219 220 if (RegionFID != FID) 221 return Bail(); 222 223 const llvm::sys::fs::UniqueID &ID = FE.getUniqueID(); 224 return PPRegion(ID, RegionOffset, FE.getModificationTime()); 225 } 226 227 bool isParsedOnceInclude(FileEntryRef FE) { 228 return PP.getHeaderSearchInfo().isFileMultipleIncludeGuarded(FE) || 229 PP.getHeaderSearchInfo().hasFileBeenImported(FE); 230 } 231 }; 232 233 //===----------------------------------------------------------------------===// 234 // IndexPPCallbacks 235 //===----------------------------------------------------------------------===// 236 237 class IndexPPCallbacks : public PPCallbacks { 238 Preprocessor &PP; 239 CXIndexDataConsumer &DataConsumer; 240 bool IsMainFileEntered; 241 242 public: 243 IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer) 244 : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { } 245 246 void FileChanged(SourceLocation Loc, FileChangeReason Reason, 247 SrcMgr::CharacteristicKind FileType, FileID PrevFID) override { 248 if (IsMainFileEntered) 249 return; 250 251 SourceManager &SM = PP.getSourceManager(); 252 SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID()); 253 254 if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) { 255 IsMainFileEntered = true; 256 DataConsumer.enteredMainFile( 257 *SM.getFileEntryRefForID(SM.getMainFileID())); 258 } 259 } 260 261 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, 262 StringRef FileName, bool IsAngled, 263 CharSourceRange FilenameRange, 264 OptionalFileEntryRef File, StringRef SearchPath, 265 StringRef RelativePath, const Module *SuggestedModule, 266 bool ModuleImported, 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 ModuleImported); 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 if (auto File = 354 CI.getFileManager().getOptionalFileRef(PPOpts.ImplicitPCHInclude)) 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 OptionalFileEntryRef FE = SM.getFileEntryRefForID(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> Diags( 484 CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(), 485 new DiagnosticOptions, 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().getFormats().front()); 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 (OptionalFileEntryRef PCHFile = Unit->getPCHFile()) 698 DataConsumer.importedPCH(*PCHFile); 699 700 FileManager &FileMgr = Unit->getFileManager(); 701 702 if (Unit->getOriginalSourceFileName().empty()) 703 DataConsumer.enteredMainFile(std::nullopt); 704 else if (auto MainFile = 705 FileMgr.getFileRef(Unit->getOriginalSourceFileName())) 706 DataConsumer.enteredMainFile(*MainFile); 707 else 708 DataConsumer.enteredMainFile(std::nullopt); 709 710 DataConsumer.setASTContext(Unit->getASTContext()); 711 DataConsumer.startedTranslationUnit(); 712 713 indexPreprocessingRecord(*Unit, DataConsumer); 714 indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options)); 715 DataConsumer.indexDiagnostics(); 716 717 return CXError_Success; 718 } 719 720 //===----------------------------------------------------------------------===// 721 // libclang public APIs. 722 //===----------------------------------------------------------------------===// 723 724 int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) { 725 return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory; 726 } 727 728 const CXIdxObjCContainerDeclInfo * 729 clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) { 730 if (!DInfo) 731 return nullptr; 732 733 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 734 if (const ObjCContainerDeclInfo * 735 ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI)) 736 return &ContInfo->ObjCContDeclInfo; 737 738 return nullptr; 739 } 740 741 const CXIdxObjCInterfaceDeclInfo * 742 clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) { 743 if (!DInfo) 744 return nullptr; 745 746 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 747 if (const ObjCInterfaceDeclInfo * 748 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 749 return &InterInfo->ObjCInterDeclInfo; 750 751 return nullptr; 752 } 753 754 const CXIdxObjCCategoryDeclInfo * 755 clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){ 756 if (!DInfo) 757 return nullptr; 758 759 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 760 if (const ObjCCategoryDeclInfo * 761 CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 762 return &CatInfo->ObjCCatDeclInfo; 763 764 return nullptr; 765 } 766 767 const CXIdxObjCProtocolRefListInfo * 768 clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) { 769 if (!DInfo) 770 return nullptr; 771 772 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 773 774 if (const ObjCInterfaceDeclInfo * 775 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 776 return InterInfo->ObjCInterDeclInfo.protocols; 777 778 if (const ObjCProtocolDeclInfo * 779 ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI)) 780 return &ProtInfo->ObjCProtoRefListInfo; 781 782 if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 783 return CatInfo->ObjCCatDeclInfo.protocols; 784 785 return nullptr; 786 } 787 788 const CXIdxObjCPropertyDeclInfo * 789 clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) { 790 if (!DInfo) 791 return nullptr; 792 793 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 794 if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI)) 795 return &PropInfo->ObjCPropDeclInfo; 796 797 return nullptr; 798 } 799 800 const CXIdxIBOutletCollectionAttrInfo * 801 clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) { 802 if (!AInfo) 803 return nullptr; 804 805 const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo); 806 if (const IBOutletCollectionInfo * 807 IBInfo = dyn_cast<IBOutletCollectionInfo>(DI)) 808 return &IBInfo->IBCollInfo; 809 810 return nullptr; 811 } 812 813 const CXIdxCXXClassDeclInfo * 814 clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) { 815 if (!DInfo) 816 return nullptr; 817 818 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 819 if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI)) 820 return &ClassInfo->CXXClassInfo; 821 822 return nullptr; 823 } 824 825 CXIdxClientContainer 826 clang_index_getClientContainer(const CXIdxContainerInfo *info) { 827 if (!info) 828 return nullptr; 829 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 830 return Container->IndexCtx->getClientContainerForDC(Container->DC); 831 } 832 833 void clang_index_setClientContainer(const CXIdxContainerInfo *info, 834 CXIdxClientContainer client) { 835 if (!info) 836 return; 837 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 838 Container->IndexCtx->addContainerInMap(Container->DC, client); 839 } 840 841 CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) { 842 if (!info) 843 return nullptr; 844 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 845 return Entity->IndexCtx->getClientEntity(Entity->Dcl); 846 } 847 848 void clang_index_setClientEntity(const CXIdxEntityInfo *info, 849 CXIdxClientEntity client) { 850 if (!info) 851 return; 852 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 853 Entity->IndexCtx->setClientEntity(Entity->Dcl, client); 854 } 855 856 CXIndexAction clang_IndexAction_create(CXIndex CIdx) { 857 return new IndexSessionData(CIdx); 858 } 859 860 void clang_IndexAction_dispose(CXIndexAction idxAction) { 861 if (idxAction) 862 delete static_cast<IndexSessionData *>(idxAction); 863 } 864 865 int clang_indexSourceFile(CXIndexAction idxAction, 866 CXClientData client_data, 867 IndexerCallbacks *index_callbacks, 868 unsigned index_callbacks_size, 869 unsigned index_options, 870 const char *source_filename, 871 const char * const *command_line_args, 872 int num_command_line_args, 873 struct CXUnsavedFile *unsaved_files, 874 unsigned num_unsaved_files, 875 CXTranslationUnit *out_TU, 876 unsigned TU_options) { 877 SmallVector<const char *, 4> Args; 878 Args.push_back("clang"); 879 Args.append(command_line_args, command_line_args + num_command_line_args); 880 return clang_indexSourceFileFullArgv( 881 idxAction, client_data, index_callbacks, index_callbacks_size, 882 index_options, source_filename, Args.data(), Args.size(), unsaved_files, 883 num_unsaved_files, out_TU, TU_options); 884 } 885 886 int clang_indexSourceFileFullArgv( 887 CXIndexAction idxAction, CXClientData client_data, 888 IndexerCallbacks *index_callbacks, unsigned index_callbacks_size, 889 unsigned index_options, const char *source_filename, 890 const char *const *command_line_args, int num_command_line_args, 891 struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files, 892 CXTranslationUnit *out_TU, unsigned TU_options) { 893 LOG_FUNC_SECTION { 894 *Log << source_filename << ": "; 895 for (int i = 0; i != num_command_line_args; ++i) 896 *Log << command_line_args[i] << " "; 897 } 898 899 if (num_unsaved_files && !unsaved_files) 900 return CXError_InvalidArguments; 901 902 CXErrorCode result = CXError_Failure; 903 auto IndexSourceFileImpl = [=, &result]() { 904 result = clang_indexSourceFile_Impl( 905 idxAction, client_data, index_callbacks, index_callbacks_size, 906 index_options, source_filename, command_line_args, 907 num_command_line_args, llvm::ArrayRef(unsaved_files, num_unsaved_files), 908 out_TU, TU_options); 909 }; 910 911 llvm::CrashRecoveryContext CRC; 912 913 if (!RunSafely(CRC, IndexSourceFileImpl)) { 914 fprintf(stderr, "libclang: crash detected during indexing source file: {\n"); 915 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename); 916 fprintf(stderr, " 'command_line_args' : ["); 917 for (int i = 0; i != num_command_line_args; ++i) { 918 if (i) 919 fprintf(stderr, ", "); 920 fprintf(stderr, "'%s'", command_line_args[i]); 921 } 922 fprintf(stderr, "],\n"); 923 fprintf(stderr, " 'unsaved_files' : ["); 924 for (unsigned i = 0; i != num_unsaved_files; ++i) { 925 if (i) 926 fprintf(stderr, ", "); 927 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename, 928 unsaved_files[i].Length); 929 } 930 fprintf(stderr, "],\n"); 931 fprintf(stderr, " 'options' : %d,\n", TU_options); 932 fprintf(stderr, "}\n"); 933 934 return 1; 935 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) { 936 if (out_TU) 937 PrintLibclangResourceUsage(*out_TU); 938 } 939 940 return result; 941 } 942 943 int clang_indexTranslationUnit(CXIndexAction idxAction, 944 CXClientData client_data, 945 IndexerCallbacks *index_callbacks, 946 unsigned index_callbacks_size, 947 unsigned index_options, 948 CXTranslationUnit TU) { 949 LOG_FUNC_SECTION { 950 *Log << TU; 951 } 952 953 CXErrorCode result; 954 auto IndexTranslationUnitImpl = [=, &result]() { 955 result = clang_indexTranslationUnit_Impl( 956 idxAction, client_data, index_callbacks, index_callbacks_size, 957 index_options, TU); 958 }; 959 960 llvm::CrashRecoveryContext CRC; 961 962 if (!RunSafely(CRC, IndexTranslationUnitImpl)) { 963 fprintf(stderr, "libclang: crash detected during indexing TU\n"); 964 965 return 1; 966 } 967 968 return result; 969 } 970 971 void clang_indexLoc_getFileLocation(CXIdxLoc location, 972 CXIdxClientFile *indexFile, 973 CXFile *file, 974 unsigned *line, 975 unsigned *column, 976 unsigned *offset) { 977 if (indexFile) *indexFile = nullptr; 978 if (file) *file = nullptr; 979 if (line) *line = 0; 980 if (column) *column = 0; 981 if (offset) *offset = 0; 982 983 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 984 if (!location.ptr_data[0] || Loc.isInvalid()) 985 return; 986 987 CXIndexDataConsumer &DataConsumer = 988 *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]); 989 DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset); 990 } 991 992 CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { 993 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 994 if (!location.ptr_data[0] || Loc.isInvalid()) 995 return clang_getNullLocation(); 996 997 CXIndexDataConsumer &DataConsumer = 998 *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]); 999 return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc); 1000 } 1001