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 } 232 }; 233 234 //===----------------------------------------------------------------------===// 235 // IndexPPCallbacks 236 //===----------------------------------------------------------------------===// 237 238 class IndexPPCallbacks : public PPCallbacks { 239 Preprocessor &PP; 240 CXIndexDataConsumer &DataConsumer; 241 bool IsMainFileEntered; 242 243 public: 244 IndexPPCallbacks(Preprocessor &PP, CXIndexDataConsumer &dataConsumer) 245 : PP(PP), DataConsumer(dataConsumer), IsMainFileEntered(false) { } 246 247 void FileChanged(SourceLocation Loc, FileChangeReason Reason, 248 SrcMgr::CharacteristicKind FileType, FileID PrevFID) override { 249 if (IsMainFileEntered) 250 return; 251 252 SourceManager &SM = PP.getSourceManager(); 253 SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID()); 254 255 if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) { 256 IsMainFileEntered = true; 257 DataConsumer.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID())); 258 } 259 } 260 261 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, 262 StringRef FileName, bool IsAngled, 263 CharSourceRange FilenameRange, const FileEntry *File, 264 StringRef SearchPath, StringRef RelativePath, 265 const Module *Imported, 266 SrcMgr::CharacteristicKind FileType) override { 267 bool isImport = (IncludeTok.is(tok::identifier) && 268 IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import); 269 DataConsumer.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled, 270 Imported); 271 } 272 273 /// MacroDefined - This hook is called whenever a macro definition is seen. 274 void MacroDefined(const Token &Id, const MacroDirective *MD) override {} 275 276 /// MacroUndefined - This hook is called whenever a macro #undef is seen. 277 /// MI is released immediately following this callback. 278 void MacroUndefined(const Token &MacroNameTok, 279 const MacroDefinition &MD, 280 const MacroDirective *UD) override {} 281 282 /// MacroExpands - This is called by when a macro invocation is found. 283 void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, 284 SourceRange Range, const MacroArgs *Args) override {} 285 286 /// SourceRangeSkipped - This hook is called when a source range is skipped. 287 /// \param Range The SourceRange that was skipped. The range begins at the 288 /// #if/#else directive and ends after the #endif/#else directive. 289 void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override { 290 } 291 }; 292 293 //===----------------------------------------------------------------------===// 294 // IndexingConsumer 295 //===----------------------------------------------------------------------===// 296 297 class IndexingConsumer : public ASTConsumer { 298 CXIndexDataConsumer &DataConsumer; 299 300 public: 301 IndexingConsumer(CXIndexDataConsumer &dataConsumer, 302 ParsedSrcLocationsTracker *parsedLocsTracker) 303 : DataConsumer(dataConsumer) {} 304 305 void Initialize(ASTContext &Context) override { 306 DataConsumer.setASTContext(Context); 307 DataConsumer.startedTranslationUnit(); 308 } 309 310 bool HandleTopLevelDecl(DeclGroupRef DG) override { 311 return !DataConsumer.shouldAbort(); 312 } 313 }; 314 315 //===----------------------------------------------------------------------===// 316 // CaptureDiagnosticConsumer 317 //===----------------------------------------------------------------------===// 318 319 class CaptureDiagnosticConsumer : public DiagnosticConsumer { 320 SmallVector<StoredDiagnostic, 4> Errors; 321 public: 322 323 void HandleDiagnostic(DiagnosticsEngine::Level level, 324 const Diagnostic &Info) override { 325 if (level >= DiagnosticsEngine::Error) 326 Errors.push_back(StoredDiagnostic(level, Info)); 327 } 328 }; 329 330 //===----------------------------------------------------------------------===// 331 // IndexingFrontendAction 332 //===----------------------------------------------------------------------===// 333 334 class IndexingFrontendAction : public ASTFrontendAction { 335 std::shared_ptr<CXIndexDataConsumer> DataConsumer; 336 IndexingOptions Opts; 337 338 ThreadSafeParsedRegions *SKData; 339 std::unique_ptr<ParsedSrcLocationsTracker> ParsedLocsTracker; 340 341 public: 342 IndexingFrontendAction(std::shared_ptr<CXIndexDataConsumer> dataConsumer, 343 const IndexingOptions &Opts, 344 ThreadSafeParsedRegions *skData) 345 : DataConsumer(std::move(dataConsumer)), Opts(Opts), SKData(skData) {} 346 347 std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, 348 StringRef InFile) override { 349 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 350 351 if (!PPOpts.ImplicitPCHInclude.empty()) { 352 auto File = CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude); 353 if (File) 354 DataConsumer->importedPCH(*File); 355 } 356 357 DataConsumer->setASTContext(CI.getASTContext()); 358 Preprocessor &PP = CI.getPreprocessor(); 359 PP.addPPCallbacks(std::make_unique<IndexPPCallbacks>(PP, *DataConsumer)); 360 DataConsumer->setPreprocessor(CI.getPreprocessorPtr()); 361 362 if (SKData) { 363 auto *PPRec = new PPConditionalDirectiveRecord(PP.getSourceManager()); 364 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec)); 365 ParsedLocsTracker = 366 std::make_unique<ParsedSrcLocationsTracker>(*SKData, *PPRec, PP); 367 } 368 369 std::vector<std::unique_ptr<ASTConsumer>> Consumers; 370 Consumers.push_back(std::make_unique<IndexingConsumer>( 371 *DataConsumer, ParsedLocsTracker.get())); 372 Consumers.push_back(createIndexingASTConsumer( 373 DataConsumer, Opts, CI.getPreprocessorPtr(), 374 [this](const Decl *D) { return this->shouldSkipFunctionBody(D); })); 375 return std::make_unique<MultiplexConsumer>(std::move(Consumers)); 376 } 377 378 bool shouldSkipFunctionBody(const Decl *D) { 379 if (!ParsedLocsTracker) { 380 // Always skip bodies. 381 return true; 382 } 383 384 const SourceManager &SM = D->getASTContext().getSourceManager(); 385 SourceLocation Loc = D->getLocation(); 386 if (Loc.isMacroID()) 387 return false; 388 if (SM.isInSystemHeader(Loc)) 389 return true; // always skip bodies from system headers. 390 391 FileID FID; 392 unsigned Offset; 393 std::tie(FID, Offset) = SM.getDecomposedLoc(Loc); 394 // Don't skip bodies from main files; this may be revisited. 395 if (SM.getMainFileID() == FID) 396 return false; 397 const FileEntry *FE = SM.getFileEntryForID(FID); 398 if (!FE) 399 return false; 400 401 return ParsedLocsTracker->hasAlredyBeenParsed(Loc, FID, FE); 402 } 403 404 TranslationUnitKind getTranslationUnitKind() override { 405 if (DataConsumer->shouldIndexImplicitTemplateInsts()) 406 return TU_Complete; 407 else 408 return TU_Prefix; 409 } 410 bool hasCodeCompletionSupport() const override { return false; } 411 412 void EndSourceFileAction() override { 413 if (ParsedLocsTracker) 414 ParsedLocsTracker->syncWithStorage(); 415 } 416 }; 417 418 //===----------------------------------------------------------------------===// 419 // clang_indexSourceFileUnit Implementation 420 //===----------------------------------------------------------------------===// 421 422 static IndexingOptions getIndexingOptionsFromCXOptions(unsigned index_options) { 423 IndexingOptions IdxOpts; 424 if (index_options & CXIndexOpt_IndexFunctionLocalSymbols) 425 IdxOpts.IndexFunctionLocals = true; 426 if (index_options & CXIndexOpt_IndexImplicitTemplateInstantiations) 427 IdxOpts.IndexImplicitInstantiation = true; 428 return IdxOpts; 429 } 430 431 struct IndexSessionData { 432 CXIndex CIdx; 433 std::unique_ptr<ThreadSafeParsedRegions> SkipBodyData = 434 std::make_unique<ThreadSafeParsedRegions>(); 435 436 explicit IndexSessionData(CXIndex cIdx) : CIdx(cIdx) {} 437 }; 438 439 } // anonymous namespace 440 441 static CXErrorCode clang_indexSourceFile_Impl( 442 CXIndexAction cxIdxAction, CXClientData client_data, 443 IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, 444 unsigned index_options, const char *source_filename, 445 const char *const *command_line_args, int num_command_line_args, 446 ArrayRef<CXUnsavedFile> unsaved_files, CXTranslationUnit *out_TU, 447 unsigned TU_options) { 448 if (out_TU) 449 *out_TU = nullptr; 450 bool requestedToGetTU = (out_TU != nullptr); 451 452 if (!cxIdxAction) { 453 return CXError_InvalidArguments; 454 } 455 if (!client_index_callbacks || index_callbacks_size == 0) { 456 return CXError_InvalidArguments; 457 } 458 459 IndexerCallbacks CB; 460 memset(&CB, 0, sizeof(CB)); 461 unsigned ClientCBSize = index_callbacks_size < sizeof(CB) 462 ? index_callbacks_size : sizeof(CB); 463 memcpy(&CB, client_index_callbacks, ClientCBSize); 464 465 IndexSessionData *IdxSession = static_cast<IndexSessionData *>(cxIdxAction); 466 CIndexer *CXXIdx = static_cast<CIndexer *>(IdxSession->CIdx); 467 468 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) 469 setThreadBackgroundPriority(); 470 471 CaptureDiagsKind CaptureDiagnostics = CaptureDiagsKind::All; 472 if (TU_options & CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles) 473 CaptureDiagnostics = CaptureDiagsKind::AllWithoutNonErrorsFromIncludes; 474 if (Logger::isLoggingEnabled()) 475 CaptureDiagnostics = CaptureDiagsKind::None; 476 477 CaptureDiagnosticConsumer *CaptureDiag = nullptr; 478 if (CaptureDiagnostics != CaptureDiagsKind::None) 479 CaptureDiag = new CaptureDiagnosticConsumer(); 480 481 // Configure the diagnostics. 482 IntrusiveRefCntPtr<DiagnosticsEngine> 483 Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions, 484 CaptureDiag, 485 /*ShouldOwnClient=*/true)); 486 487 // Recover resources if we crash before exiting this function. 488 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, 489 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > 490 DiagCleanup(Diags.get()); 491 492 std::unique_ptr<std::vector<const char *>> Args( 493 new std::vector<const char *>()); 494 495 // Recover resources if we crash before exiting this method. 496 llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> > 497 ArgsCleanup(Args.get()); 498 499 Args->insert(Args->end(), command_line_args, 500 command_line_args + num_command_line_args); 501 502 // The 'source_filename' argument is optional. If the caller does not 503 // specify it then it is assumed that the source file is specified 504 // in the actual argument list. 505 // Put the source file after command_line_args otherwise if '-x' flag is 506 // present it will be unused. 507 if (source_filename) 508 Args->push_back(source_filename); 509 510 std::shared_ptr<CompilerInvocation> CInvok = 511 createInvocationFromCommandLine(*Args, Diags); 512 513 if (!CInvok) 514 return CXError_Failure; 515 516 // Recover resources if we crash before exiting this function. 517 llvm::CrashRecoveryContextCleanupRegistrar< 518 std::shared_ptr<CompilerInvocation>, 519 llvm::CrashRecoveryContextDestructorCleanup< 520 std::shared_ptr<CompilerInvocation>>> 521 CInvokCleanup(&CInvok); 522 523 if (CInvok->getFrontendOpts().Inputs.empty()) 524 return CXError_Failure; 525 526 typedef SmallVector<std::unique_ptr<llvm::MemoryBuffer>, 8> MemBufferOwner; 527 std::unique_ptr<MemBufferOwner> BufOwner(new MemBufferOwner); 528 529 // Recover resources if we crash before exiting this method. 530 llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> BufOwnerCleanup( 531 BufOwner.get()); 532 533 for (auto &UF : unsaved_files) { 534 std::unique_ptr<llvm::MemoryBuffer> MB = 535 llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename); 536 CInvok->getPreprocessorOpts().addRemappedFile(UF.Filename, MB.get()); 537 BufOwner->push_back(std::move(MB)); 538 } 539 540 // Since libclang is primarily used by batch tools dealing with 541 // (often very broken) source code, where spell-checking can have a 542 // significant negative impact on performance (particularly when 543 // precompiled headers are involved), we disable it. 544 CInvok->getLangOpts()->SpellChecking = false; 545 546 if (index_options & CXIndexOpt_SuppressWarnings) 547 CInvok->getDiagnosticOpts().IgnoreWarnings = true; 548 549 // Make sure to use the raw module format. 550 CInvok->getHeaderSearchOpts().ModuleFormat = 551 CXXIdx->getPCHContainerOperations()->getRawReader().getFormat(); 552 553 auto Unit = ASTUnit::create(CInvok, Diags, CaptureDiagnostics, 554 /*UserFilesAreVolatile=*/true); 555 if (!Unit) 556 return CXError_InvalidArguments; 557 558 auto *UPtr = Unit.get(); 559 std::unique_ptr<CXTUOwner> CXTU( 560 new CXTUOwner(MakeCXTranslationUnit(CXXIdx, std::move(Unit)))); 561 562 // Recover resources if we crash before exiting this method. 563 llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner> 564 CXTUCleanup(CXTU.get()); 565 566 // Enable the skip-parsed-bodies optimization only for C++; this may be 567 // revisited. 568 bool SkipBodies = (index_options & CXIndexOpt_SkipParsedBodiesInSession) && 569 CInvok->getLangOpts()->CPlusPlus; 570 if (SkipBodies) 571 CInvok->getFrontendOpts().SkipFunctionBodies = true; 572 573 auto DataConsumer = 574 std::make_shared<CXIndexDataConsumer>(client_data, CB, index_options, 575 CXTU->getTU()); 576 auto IndexAction = std::make_unique<IndexingFrontendAction>( 577 DataConsumer, getIndexingOptionsFromCXOptions(index_options), 578 SkipBodies ? IdxSession->SkipBodyData.get() : nullptr); 579 580 // Recover resources if we crash before exiting this method. 581 llvm::CrashRecoveryContextCleanupRegistrar<FrontendAction> 582 IndexActionCleanup(IndexAction.get()); 583 584 bool Persistent = requestedToGetTU; 585 bool OnlyLocalDecls = false; 586 bool PrecompilePreamble = false; 587 bool CreatePreambleOnFirstParse = false; 588 bool CacheCodeCompletionResults = false; 589 PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); 590 PPOpts.AllowPCHWithCompilerErrors = true; 591 592 if (requestedToGetTU) { 593 OnlyLocalDecls = CXXIdx->getOnlyLocalDecls(); 594 PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble; 595 CreatePreambleOnFirstParse = 596 TU_options & CXTranslationUnit_CreatePreambleOnFirstParse; 597 // FIXME: Add a flag for modules. 598 CacheCodeCompletionResults 599 = TU_options & CXTranslationUnit_CacheCompletionResults; 600 } 601 602 if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) { 603 PPOpts.DetailedRecord = true; 604 } 605 606 if (!requestedToGetTU && !CInvok->getLangOpts()->Modules) 607 PPOpts.DetailedRecord = false; 608 609 // Unless the user specified that they want the preamble on the first parse 610 // set it up to be created on the first reparse. This makes the first parse 611 // faster, trading for a slower (first) reparse. 612 unsigned PrecompilePreambleAfterNParses = 613 !PrecompilePreamble ? 0 : 2 - CreatePreambleOnFirstParse; 614 DiagnosticErrorTrap DiagTrap(*Diags); 615 bool Success = ASTUnit::LoadFromCompilerInvocationAction( 616 std::move(CInvok), CXXIdx->getPCHContainerOperations(), Diags, 617 IndexAction.get(), UPtr, Persistent, CXXIdx->getClangResourcesPath(), 618 OnlyLocalDecls, CaptureDiagnostics, PrecompilePreambleAfterNParses, 619 CacheCodeCompletionResults, 620 /*IncludeBriefCommentsInCodeCompletion=*/false, 621 /*UserFilesAreVolatile=*/true); 622 if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics()) 623 printDiagsToStderr(UPtr); 624 625 if (isASTReadError(UPtr)) 626 return CXError_ASTReadError; 627 628 if (!Success) 629 return CXError_Failure; 630 631 if (out_TU) 632 *out_TU = CXTU->takeTU(); 633 634 return CXError_Success; 635 } 636 637 //===----------------------------------------------------------------------===// 638 // clang_indexTranslationUnit Implementation 639 //===----------------------------------------------------------------------===// 640 641 static void indexPreprocessingRecord(ASTUnit &Unit, CXIndexDataConsumer &IdxCtx) { 642 Preprocessor &PP = Unit.getPreprocessor(); 643 if (!PP.getPreprocessingRecord()) 644 return; 645 646 // FIXME: Only deserialize inclusion directives. 647 648 bool isModuleFile = Unit.isModuleFile(); 649 for (PreprocessedEntity *PPE : Unit.getLocalPreprocessingEntities()) { 650 if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) { 651 SourceLocation Loc = ID->getSourceRange().getBegin(); 652 // Modules have synthetic main files as input, give an invalid location 653 // if the location points to such a file. 654 if (isModuleFile && Unit.isInMainFileID(Loc)) 655 Loc = SourceLocation(); 656 IdxCtx.ppIncludedFile(Loc, ID->getFileName(), 657 ID->getFile(), 658 ID->getKind() == InclusionDirective::Import, 659 !ID->wasInQuotes(), ID->importedModule()); 660 } 661 } 662 } 663 664 static CXErrorCode clang_indexTranslationUnit_Impl( 665 CXIndexAction idxAction, CXClientData client_data, 666 IndexerCallbacks *client_index_callbacks, unsigned index_callbacks_size, 667 unsigned index_options, CXTranslationUnit TU) { 668 // Check arguments. 669 if (isNotUsableTU(TU)) { 670 LOG_BAD_TU(TU); 671 return CXError_InvalidArguments; 672 } 673 if (!client_index_callbacks || index_callbacks_size == 0) { 674 return CXError_InvalidArguments; 675 } 676 677 CIndexer *CXXIdx = TU->CIdx; 678 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) 679 setThreadBackgroundPriority(); 680 681 IndexerCallbacks CB; 682 memset(&CB, 0, sizeof(CB)); 683 unsigned ClientCBSize = index_callbacks_size < sizeof(CB) 684 ? index_callbacks_size : sizeof(CB); 685 memcpy(&CB, client_index_callbacks, ClientCBSize); 686 687 CXIndexDataConsumer DataConsumer(client_data, CB, index_options, TU); 688 689 ASTUnit *Unit = cxtu::getASTUnit(TU); 690 if (!Unit) 691 return CXError_Failure; 692 693 ASTUnit::ConcurrencyCheck Check(*Unit); 694 695 if (const FileEntry *PCHFile = Unit->getPCHFile()) 696 DataConsumer.importedPCH(PCHFile); 697 698 FileManager &FileMgr = Unit->getFileManager(); 699 700 if (Unit->getOriginalSourceFileName().empty()) 701 DataConsumer.enteredMainFile(nullptr); 702 else if (auto MainFile = FileMgr.getFile(Unit->getOriginalSourceFileName())) 703 DataConsumer.enteredMainFile(*MainFile); 704 else 705 DataConsumer.enteredMainFile(nullptr); 706 707 DataConsumer.setASTContext(Unit->getASTContext()); 708 DataConsumer.startedTranslationUnit(); 709 710 indexPreprocessingRecord(*Unit, DataConsumer); 711 indexASTUnit(*Unit, DataConsumer, getIndexingOptionsFromCXOptions(index_options)); 712 DataConsumer.indexDiagnostics(); 713 714 return CXError_Success; 715 } 716 717 //===----------------------------------------------------------------------===// 718 // libclang public APIs. 719 //===----------------------------------------------------------------------===// 720 721 int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) { 722 return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory; 723 } 724 725 const CXIdxObjCContainerDeclInfo * 726 clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) { 727 if (!DInfo) 728 return nullptr; 729 730 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 731 if (const ObjCContainerDeclInfo * 732 ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI)) 733 return &ContInfo->ObjCContDeclInfo; 734 735 return nullptr; 736 } 737 738 const CXIdxObjCInterfaceDeclInfo * 739 clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) { 740 if (!DInfo) 741 return nullptr; 742 743 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 744 if (const ObjCInterfaceDeclInfo * 745 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 746 return &InterInfo->ObjCInterDeclInfo; 747 748 return nullptr; 749 } 750 751 const CXIdxObjCCategoryDeclInfo * 752 clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){ 753 if (!DInfo) 754 return nullptr; 755 756 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 757 if (const ObjCCategoryDeclInfo * 758 CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 759 return &CatInfo->ObjCCatDeclInfo; 760 761 return nullptr; 762 } 763 764 const CXIdxObjCProtocolRefListInfo * 765 clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) { 766 if (!DInfo) 767 return nullptr; 768 769 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 770 771 if (const ObjCInterfaceDeclInfo * 772 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 773 return InterInfo->ObjCInterDeclInfo.protocols; 774 775 if (const ObjCProtocolDeclInfo * 776 ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI)) 777 return &ProtInfo->ObjCProtoRefListInfo; 778 779 if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 780 return CatInfo->ObjCCatDeclInfo.protocols; 781 782 return nullptr; 783 } 784 785 const CXIdxObjCPropertyDeclInfo * 786 clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) { 787 if (!DInfo) 788 return nullptr; 789 790 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 791 if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI)) 792 return &PropInfo->ObjCPropDeclInfo; 793 794 return nullptr; 795 } 796 797 const CXIdxIBOutletCollectionAttrInfo * 798 clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) { 799 if (!AInfo) 800 return nullptr; 801 802 const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo); 803 if (const IBOutletCollectionInfo * 804 IBInfo = dyn_cast<IBOutletCollectionInfo>(DI)) 805 return &IBInfo->IBCollInfo; 806 807 return nullptr; 808 } 809 810 const CXIdxCXXClassDeclInfo * 811 clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) { 812 if (!DInfo) 813 return nullptr; 814 815 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 816 if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI)) 817 return &ClassInfo->CXXClassInfo; 818 819 return nullptr; 820 } 821 822 CXIdxClientContainer 823 clang_index_getClientContainer(const CXIdxContainerInfo *info) { 824 if (!info) 825 return nullptr; 826 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 827 return Container->IndexCtx->getClientContainerForDC(Container->DC); 828 } 829 830 void clang_index_setClientContainer(const CXIdxContainerInfo *info, 831 CXIdxClientContainer client) { 832 if (!info) 833 return; 834 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 835 Container->IndexCtx->addContainerInMap(Container->DC, client); 836 } 837 838 CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) { 839 if (!info) 840 return nullptr; 841 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 842 return Entity->IndexCtx->getClientEntity(Entity->Dcl); 843 } 844 845 void clang_index_setClientEntity(const CXIdxEntityInfo *info, 846 CXIdxClientEntity client) { 847 if (!info) 848 return; 849 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 850 Entity->IndexCtx->setClientEntity(Entity->Dcl, client); 851 } 852 853 CXIndexAction clang_IndexAction_create(CXIndex CIdx) { 854 return new IndexSessionData(CIdx); 855 } 856 857 void clang_IndexAction_dispose(CXIndexAction idxAction) { 858 if (idxAction) 859 delete static_cast<IndexSessionData *>(idxAction); 860 } 861 862 int clang_indexSourceFile(CXIndexAction idxAction, 863 CXClientData client_data, 864 IndexerCallbacks *index_callbacks, 865 unsigned index_callbacks_size, 866 unsigned index_options, 867 const char *source_filename, 868 const char * const *command_line_args, 869 int num_command_line_args, 870 struct CXUnsavedFile *unsaved_files, 871 unsigned num_unsaved_files, 872 CXTranslationUnit *out_TU, 873 unsigned TU_options) { 874 SmallVector<const char *, 4> Args; 875 Args.push_back("clang"); 876 Args.append(command_line_args, command_line_args + num_command_line_args); 877 return clang_indexSourceFileFullArgv( 878 idxAction, client_data, index_callbacks, index_callbacks_size, 879 index_options, source_filename, Args.data(), Args.size(), unsaved_files, 880 num_unsaved_files, out_TU, TU_options); 881 } 882 883 int clang_indexSourceFileFullArgv( 884 CXIndexAction idxAction, CXClientData client_data, 885 IndexerCallbacks *index_callbacks, unsigned index_callbacks_size, 886 unsigned index_options, const char *source_filename, 887 const char *const *command_line_args, int num_command_line_args, 888 struct CXUnsavedFile *unsaved_files, unsigned num_unsaved_files, 889 CXTranslationUnit *out_TU, unsigned TU_options) { 890 LOG_FUNC_SECTION { 891 *Log << source_filename << ": "; 892 for (int i = 0; i != num_command_line_args; ++i) 893 *Log << command_line_args[i] << " "; 894 } 895 896 if (num_unsaved_files && !unsaved_files) 897 return CXError_InvalidArguments; 898 899 CXErrorCode result = CXError_Failure; 900 auto IndexSourceFileImpl = [=, &result]() { 901 result = clang_indexSourceFile_Impl( 902 idxAction, client_data, index_callbacks, index_callbacks_size, 903 index_options, source_filename, command_line_args, 904 num_command_line_args, 905 llvm::makeArrayRef(unsaved_files, num_unsaved_files), out_TU, 906 TU_options); 907 }; 908 909 llvm::CrashRecoveryContext CRC; 910 911 if (!RunSafely(CRC, IndexSourceFileImpl)) { 912 fprintf(stderr, "libclang: crash detected during indexing source file: {\n"); 913 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename); 914 fprintf(stderr, " 'command_line_args' : ["); 915 for (int i = 0; i != num_command_line_args; ++i) { 916 if (i) 917 fprintf(stderr, ", "); 918 fprintf(stderr, "'%s'", command_line_args[i]); 919 } 920 fprintf(stderr, "],\n"); 921 fprintf(stderr, " 'unsaved_files' : ["); 922 for (unsigned i = 0; i != num_unsaved_files; ++i) { 923 if (i) 924 fprintf(stderr, ", "); 925 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename, 926 unsaved_files[i].Length); 927 } 928 fprintf(stderr, "],\n"); 929 fprintf(stderr, " 'options' : %d,\n", TU_options); 930 fprintf(stderr, "}\n"); 931 932 return 1; 933 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) { 934 if (out_TU) 935 PrintLibclangResourceUsage(*out_TU); 936 } 937 938 return result; 939 } 940 941 int clang_indexTranslationUnit(CXIndexAction idxAction, 942 CXClientData client_data, 943 IndexerCallbacks *index_callbacks, 944 unsigned index_callbacks_size, 945 unsigned index_options, 946 CXTranslationUnit TU) { 947 LOG_FUNC_SECTION { 948 *Log << TU; 949 } 950 951 CXErrorCode result; 952 auto IndexTranslationUnitImpl = [=, &result]() { 953 result = clang_indexTranslationUnit_Impl( 954 idxAction, client_data, index_callbacks, index_callbacks_size, 955 index_options, TU); 956 }; 957 958 llvm::CrashRecoveryContext CRC; 959 960 if (!RunSafely(CRC, IndexTranslationUnitImpl)) { 961 fprintf(stderr, "libclang: crash detected during indexing TU\n"); 962 963 return 1; 964 } 965 966 return result; 967 } 968 969 void clang_indexLoc_getFileLocation(CXIdxLoc location, 970 CXIdxClientFile *indexFile, 971 CXFile *file, 972 unsigned *line, 973 unsigned *column, 974 unsigned *offset) { 975 if (indexFile) *indexFile = nullptr; 976 if (file) *file = nullptr; 977 if (line) *line = 0; 978 if (column) *column = 0; 979 if (offset) *offset = 0; 980 981 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 982 if (!location.ptr_data[0] || Loc.isInvalid()) 983 return; 984 985 CXIndexDataConsumer &DataConsumer = 986 *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]); 987 DataConsumer.translateLoc(Loc, indexFile, file, line, column, offset); 988 } 989 990 CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { 991 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 992 if (!location.ptr_data[0] || Loc.isInvalid()) 993 return clang_getNullLocation(); 994 995 CXIndexDataConsumer &DataConsumer = 996 *static_cast<CXIndexDataConsumer*>(location.ptr_data[0]); 997 return cxloc::translateSourceLocation(DataConsumer.getASTContext(), Loc); 998 } 999