Indexing.cpp revision f59edb96b2d0bfe612b732f19519ab84bb995bd4
1//===- CIndexHigh.cpp - Higher level API functions ------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "IndexingContext.h" 11#include "CIndexDiagnostic.h" 12#include "CIndexer.h" 13#include "CXCursor.h" 14#include "CXSourceLocation.h" 15#include "CXString.h" 16#include "CXTranslationUnit.h" 17#include "clang/AST/ASTConsumer.h" 18#include "clang/AST/DeclVisitor.h" 19#include "clang/Frontend/ASTUnit.h" 20#include "clang/Frontend/CompilerInstance.h" 21#include "clang/Frontend/CompilerInvocation.h" 22#include "clang/Frontend/FrontendAction.h" 23#include "clang/Frontend/Utils.h" 24#include "clang/Lex/PPCallbacks.h" 25#include "clang/Lex/Preprocessor.h" 26#include "clang/Sema/SemaConsumer.h" 27#include "llvm/Support/CrashRecoveryContext.h" 28#include "llvm/Support/MemoryBuffer.h" 29 30using namespace clang; 31using namespace cxstring; 32using namespace cxtu; 33using namespace cxindex; 34 35static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx); 36 37namespace { 38 39//===----------------------------------------------------------------------===// 40// IndexPPCallbacks 41//===----------------------------------------------------------------------===// 42 43class IndexPPCallbacks : public PPCallbacks { 44 Preprocessor &PP; 45 IndexingContext &IndexCtx; 46 bool IsMainFileEntered; 47 48public: 49 IndexPPCallbacks(Preprocessor &PP, IndexingContext &indexCtx) 50 : PP(PP), IndexCtx(indexCtx), IsMainFileEntered(false) { } 51 52 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, 53 SrcMgr::CharacteristicKind FileType, FileID PrevFID) { 54 if (IsMainFileEntered) 55 return; 56 57 SourceManager &SM = PP.getSourceManager(); 58 SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID()); 59 60 if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) { 61 IsMainFileEntered = true; 62 IndexCtx.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID())); 63 } 64 } 65 66 virtual void InclusionDirective(SourceLocation HashLoc, 67 const Token &IncludeTok, 68 StringRef FileName, 69 bool IsAngled, 70 CharSourceRange FilenameRange, 71 const FileEntry *File, 72 StringRef SearchPath, 73 StringRef RelativePath, 74 const Module *Imported) { 75 bool isImport = (IncludeTok.is(tok::identifier) && 76 IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import); 77 IndexCtx.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled, 78 Imported); 79 } 80 81 /// MacroDefined - This hook is called whenever a macro definition is seen. 82 virtual void MacroDefined(const Token &Id, const MacroInfo *MI) { 83 } 84 85 /// MacroUndefined - This hook is called whenever a macro #undef is seen. 86 /// MI is released immediately following this callback. 87 virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) { 88 } 89 90 /// MacroExpands - This is called by when a macro invocation is found. 91 virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI, 92 SourceRange Range) { 93 } 94 95 /// SourceRangeSkipped - This hook is called when a source range is skipped. 96 /// \param Range The SourceRange that was skipped. The range begins at the 97 /// #if/#else directive and ends after the #endif/#else directive. 98 virtual void SourceRangeSkipped(SourceRange Range) { 99 } 100}; 101 102//===----------------------------------------------------------------------===// 103// IndexingConsumer 104//===----------------------------------------------------------------------===// 105 106class IndexingConsumer : public ASTConsumer { 107 IndexingContext &IndexCtx; 108 109public: 110 explicit IndexingConsumer(IndexingContext &indexCtx) 111 : IndexCtx(indexCtx) { } 112 113 // ASTConsumer Implementation 114 115 virtual void Initialize(ASTContext &Context) { 116 IndexCtx.setASTContext(Context); 117 IndexCtx.startedTranslationUnit(); 118 } 119 120 virtual void HandleTranslationUnit(ASTContext &Ctx) { 121 } 122 123 virtual bool HandleTopLevelDecl(DeclGroupRef DG) { 124 IndexCtx.indexDeclGroupRef(DG); 125 return !IndexCtx.shouldAbort(); 126 } 127 128 /// \brief Handle the specified top-level declaration that occurred inside 129 /// and ObjC container. 130 virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) { 131 // They will be handled after the interface is seen first. 132 IndexCtx.addTUDeclInObjCContainer(D); 133 } 134 135 /// \brief This is called by the AST reader when deserializing things. 136 /// The default implementation forwards to HandleTopLevelDecl but we don't 137 /// care about them when indexing, so have an empty definition. 138 virtual void HandleInterestingDecl(DeclGroupRef D) {} 139 140 virtual void HandleTagDeclDefinition(TagDecl *D) { 141 if (!IndexCtx.shouldIndexImplicitTemplateInsts()) 142 return; 143 144 if (IndexCtx.isTemplateImplicitInstantiation(D)) 145 IndexCtx.indexDecl(D); 146 } 147 148 virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) { 149 if (!IndexCtx.shouldIndexImplicitTemplateInsts()) 150 return; 151 152 IndexCtx.indexDecl(D); 153 } 154}; 155 156//===----------------------------------------------------------------------===// 157// CaptureDiagnosticConsumer 158//===----------------------------------------------------------------------===// 159 160class CaptureDiagnosticConsumer : public DiagnosticConsumer { 161 SmallVector<StoredDiagnostic, 4> Errors; 162public: 163 164 virtual void HandleDiagnostic(DiagnosticsEngine::Level level, 165 const Diagnostic &Info) { 166 if (level >= DiagnosticsEngine::Error) 167 Errors.push_back(StoredDiagnostic(level, Info)); 168 } 169 170 DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const { 171 return new IgnoringDiagConsumer(); 172 } 173}; 174 175//===----------------------------------------------------------------------===// 176// IndexingFrontendAction 177//===----------------------------------------------------------------------===// 178 179class IndexingFrontendAction : public ASTFrontendAction { 180 IndexingContext IndexCtx; 181 CXTranslationUnit CXTU; 182 183public: 184 IndexingFrontendAction(CXClientData clientData, 185 IndexerCallbacks &indexCallbacks, 186 unsigned indexOptions, 187 CXTranslationUnit cxTU) 188 : IndexCtx(clientData, indexCallbacks, indexOptions, cxTU), 189 CXTU(cxTU) { } 190 191 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, 192 StringRef InFile) { 193 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 194 195 if (!PPOpts.ImplicitPCHInclude.empty()) { 196 IndexCtx.importedPCH( 197 CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude)); 198 } 199 200 IndexCtx.setASTContext(CI.getASTContext()); 201 Preprocessor &PP = CI.getPreprocessor(); 202 PP.addPPCallbacks(new IndexPPCallbacks(PP, IndexCtx)); 203 IndexCtx.setPreprocessor(PP); 204 return new IndexingConsumer(IndexCtx); 205 } 206 207 virtual void EndSourceFileAction() { 208 indexDiagnostics(CXTU, IndexCtx); 209 } 210 211 virtual TranslationUnitKind getTranslationUnitKind() { 212 if (IndexCtx.shouldIndexImplicitTemplateInsts()) 213 return TU_Complete; 214 else 215 return TU_Prefix; 216 } 217 virtual bool hasCodeCompletionSupport() const { return false; } 218}; 219 220//===----------------------------------------------------------------------===// 221// clang_indexSourceFileUnit Implementation 222//===----------------------------------------------------------------------===// 223 224struct IndexSourceFileInfo { 225 CXIndexAction idxAction; 226 CXClientData client_data; 227 IndexerCallbacks *index_callbacks; 228 unsigned index_callbacks_size; 229 unsigned index_options; 230 const char *source_filename; 231 const char *const *command_line_args; 232 int num_command_line_args; 233 struct CXUnsavedFile *unsaved_files; 234 unsigned num_unsaved_files; 235 CXTranslationUnit *out_TU; 236 unsigned TU_options; 237 int result; 238}; 239 240struct MemBufferOwner { 241 SmallVector<const llvm::MemoryBuffer *, 8> Buffers; 242 243 ~MemBufferOwner() { 244 for (SmallVectorImpl<const llvm::MemoryBuffer *>::iterator 245 I = Buffers.begin(), E = Buffers.end(); I != E; ++I) 246 delete *I; 247 } 248}; 249 250} // anonymous namespace 251 252static void clang_indexSourceFile_Impl(void *UserData) { 253 IndexSourceFileInfo *ITUI = 254 static_cast<IndexSourceFileInfo*>(UserData); 255 CXIndex CIdx = (CXIndex)ITUI->idxAction; 256 CXClientData client_data = ITUI->client_data; 257 IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks; 258 unsigned index_callbacks_size = ITUI->index_callbacks_size; 259 unsigned index_options = ITUI->index_options; 260 const char *source_filename = ITUI->source_filename; 261 const char * const *command_line_args = ITUI->command_line_args; 262 int num_command_line_args = ITUI->num_command_line_args; 263 struct CXUnsavedFile *unsaved_files = ITUI->unsaved_files; 264 unsigned num_unsaved_files = ITUI->num_unsaved_files; 265 CXTranslationUnit *out_TU = ITUI->out_TU; 266 unsigned TU_options = ITUI->TU_options; 267 ITUI->result = 1; // init as error. 268 269 if (out_TU) 270 *out_TU = 0; 271 bool requestedToGetTU = (out_TU != 0); 272 273 if (!CIdx) 274 return; 275 if (!client_index_callbacks || index_callbacks_size == 0) 276 return; 277 278 IndexerCallbacks CB; 279 memset(&CB, 0, sizeof(CB)); 280 unsigned ClientCBSize = index_callbacks_size < sizeof(CB) 281 ? index_callbacks_size : sizeof(CB); 282 memcpy(&CB, client_index_callbacks, ClientCBSize); 283 284 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); 285 286 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) 287 setThreadBackgroundPriority(); 288 289 CaptureDiagnosticConsumer *CaptureDiag = new CaptureDiagnosticConsumer(); 290 291 // Configure the diagnostics. 292 IntrusiveRefCntPtr<DiagnosticsEngine> 293 Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions, 294 num_command_line_args, 295 command_line_args, 296 CaptureDiag, 297 /*ShouldOwnClient=*/true, 298 /*ShouldCloneClient=*/false)); 299 300 // Recover resources if we crash before exiting this function. 301 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, 302 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > 303 DiagCleanup(Diags.getPtr()); 304 305 OwningPtr<std::vector<const char *> > 306 Args(new std::vector<const char*>()); 307 308 // Recover resources if we crash before exiting this method. 309 llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> > 310 ArgsCleanup(Args.get()); 311 312 Args->insert(Args->end(), command_line_args, 313 command_line_args + num_command_line_args); 314 315 // The 'source_filename' argument is optional. If the caller does not 316 // specify it then it is assumed that the source file is specified 317 // in the actual argument list. 318 // Put the source file after command_line_args otherwise if '-x' flag is 319 // present it will be unused. 320 if (source_filename) 321 Args->push_back(source_filename); 322 323 IntrusiveRefCntPtr<CompilerInvocation> 324 CInvok(createInvocationFromCommandLine(*Args, Diags)); 325 326 if (!CInvok) 327 return; 328 329 // Recover resources if we crash before exiting this function. 330 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation, 331 llvm::CrashRecoveryContextReleaseRefCleanup<CompilerInvocation> > 332 CInvokCleanup(CInvok.getPtr()); 333 334 if (CInvok->getFrontendOpts().Inputs.empty()) 335 return; 336 337 OwningPtr<MemBufferOwner> BufOwner(new MemBufferOwner()); 338 339 // Recover resources if we crash before exiting this method. 340 llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> 341 BufOwnerCleanup(BufOwner.get()); 342 343 for (unsigned I = 0; I != num_unsaved_files; ++I) { 344 StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); 345 const llvm::MemoryBuffer *Buffer 346 = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename); 347 CInvok->getPreprocessorOpts().addRemappedFile(unsaved_files[I].Filename, Buffer); 348 BufOwner->Buffers.push_back(Buffer); 349 } 350 351 // Since libclang is primarily used by batch tools dealing with 352 // (often very broken) source code, where spell-checking can have a 353 // significant negative impact on performance (particularly when 354 // precompiled headers are involved), we disable it. 355 CInvok->getLangOpts()->SpellChecking = false; 356 357 if (index_options & CXIndexOpt_SuppressWarnings) 358 CInvok->getDiagnosticOpts().IgnoreWarnings = true; 359 360 ASTUnit *Unit = ASTUnit::create(CInvok.getPtr(), Diags, 361 /*CaptureDiagnostics=*/true, 362 /*UserFilesAreVolatile=*/true); 363 OwningPtr<CXTUOwner> CXTU(new CXTUOwner(MakeCXTranslationUnit(CXXIdx, Unit))); 364 365 // Recover resources if we crash before exiting this method. 366 llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner> 367 CXTUCleanup(CXTU.get()); 368 369 OwningPtr<IndexingFrontendAction> IndexAction; 370 IndexAction.reset(new IndexingFrontendAction(client_data, CB, 371 index_options, CXTU->getTU())); 372 373 // Recover resources if we crash before exiting this method. 374 llvm::CrashRecoveryContextCleanupRegistrar<IndexingFrontendAction> 375 IndexActionCleanup(IndexAction.get()); 376 377 bool Persistent = requestedToGetTU; 378 bool OnlyLocalDecls = false; 379 bool PrecompilePreamble = false; 380 bool CacheCodeCompletionResults = false; 381 PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); 382 PPOpts.AllowPCHWithCompilerErrors = true; 383 384 if (requestedToGetTU) { 385 OnlyLocalDecls = CXXIdx->getOnlyLocalDecls(); 386 PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble; 387 // FIXME: Add a flag for modules. 388 CacheCodeCompletionResults 389 = TU_options & CXTranslationUnit_CacheCompletionResults; 390 } 391 392 if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) { 393 PPOpts.DetailedRecord = true; 394 } 395 396 if (!requestedToGetTU && !CInvok->getLangOpts()->Modules) 397 PPOpts.DetailedRecord = false; 398 399 DiagnosticErrorTrap DiagTrap(*Diags); 400 bool Success = ASTUnit::LoadFromCompilerInvocationAction(CInvok.getPtr(), Diags, 401 IndexAction.get(), 402 Unit, 403 Persistent, 404 CXXIdx->getClangResourcesPath(), 405 OnlyLocalDecls, 406 /*CaptureDiagnostics=*/true, 407 PrecompilePreamble, 408 CacheCodeCompletionResults, 409 /*IncludeBriefCommentsInCodeCompletion=*/false, 410 /*UserFilesAreVolatile=*/true); 411 if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics()) 412 printDiagsToStderr(Unit); 413 414 if (!Success) 415 return; 416 417 if (out_TU) 418 *out_TU = CXTU->takeTU(); 419 420 ITUI->result = 0; // success. 421} 422 423//===----------------------------------------------------------------------===// 424// clang_indexTranslationUnit Implementation 425//===----------------------------------------------------------------------===// 426 427namespace { 428 429struct IndexTranslationUnitInfo { 430 CXIndexAction idxAction; 431 CXClientData client_data; 432 IndexerCallbacks *index_callbacks; 433 unsigned index_callbacks_size; 434 unsigned index_options; 435 CXTranslationUnit TU; 436 int result; 437}; 438 439} // anonymous namespace 440 441static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) { 442 Preprocessor &PP = Unit.getPreprocessor(); 443 if (!PP.getPreprocessingRecord()) 444 return; 445 446 // FIXME: Only deserialize inclusion directives. 447 448 PreprocessingRecord::iterator I, E; 449 llvm::tie(I, E) = Unit.getLocalPreprocessingEntities(); 450 451 bool isModuleFile = Unit.isModuleFile(); 452 for (; I != E; ++I) { 453 PreprocessedEntity *PPE = *I; 454 455 if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) { 456 SourceLocation Loc = ID->getSourceRange().getBegin(); 457 // Modules have synthetic main files as input, give an invalid location 458 // if the location points to such a file. 459 if (isModuleFile && Unit.isInMainFileID(Loc)) 460 Loc = SourceLocation(); 461 IdxCtx.ppIncludedFile(Loc, ID->getFileName(), 462 ID->getFile(), 463 ID->getKind() == InclusionDirective::Import, 464 !ID->wasInQuotes(), ID->importedModule()); 465 } 466 } 467} 468 469static bool topLevelDeclVisitor(void *context, const Decl *D) { 470 IndexingContext &IdxCtx = *static_cast<IndexingContext*>(context); 471 IdxCtx.indexTopLevelDecl(D); 472 if (IdxCtx.shouldAbort()) 473 return false; 474 return true; 475} 476 477static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) { 478 Unit.visitLocalTopLevelDecls(&IdxCtx, topLevelDeclVisitor); 479} 480 481static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) { 482 if (!IdxCtx.hasDiagnosticCallback()) 483 return; 484 485 CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(TU); 486 IdxCtx.handleDiagnosticSet(DiagSet); 487} 488 489static void clang_indexTranslationUnit_Impl(void *UserData) { 490 IndexTranslationUnitInfo *ITUI = 491 static_cast<IndexTranslationUnitInfo*>(UserData); 492 CXTranslationUnit TU = ITUI->TU; 493 CXClientData client_data = ITUI->client_data; 494 IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks; 495 unsigned index_callbacks_size = ITUI->index_callbacks_size; 496 unsigned index_options = ITUI->index_options; 497 ITUI->result = 1; // init as error. 498 499 if (!TU) 500 return; 501 if (!client_index_callbacks || index_callbacks_size == 0) 502 return; 503 504 CIndexer *CXXIdx = (CIndexer*)TU->CIdx; 505 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing)) 506 setThreadBackgroundPriority(); 507 508 IndexerCallbacks CB; 509 memset(&CB, 0, sizeof(CB)); 510 unsigned ClientCBSize = index_callbacks_size < sizeof(CB) 511 ? index_callbacks_size : sizeof(CB); 512 memcpy(&CB, client_index_callbacks, ClientCBSize); 513 514 OwningPtr<IndexingContext> IndexCtx; 515 IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU)); 516 517 // Recover resources if we crash before exiting this method. 518 llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext> 519 IndexCtxCleanup(IndexCtx.get()); 520 521 OwningPtr<IndexingConsumer> IndexConsumer; 522 IndexConsumer.reset(new IndexingConsumer(*IndexCtx)); 523 524 // Recover resources if we crash before exiting this method. 525 llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer> 526 IndexConsumerCleanup(IndexConsumer.get()); 527 528 ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData); 529 if (!Unit) 530 return; 531 532 ASTUnit::ConcurrencyCheck Check(*Unit); 533 534 if (const FileEntry *PCHFile = Unit->getPCHFile()) 535 IndexCtx->importedPCH(PCHFile); 536 537 FileManager &FileMgr = Unit->getFileManager(); 538 539 if (Unit->getOriginalSourceFileName().empty()) 540 IndexCtx->enteredMainFile(0); 541 else 542 IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); 543 544 IndexConsumer->Initialize(Unit->getASTContext()); 545 546 indexPreprocessingRecord(*Unit, *IndexCtx); 547 indexTranslationUnit(*Unit, *IndexCtx); 548 indexDiagnostics(TU, *IndexCtx); 549 550 ITUI->result = 0; 551} 552 553//===----------------------------------------------------------------------===// 554// libclang public APIs. 555//===----------------------------------------------------------------------===// 556 557extern "C" { 558 559int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) { 560 return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory; 561} 562 563const CXIdxObjCContainerDeclInfo * 564clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) { 565 if (!DInfo) 566 return 0; 567 568 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 569 if (const ObjCContainerDeclInfo * 570 ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI)) 571 return &ContInfo->ObjCContDeclInfo; 572 573 return 0; 574} 575 576const CXIdxObjCInterfaceDeclInfo * 577clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) { 578 if (!DInfo) 579 return 0; 580 581 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 582 if (const ObjCInterfaceDeclInfo * 583 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 584 return &InterInfo->ObjCInterDeclInfo; 585 586 return 0; 587} 588 589const CXIdxObjCCategoryDeclInfo * 590clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){ 591 if (!DInfo) 592 return 0; 593 594 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 595 if (const ObjCCategoryDeclInfo * 596 CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 597 return &CatInfo->ObjCCatDeclInfo; 598 599 return 0; 600} 601 602const CXIdxObjCProtocolRefListInfo * 603clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) { 604 if (!DInfo) 605 return 0; 606 607 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 608 609 if (const ObjCInterfaceDeclInfo * 610 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 611 return InterInfo->ObjCInterDeclInfo.protocols; 612 613 if (const ObjCProtocolDeclInfo * 614 ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI)) 615 return &ProtInfo->ObjCProtoRefListInfo; 616 617 if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 618 return CatInfo->ObjCCatDeclInfo.protocols; 619 620 return 0; 621} 622 623const CXIdxObjCPropertyDeclInfo * 624clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) { 625 if (!DInfo) 626 return 0; 627 628 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 629 if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI)) 630 return &PropInfo->ObjCPropDeclInfo; 631 632 return 0; 633} 634 635const CXIdxIBOutletCollectionAttrInfo * 636clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) { 637 if (!AInfo) 638 return 0; 639 640 const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo); 641 if (const IBOutletCollectionInfo * 642 IBInfo = dyn_cast<IBOutletCollectionInfo>(DI)) 643 return &IBInfo->IBCollInfo; 644 645 return 0; 646} 647 648const CXIdxCXXClassDeclInfo * 649clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) { 650 if (!DInfo) 651 return 0; 652 653 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 654 if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI)) 655 return &ClassInfo->CXXClassInfo; 656 657 return 0; 658} 659 660CXIdxClientContainer 661clang_index_getClientContainer(const CXIdxContainerInfo *info) { 662 if (!info) 663 return 0; 664 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 665 return Container->IndexCtx->getClientContainerForDC(Container->DC); 666} 667 668void clang_index_setClientContainer(const CXIdxContainerInfo *info, 669 CXIdxClientContainer client) { 670 if (!info) 671 return; 672 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 673 Container->IndexCtx->addContainerInMap(Container->DC, client); 674} 675 676CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) { 677 if (!info) 678 return 0; 679 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 680 return Entity->IndexCtx->getClientEntity(Entity->Dcl); 681} 682 683void clang_index_setClientEntity(const CXIdxEntityInfo *info, 684 CXIdxClientEntity client) { 685 if (!info) 686 return; 687 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 688 Entity->IndexCtx->setClientEntity(Entity->Dcl, client); 689} 690 691CXIndexAction clang_IndexAction_create(CXIndex CIdx) { 692 // For now, CXIndexAction is featureless. 693 return CIdx; 694} 695 696void clang_IndexAction_dispose(CXIndexAction idxAction) { 697 // For now, CXIndexAction is featureless. 698} 699 700int clang_indexSourceFile(CXIndexAction idxAction, 701 CXClientData client_data, 702 IndexerCallbacks *index_callbacks, 703 unsigned index_callbacks_size, 704 unsigned index_options, 705 const char *source_filename, 706 const char * const *command_line_args, 707 int num_command_line_args, 708 struct CXUnsavedFile *unsaved_files, 709 unsigned num_unsaved_files, 710 CXTranslationUnit *out_TU, 711 unsigned TU_options) { 712 713 IndexSourceFileInfo ITUI = { idxAction, client_data, index_callbacks, 714 index_callbacks_size, index_options, 715 source_filename, command_line_args, 716 num_command_line_args, unsaved_files, 717 num_unsaved_files, out_TU, TU_options, 0 }; 718 719 if (getenv("LIBCLANG_NOTHREADS")) { 720 clang_indexSourceFile_Impl(&ITUI); 721 return ITUI.result; 722 } 723 724 llvm::CrashRecoveryContext CRC; 725 726 if (!RunSafely(CRC, clang_indexSourceFile_Impl, &ITUI)) { 727 fprintf(stderr, "libclang: crash detected during indexing source file: {\n"); 728 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename); 729 fprintf(stderr, " 'command_line_args' : ["); 730 for (int i = 0; i != num_command_line_args; ++i) { 731 if (i) 732 fprintf(stderr, ", "); 733 fprintf(stderr, "'%s'", command_line_args[i]); 734 } 735 fprintf(stderr, "],\n"); 736 fprintf(stderr, " 'unsaved_files' : ["); 737 for (unsigned i = 0; i != num_unsaved_files; ++i) { 738 if (i) 739 fprintf(stderr, ", "); 740 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename, 741 unsaved_files[i].Length); 742 } 743 fprintf(stderr, "],\n"); 744 fprintf(stderr, " 'options' : %d,\n", TU_options); 745 fprintf(stderr, "}\n"); 746 747 return 1; 748 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) { 749 if (out_TU) 750 PrintLibclangResourceUsage(*out_TU); 751 } 752 753 return ITUI.result; 754} 755 756int clang_indexTranslationUnit(CXIndexAction idxAction, 757 CXClientData client_data, 758 IndexerCallbacks *index_callbacks, 759 unsigned index_callbacks_size, 760 unsigned index_options, 761 CXTranslationUnit TU) { 762 763 IndexTranslationUnitInfo ITUI = { idxAction, client_data, index_callbacks, 764 index_callbacks_size, index_options, TU, 765 0 }; 766 767 if (getenv("LIBCLANG_NOTHREADS")) { 768 clang_indexTranslationUnit_Impl(&ITUI); 769 return ITUI.result; 770 } 771 772 llvm::CrashRecoveryContext CRC; 773 774 if (!RunSafely(CRC, clang_indexTranslationUnit_Impl, &ITUI)) { 775 fprintf(stderr, "libclang: crash detected during indexing TU\n"); 776 777 return 1; 778 } 779 780 return ITUI.result; 781} 782 783void clang_indexLoc_getFileLocation(CXIdxLoc location, 784 CXIdxClientFile *indexFile, 785 CXFile *file, 786 unsigned *line, 787 unsigned *column, 788 unsigned *offset) { 789 if (indexFile) *indexFile = 0; 790 if (file) *file = 0; 791 if (line) *line = 0; 792 if (column) *column = 0; 793 if (offset) *offset = 0; 794 795 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 796 if (!location.ptr_data[0] || Loc.isInvalid()) 797 return; 798 799 IndexingContext &IndexCtx = 800 *static_cast<IndexingContext*>(location.ptr_data[0]); 801 IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset); 802} 803 804CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { 805 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 806 if (!location.ptr_data[0] || Loc.isInvalid()) 807 return clang_getNullLocation(); 808 809 IndexingContext &IndexCtx = 810 *static_cast<IndexingContext*>(location.ptr_data[0]); 811 return cxloc::translateSourceLocation(IndexCtx.getASTContext(), Loc); 812} 813 814} // end: extern "C" 815 816