Indexing.cpp revision b395c63b473bf1b3783bff371a993332e8c4c5e3
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 void HandleTopLevelDecl(DeclGroupRef DG) { 119 IndexCtx.indexDeclGroupRef(DG); 120 // FIXME: Indicate to parser to abort. 121// if (IndexCtx.shouldAbort()) { 122// 123// } 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 165public: 166 IndexingFrontendAction(CXClientData clientData, 167 IndexerCallbacks &indexCallbacks, 168 unsigned indexOptions, 169 CXTranslationUnit cxTU) 170 : IndexCtx(clientData, indexCallbacks, indexOptions, cxTU) { } 171 172 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, 173 StringRef InFile) { 174 IndexCtx.setASTContext(CI.getASTContext()); 175 Preprocessor &PP = CI.getPreprocessor(); 176 PP.addPPCallbacks(new IndexPPCallbacks(PP, IndexCtx)); 177 return new IndexingConsumer(IndexCtx); 178 } 179 180 virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; } 181 virtual bool hasCodeCompletionSupport() const { return false; } 182}; 183 184//===----------------------------------------------------------------------===// 185// clang_indexSourceFileUnit Implementation 186//===----------------------------------------------------------------------===// 187 188struct IndexSourceFileInfo { 189 CXIndex CIdx; 190 CXClientData client_data; 191 IndexerCallbacks *index_callbacks; 192 unsigned index_callbacks_size; 193 unsigned index_options; 194 const char *source_filename; 195 const char *const *command_line_args; 196 int num_command_line_args; 197 struct CXUnsavedFile *unsaved_files; 198 unsigned num_unsaved_files; 199 CXTranslationUnit *out_TU; 200 unsigned TU_options; 201 int result; 202}; 203 204struct MemBufferOwner { 205 SmallVector<const llvm::MemoryBuffer *, 8> Buffers; 206 207 ~MemBufferOwner() { 208 for (SmallVectorImpl<const llvm::MemoryBuffer *>::iterator 209 I = Buffers.begin(), E = Buffers.end(); I != E; ++I) 210 delete *I; 211 } 212}; 213 214} // anonymous namespace 215 216static void clang_indexSourceFile_Impl(void *UserData) { 217 IndexSourceFileInfo *ITUI = 218 static_cast<IndexSourceFileInfo*>(UserData); 219 CXIndex CIdx = ITUI->CIdx; 220 CXClientData client_data = ITUI->client_data; 221 IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks; 222 unsigned index_callbacks_size = ITUI->index_callbacks_size; 223 unsigned index_options = ITUI->index_options; 224 const char *source_filename = ITUI->source_filename; 225 const char * const *command_line_args = ITUI->command_line_args; 226 int num_command_line_args = ITUI->num_command_line_args; 227 struct CXUnsavedFile *unsaved_files = ITUI->unsaved_files; 228 unsigned num_unsaved_files = ITUI->num_unsaved_files; 229 CXTranslationUnit *out_TU = ITUI->out_TU; 230 unsigned TU_options = ITUI->TU_options; 231 ITUI->result = 1; // init as error. 232 233 if (out_TU) 234 *out_TU = 0; 235 bool requestedToGetTU = (out_TU != 0); 236 237 if (!CIdx) 238 return; 239 if (!client_index_callbacks || index_callbacks_size == 0) 240 return; 241 242 IndexerCallbacks CB; 243 memset(&CB, 0, sizeof(CB)); 244 unsigned ClientCBSize = index_callbacks_size < sizeof(CB) 245 ? index_callbacks_size : sizeof(CB); 246 memcpy(&CB, client_index_callbacks, ClientCBSize); 247 248 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); 249 250 (void)CXXIdx; 251 (void)TU_options; 252 253 CaptureDiagnosticConsumer *CaptureDiag = new CaptureDiagnosticConsumer(); 254 255 // Configure the diagnostics. 256 DiagnosticOptions DiagOpts; 257 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> 258 Diags(CompilerInstance::createDiagnostics(DiagOpts, num_command_line_args, 259 command_line_args, 260 CaptureDiag, 261 /*ShouldOwnClient=*/true)); 262 263 // Recover resources if we crash before exiting this function. 264 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, 265 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> > 266 DiagCleanup(Diags.getPtr()); 267 268 llvm::OwningPtr<std::vector<const char *> > 269 Args(new std::vector<const char*>()); 270 271 // Recover resources if we crash before exiting this method. 272 llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> > 273 ArgsCleanup(Args.get()); 274 275 Args->insert(Args->end(), command_line_args, 276 command_line_args + num_command_line_args); 277 278 // The 'source_filename' argument is optional. If the caller does not 279 // specify it then it is assumed that the source file is specified 280 // in the actual argument list. 281 // Put the source file after command_line_args otherwise if '-x' flag is 282 // present it will be unused. 283 if (source_filename) 284 Args->push_back(source_filename); 285 286 llvm::IntrusiveRefCntPtr<CompilerInvocation> 287 CInvok(createInvocationFromCommandLine(*Args, Diags)); 288 289 if (!CInvok) 290 return; 291 292 // Recover resources if we crash before exiting this function. 293 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation, 294 llvm::CrashRecoveryContextReleaseRefCleanup<CompilerInvocation> > 295 CInvokCleanup(CInvok.getPtr()); 296 297 if (CInvok->getFrontendOpts().Inputs.empty()) 298 return; 299 300 llvm::OwningPtr<MemBufferOwner> BufOwner(new MemBufferOwner()); 301 302 // Recover resources if we crash before exiting this method. 303 llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner> 304 BufOwnerCleanup(BufOwner.get()); 305 306 for (unsigned I = 0; I != num_unsaved_files; ++I) { 307 StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length); 308 const llvm::MemoryBuffer *Buffer 309 = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename); 310 CInvok->getPreprocessorOpts().addRemappedFile(unsaved_files[I].Filename, Buffer); 311 BufOwner->Buffers.push_back(Buffer); 312 } 313 314 // Since libclang is primarily used by batch tools dealing with 315 // (often very broken) source code, where spell-checking can have a 316 // significant negative impact on performance (particularly when 317 // precompiled headers are involved), we disable it. 318 CInvok->getLangOpts()->SpellChecking = false; 319 320 if (!requestedToGetTU) 321 CInvok->getPreprocessorOpts().DetailedRecord = false; 322 323 ASTUnit *Unit = ASTUnit::create(CInvok.getPtr(), Diags); 324 llvm::OwningPtr<CXTUOwner> CXTU(new CXTUOwner(MakeCXTranslationUnit(Unit))); 325 326 // Recover resources if we crash before exiting this method. 327 llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner> 328 CXTUCleanup(CXTU.get()); 329 330 llvm::OwningPtr<IndexingFrontendAction> IndexAction; 331 IndexAction.reset(new IndexingFrontendAction(client_data, CB, 332 index_options, CXTU->getTU())); 333 334 // Recover resources if we crash before exiting this method. 335 llvm::CrashRecoveryContextCleanupRegistrar<IndexingFrontendAction> 336 IndexActionCleanup(IndexAction.get()); 337 338 Unit = ASTUnit::LoadFromCompilerInvocationAction(CInvok.getPtr(), Diags, 339 IndexAction.get(), 340 Unit); 341 if (!Unit) 342 return; 343 344 // FIXME: Set state of the ASTUnit according to the TU_options. 345 if (out_TU) 346 *out_TU = CXTU->takeTU(); 347 348 ITUI->result = 0; // success. 349} 350 351//===----------------------------------------------------------------------===// 352// clang_indexTranslationUnit Implementation 353//===----------------------------------------------------------------------===// 354 355namespace { 356 357struct IndexTranslationUnitInfo { 358 CXTranslationUnit TU; 359 CXClientData client_data; 360 IndexerCallbacks *index_callbacks; 361 unsigned index_callbacks_size; 362 unsigned index_options; 363 int result; 364}; 365 366} // anonymous namespace 367 368static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) { 369 Preprocessor &PP = Unit.getPreprocessor(); 370 if (!PP.getPreprocessingRecord()) 371 return; 372 373 PreprocessingRecord &PPRec = *PP.getPreprocessingRecord(); 374 375 // FIXME: Only deserialize inclusion directives. 376 // FIXME: Only deserialize stuff from the last chained PCH, not the PCH/Module 377 // that it depends on. 378 379 bool OnlyLocal = !Unit.isMainFileAST() && Unit.getOnlyLocalDecls(); 380 PreprocessingRecord::iterator I, E; 381 if (OnlyLocal) { 382 I = PPRec.local_begin(); 383 E = PPRec.local_end(); 384 } else { 385 I = PPRec.begin(); 386 E = PPRec.end(); 387 } 388 389 for (; I != E; ++I) { 390 PreprocessedEntity *PPE = *I; 391 392 if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) { 393 IdxCtx.ppIncludedFile(ID->getSourceRange().getBegin(), ID->getFileName(), 394 ID->getFile(), ID->getKind() == InclusionDirective::Import, 395 !ID->wasInQuotes()); 396 } 397 } 398} 399 400static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) { 401 // FIXME: Only deserialize stuff from the last chained PCH, not the PCH/Module 402 // that it depends on. 403 404 bool OnlyLocal = !Unit.isMainFileAST() && Unit.getOnlyLocalDecls(); 405 406 if (OnlyLocal) { 407 for (ASTUnit::top_level_iterator TL = Unit.top_level_begin(), 408 TLEnd = Unit.top_level_end(); 409 TL != TLEnd; ++TL) { 410 IdxCtx.indexTopLevelDecl(*TL); 411 if (IdxCtx.shouldAbort()) 412 return; 413 } 414 415 } else { 416 TranslationUnitDecl *TUDecl = Unit.getASTContext().getTranslationUnitDecl(); 417 for (TranslationUnitDecl::decl_iterator 418 I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; ++I) { 419 IdxCtx.indexTopLevelDecl(*I); 420 if (IdxCtx.shouldAbort()) 421 return; 422 } 423 } 424} 425 426static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) { 427 // FIXME: Create a CXDiagnosticSet from TU; 428 // IdxCtx.handleDiagnosticSet(Set); 429} 430 431static void clang_indexTranslationUnit_Impl(void *UserData) { 432 IndexTranslationUnitInfo *ITUI = 433 static_cast<IndexTranslationUnitInfo*>(UserData); 434 CXTranslationUnit TU = ITUI->TU; 435 CXClientData client_data = ITUI->client_data; 436 IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks; 437 unsigned index_callbacks_size = ITUI->index_callbacks_size; 438 unsigned index_options = ITUI->index_options; 439 ITUI->result = 1; // init as error. 440 441 if (!TU) 442 return; 443 if (!client_index_callbacks || index_callbacks_size == 0) 444 return; 445 446 IndexerCallbacks CB; 447 memset(&CB, 0, sizeof(CB)); 448 unsigned ClientCBSize = index_callbacks_size < sizeof(CB) 449 ? index_callbacks_size : sizeof(CB); 450 memcpy(&CB, client_index_callbacks, ClientCBSize); 451 452 llvm::OwningPtr<IndexingContext> IndexCtx; 453 IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU)); 454 455 // Recover resources if we crash before exiting this method. 456 llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext> 457 IndexCtxCleanup(IndexCtx.get()); 458 459 llvm::OwningPtr<IndexingConsumer> IndexConsumer; 460 IndexConsumer.reset(new IndexingConsumer(*IndexCtx)); 461 462 // Recover resources if we crash before exiting this method. 463 llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer> 464 IndexConsumerCleanup(IndexConsumer.get()); 465 466 ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData); 467 if (!Unit) 468 return; 469 470 FileManager &FileMgr = Unit->getFileManager(); 471 472 if (Unit->getOriginalSourceFileName().empty()) 473 IndexCtx->enteredMainFile(0); 474 else 475 IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName())); 476 477 IndexConsumer->Initialize(Unit->getASTContext()); 478 479 indexPreprocessingRecord(*Unit, *IndexCtx); 480 indexTranslationUnit(*Unit, *IndexCtx); 481 indexDiagnostics(TU, *IndexCtx); 482 483 ITUI->result = 0; 484} 485 486//===----------------------------------------------------------------------===// 487// libclang public APIs. 488//===----------------------------------------------------------------------===// 489 490extern "C" { 491 492int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) { 493 return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory; 494} 495 496const CXIdxObjCContainerDeclInfo * 497clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) { 498 if (!DInfo) 499 return 0; 500 501 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 502 if (const ObjCContainerDeclInfo * 503 ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI)) 504 return &ContInfo->ObjCContDeclInfo; 505 506 return 0; 507} 508 509const CXIdxObjCInterfaceDeclInfo * 510clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) { 511 if (!DInfo) 512 return 0; 513 514 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 515 if (const ObjCInterfaceDeclInfo * 516 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 517 return &InterInfo->ObjCInterDeclInfo; 518 519 return 0; 520} 521 522const CXIdxObjCCategoryDeclInfo * 523clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){ 524 if (!DInfo) 525 return 0; 526 527 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 528 if (const ObjCCategoryDeclInfo * 529 CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI)) 530 return &CatInfo->ObjCCatDeclInfo; 531 532 return 0; 533} 534 535const CXIdxObjCProtocolRefListInfo * 536clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) { 537 if (!DInfo) 538 return 0; 539 540 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo); 541 542 if (const ObjCInterfaceDeclInfo * 543 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI)) 544 return InterInfo->ObjCInterDeclInfo.protocols; 545 546 if (const ObjCProtocolDeclInfo * 547 ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI)) 548 return &ProtInfo->ObjCProtoRefListInfo; 549 550 return 0; 551} 552 553const CXIdxIBOutletCollectionAttrInfo * 554clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) { 555 if (!AInfo) 556 return 0; 557 558 const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo); 559 if (const IBOutletCollectionInfo * 560 IBInfo = dyn_cast<IBOutletCollectionInfo>(DI)) 561 return &IBInfo->IBCollInfo; 562 563 return 0; 564} 565 566int clang_indexSourceFile(CXIndex CIdx, 567 CXClientData client_data, 568 IndexerCallbacks *index_callbacks, 569 unsigned index_callbacks_size, 570 unsigned index_options, 571 const char *source_filename, 572 const char * const *command_line_args, 573 int num_command_line_args, 574 struct CXUnsavedFile *unsaved_files, 575 unsigned num_unsaved_files, 576 CXTranslationUnit *out_TU, 577 unsigned TU_options) { 578 579 IndexSourceFileInfo ITUI = { CIdx, client_data, index_callbacks, 580 index_callbacks_size, index_options, 581 source_filename, command_line_args, 582 num_command_line_args, unsaved_files, 583 num_unsaved_files, out_TU, TU_options, 0 }; 584 585 if (getenv("LIBCLANG_NOTHREADS")) { 586 clang_indexSourceFile_Impl(&ITUI); 587 return ITUI.result; 588 } 589 590 llvm::CrashRecoveryContext CRC; 591 592 if (!RunSafely(CRC, clang_indexSourceFile_Impl, &ITUI)) { 593 fprintf(stderr, "libclang: crash detected during indexing source file: {\n"); 594 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename); 595 fprintf(stderr, " 'command_line_args' : ["); 596 for (int i = 0; i != num_command_line_args; ++i) { 597 if (i) 598 fprintf(stderr, ", "); 599 fprintf(stderr, "'%s'", command_line_args[i]); 600 } 601 fprintf(stderr, "],\n"); 602 fprintf(stderr, " 'unsaved_files' : ["); 603 for (unsigned i = 0; i != num_unsaved_files; ++i) { 604 if (i) 605 fprintf(stderr, ", "); 606 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename, 607 unsaved_files[i].Length); 608 } 609 fprintf(stderr, "],\n"); 610 fprintf(stderr, " 'options' : %d,\n", TU_options); 611 fprintf(stderr, "}\n"); 612 613 return 1; 614 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) { 615 if (out_TU) 616 PrintLibclangResourceUsage(*out_TU); 617 } 618 619 return ITUI.result; 620} 621 622int clang_indexTranslationUnit(CXTranslationUnit TU, 623 CXClientData client_data, 624 IndexerCallbacks *index_callbacks, 625 unsigned index_callbacks_size, 626 unsigned index_options) { 627 628 IndexTranslationUnitInfo ITUI = { TU, client_data, index_callbacks, 629 index_callbacks_size, index_options, 0 }; 630 631 if (getenv("LIBCLANG_NOTHREADS")) { 632 clang_indexTranslationUnit_Impl(&ITUI); 633 return ITUI.result; 634 } 635 636 llvm::CrashRecoveryContext CRC; 637 638 if (!RunSafely(CRC, clang_indexTranslationUnit_Impl, &ITUI)) { 639 fprintf(stderr, "libclang: crash detected during indexing TU\n"); 640 641 return 1; 642 } 643 644 return ITUI.result; 645} 646 647void clang_indexLoc_getFileLocation(CXIdxLoc location, 648 CXIdxClientFile *indexFile, 649 CXFile *file, 650 unsigned *line, 651 unsigned *column, 652 unsigned *offset) { 653 if (indexFile) *indexFile = 0; 654 if (file) *file = 0; 655 if (line) *line = 0; 656 if (column) *column = 0; 657 if (offset) *offset = 0; 658 659 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 660 if (!location.ptr_data[0] || Loc.isInvalid()) 661 return; 662 663 IndexingContext &IndexCtx = 664 *static_cast<IndexingContext*>(location.ptr_data[0]); 665 IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset); 666} 667 668CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) { 669 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data); 670 if (!location.ptr_data[0] || Loc.isInvalid()) 671 return clang_getNullLocation(); 672 673 IndexingContext &IndexCtx = 674 *static_cast<IndexingContext*>(location.ptr_data[0]); 675 return cxloc::translateSourceLocation(IndexCtx.getASTContext(), Loc); 676} 677 678} // end: extern "C" 679 680