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