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