Indexing.cpp revision 996e6e564af7483e2d5e0b70df5fdb9f79ec4b5a
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 return 0; 587} 588 589const CXIdxIBOutletCollectionAttrInfo * 590clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) { 591 if (!AInfo) 592 return 0; 593 594 const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo); 595 if (const IBOutletCollectionInfo * 596 IBInfo = dyn_cast<IBOutletCollectionInfo>(DI)) 597 return &IBInfo->IBCollInfo; 598 599 return 0; 600} 601 602const CXIdxCXXClassDeclInfo * 603clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) { 604 if (!DInfo) 605 return 0; 606 607 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 608 if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI)) 609 return &ClassInfo->CXXClassInfo; 610 611 return 0; 612} 613 614CXIdxClientContainer 615clang_index_getClientContainer(const CXIdxContainerInfo *info) { 616 if (!info) 617 return 0; 618 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 619 return Container->IndexCtx->getClientContainerForDC(Container->DC); 620} 621 622void clang_index_setClientContainer(const CXIdxContainerInfo *info, 623 CXIdxClientContainer client) { 624 if (!info) 625 return; 626 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info); 627 Container->IndexCtx->addContainerInMap(Container->DC, client); 628} 629 630CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) { 631 if (!info) 632 return 0; 633 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 634 return Entity->IndexCtx->getClientEntity(Entity->Dcl); 635} 636 637void clang_index_setClientEntity(const CXIdxEntityInfo *info, 638 CXIdxClientEntity client) { 639 if (!info) 640 return; 641 const EntityInfo *Entity = static_cast<const EntityInfo *>(info); 642 Entity->IndexCtx->setClientEntity(Entity->Dcl, client); 643} 644 645CXIndexAction clang_IndexAction_create(CXIndex CIdx) { 646 // For now, CXIndexAction is featureless. 647 return CIdx; 648} 649 650void clang_IndexAction_dispose(CXIndexAction idxAction) { 651 // For now, CXIndexAction is featureless. 652} 653 654int clang_indexSourceFile(CXIndexAction idxAction, 655 CXClientData client_data, 656 IndexerCallbacks *index_callbacks, 657 unsigned index_callbacks_size, 658 unsigned index_options, 659 const char *source_filename, 660 const char * const *command_line_args, 661 int num_command_line_args, 662 struct CXUnsavedFile *unsaved_files, 663 unsigned num_unsaved_files, 664 CXTranslationUnit *out_TU, 665 unsigned TU_options) { 666 667 IndexSourceFileInfo ITUI = { idxAction, client_data, index_callbacks, 668 index_callbacks_size, index_options, 669 source_filename, command_line_args, 670 num_command_line_args, unsaved_files, 671 num_unsaved_files, out_TU, TU_options, 0 }; 672 673 if (getenv("LIBCLANG_NOTHREADS")) { 674 clang_indexSourceFile_Impl(&ITUI); 675 return ITUI.result; 676 } 677 678 llvm::CrashRecoveryContext CRC; 679 680 if (!RunSafely(CRC, clang_indexSourceFile_Impl, &ITUI)) { 681 fprintf(stderr, "libclang: crash detected during indexing source file: {\n"); 682 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename); 683 fprintf(stderr, " 'command_line_args' : ["); 684 for (int i = 0; i != num_command_line_args; ++i) { 685 if (i) 686 fprintf(stderr, ", "); 687 fprintf(stderr, "'%s'", command_line_args[i]); 688 } 689 fprintf(stderr, "],\n"); 690 fprintf(stderr, " 'unsaved_files' : ["); 691 for (unsigned i = 0; i != num_unsaved_files; ++i) { 692 if (i) 693 fprintf(stderr, ", "); 694 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename, 695 unsaved_files[i].Length); 696 } 697 fprintf(stderr, "],\n"); 698 fprintf(stderr, " 'options' : %d,\n", TU_options); 699 fprintf(stderr, "}\n"); 700 701 return 1; 702 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) { 703 if (out_TU) 704 PrintLibclangResourceUsage(*out_TU); 705 } 706 707 return ITUI.result; 708} 709 710int clang_indexTranslationUnit(CXIndexAction idxAction, 711 CXClientData client_data, 712 IndexerCallbacks *index_callbacks, 713 unsigned index_callbacks_size, 714 unsigned index_options, 715 CXTranslationUnit TU) { 716 717 IndexTranslationUnitInfo ITUI = { idxAction, client_data, index_callbacks, 718 index_callbacks_size, index_options, TU, 719 0 }; 720 721 if (getenv("LIBCLANG_NOTHREADS")) { 722 clang_indexTranslationUnit_Impl(&ITUI); 723 return ITUI.result; 724 } 725 726 llvm::CrashRecoveryContext CRC; 727 728 if (!RunSafely(CRC, clang_indexTranslationUnit_Impl, &ITUI)) { 729 fprintf(stderr, "libclang: crash detected during indexing TU\n"); 730 731 return 1; 732 } 733 734 return ITUI.result; 735} 736 737void clang_indexLoc_getFileLocation(CXIdxLoc location, 738 CXIdxClientFile *indexFile, 739 CXFile *file, 740 unsigned *line, 741 unsigned *column, 742 unsigned *offset) { 743 if (indexFile) *indexFile = 0; 744 if (file) *file = 0; 745 if (line) *line = 0; 746 if (column) *column = 0; 747 if (offset) *offset = 0; 748 749 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 750 if (!location.ptr_data[0] || Loc.isInvalid()) 751 return; 752 753 IndexingContext &IndexCtx = 754 *static_cast<IndexingContext*>(location.ptr_data[0]); 755 IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset); 756} 757 758CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { 759 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 760 if (!location.ptr_data[0] || Loc.isInvalid()) 761 return clang_getNullLocation(); 762 763 IndexingContext &IndexCtx = 764 *static_cast<IndexingContext*>(location.ptr_data[0]); 765 return cxloc::translateSourceLocation(IndexCtx.getASTContext(), Loc); 766} 767 768} // end: extern "C" 769 770