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