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