1 //===- CIndexHigh.cpp - Higher level API functions ------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "IndexingContext.h"
12 #include "CXSourceLocation.h"
13 #include "CXTranslationUnit.h"
15 #include "CIndexDiagnostic.h"
18 #include "clang/Frontend/ASTUnit.h"
19 #include "clang/Frontend/CompilerInvocation.h"
20 #include "clang/Frontend/CompilerInstance.h"
21 #include "clang/Frontend/FrontendAction.h"
22 #include "clang/Frontend/Utils.h"
23 #include "clang/Sema/SemaConsumer.h"
24 #include "clang/AST/ASTConsumer.h"
25 #include "clang/AST/DeclVisitor.h"
26 #include "clang/Lex/Preprocessor.h"
27 #include "clang/Lex/PPCallbacks.h"
28 #include "llvm/Support/MemoryBuffer.h"
29 #include "llvm/Support/CrashRecoveryContext.h"
31 using namespace clang;
32 using namespace cxstring;
34 using namespace cxindex;
36 static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx);
40 //===----------------------------------------------------------------------===//
42 //===----------------------------------------------------------------------===//
44 class IndexPPCallbacks : public PPCallbacks {
46 IndexingContext &IndexCtx;
47 bool IsMainFileEntered;
50 IndexPPCallbacks(Preprocessor &PP, IndexingContext &indexCtx)
51 : PP(PP), IndexCtx(indexCtx), IsMainFileEntered(false) { }
53 virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason,
54 SrcMgr::CharacteristicKind FileType, FileID PrevFID) {
55 if (IsMainFileEntered)
58 SourceManager &SM = PP.getSourceManager();
59 SourceLocation MainFileLoc = SM.getLocForStartOfFile(SM.getMainFileID());
61 if (Loc == MainFileLoc && Reason == PPCallbacks::EnterFile) {
62 IsMainFileEntered = true;
63 IndexCtx.enteredMainFile(SM.getFileEntryForID(SM.getMainFileID()));
67 virtual void InclusionDirective(SourceLocation HashLoc,
68 const Token &IncludeTok,
71 CharSourceRange FilenameRange,
72 const FileEntry *File,
74 StringRef RelativePath,
75 const Module *Imported) {
76 bool isImport = (IncludeTok.is(tok::identifier) &&
77 IncludeTok.getIdentifierInfo()->getPPKeywordID() == tok::pp_import);
78 IndexCtx.ppIncludedFile(HashLoc, FileName, File, isImport, IsAngled,
82 /// MacroDefined - This hook is called whenever a macro definition is seen.
83 virtual void MacroDefined(const Token &Id, const MacroInfo *MI) {
86 /// MacroUndefined - This hook is called whenever a macro #undef is seen.
87 /// MI is released immediately following this callback.
88 virtual void MacroUndefined(const Token &MacroNameTok, const MacroInfo *MI) {
91 /// MacroExpands - This is called by when a macro invocation is found.
92 virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI,
96 /// SourceRangeSkipped - This hook is called when a source range is skipped.
97 /// \param Range The SourceRange that was skipped. The range begins at the
98 /// #if/#else directive and ends after the #endif/#else directive.
99 virtual void SourceRangeSkipped(SourceRange Range) {
103 //===----------------------------------------------------------------------===//
105 //===----------------------------------------------------------------------===//
107 class IndexingConsumer : public ASTConsumer {
108 IndexingContext &IndexCtx;
111 explicit IndexingConsumer(IndexingContext &indexCtx)
112 : IndexCtx(indexCtx) { }
114 // ASTConsumer Implementation
116 virtual void Initialize(ASTContext &Context) {
117 IndexCtx.setASTContext(Context);
118 IndexCtx.startedTranslationUnit();
121 virtual void HandleTranslationUnit(ASTContext &Ctx) {
124 virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
125 IndexCtx.indexDeclGroupRef(DG);
126 return !IndexCtx.shouldAbort();
129 /// \brief Handle the specified top-level declaration that occurred inside
130 /// and ObjC container.
131 virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {
132 // They will be handled after the interface is seen first.
133 IndexCtx.addTUDeclInObjCContainer(D);
136 /// \brief This is called by the AST reader when deserializing things.
137 /// The default implementation forwards to HandleTopLevelDecl but we don't
138 /// care about them when indexing, so have an empty definition.
139 virtual void HandleInterestingDecl(DeclGroupRef D) {}
141 virtual void HandleTagDeclDefinition(TagDecl *D) {
142 if (!IndexCtx.shouldIndexImplicitTemplateInsts())
145 if (IndexCtx.isTemplateImplicitInstantiation(D))
146 IndexCtx.indexDecl(D);
149 virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {
150 if (!IndexCtx.shouldIndexImplicitTemplateInsts())
153 IndexCtx.indexDecl(D);
157 //===----------------------------------------------------------------------===//
158 // CaptureDiagnosticConsumer
159 //===----------------------------------------------------------------------===//
161 class CaptureDiagnosticConsumer : public DiagnosticConsumer {
162 SmallVector<StoredDiagnostic, 4> Errors;
165 virtual void HandleDiagnostic(DiagnosticsEngine::Level level,
166 const Diagnostic &Info) {
167 if (level >= DiagnosticsEngine::Error)
168 Errors.push_back(StoredDiagnostic(level, Info));
171 DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
172 return new IgnoringDiagConsumer();
176 //===----------------------------------------------------------------------===//
177 // IndexingFrontendAction
178 //===----------------------------------------------------------------------===//
180 class IndexingFrontendAction : public ASTFrontendAction {
181 IndexingContext IndexCtx;
182 CXTranslationUnit CXTU;
185 IndexingFrontendAction(CXClientData clientData,
186 IndexerCallbacks &indexCallbacks,
187 unsigned indexOptions,
188 CXTranslationUnit cxTU)
189 : IndexCtx(clientData, indexCallbacks, indexOptions, cxTU),
192 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
194 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
196 if (!PPOpts.ImplicitPCHInclude.empty()) {
197 IndexCtx.importedPCH(
198 CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude));
201 IndexCtx.setASTContext(CI.getASTContext());
202 Preprocessor &PP = CI.getPreprocessor();
203 PP.addPPCallbacks(new IndexPPCallbacks(PP, IndexCtx));
204 IndexCtx.setPreprocessor(PP);
205 return new IndexingConsumer(IndexCtx);
208 virtual void EndSourceFileAction() {
209 indexDiagnostics(CXTU, IndexCtx);
212 virtual TranslationUnitKind getTranslationUnitKind() {
213 if (IndexCtx.shouldIndexImplicitTemplateInsts())
218 virtual bool hasCodeCompletionSupport() const { return false; }
221 //===----------------------------------------------------------------------===//
222 // clang_indexSourceFileUnit Implementation
223 //===----------------------------------------------------------------------===//
225 struct IndexSourceFileInfo {
226 CXIndexAction idxAction;
227 CXClientData client_data;
228 IndexerCallbacks *index_callbacks;
229 unsigned index_callbacks_size;
230 unsigned index_options;
231 const char *source_filename;
232 const char *const *command_line_args;
233 int num_command_line_args;
234 struct CXUnsavedFile *unsaved_files;
235 unsigned num_unsaved_files;
236 CXTranslationUnit *out_TU;
241 struct MemBufferOwner {
242 SmallVector<const llvm::MemoryBuffer *, 8> Buffers;
245 for (SmallVectorImpl<const llvm::MemoryBuffer *>::iterator
246 I = Buffers.begin(), E = Buffers.end(); I != E; ++I)
251 } // anonymous namespace
253 static void clang_indexSourceFile_Impl(void *UserData) {
254 IndexSourceFileInfo *ITUI =
255 static_cast<IndexSourceFileInfo*>(UserData);
256 CXIndex CIdx = (CXIndex)ITUI->idxAction;
257 CXClientData client_data = ITUI->client_data;
258 IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
259 unsigned index_callbacks_size = ITUI->index_callbacks_size;
260 unsigned index_options = ITUI->index_options;
261 const char *source_filename = ITUI->source_filename;
262 const char * const *command_line_args = ITUI->command_line_args;
263 int num_command_line_args = ITUI->num_command_line_args;
264 struct CXUnsavedFile *unsaved_files = ITUI->unsaved_files;
265 unsigned num_unsaved_files = ITUI->num_unsaved_files;
266 CXTranslationUnit *out_TU = ITUI->out_TU;
267 unsigned TU_options = ITUI->TU_options;
268 ITUI->result = 1; // init as error.
272 bool requestedToGetTU = (out_TU != 0);
276 if (!client_index_callbacks || index_callbacks_size == 0)
280 memset(&CB, 0, sizeof(CB));
281 unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
282 ? index_callbacks_size : sizeof(CB);
283 memcpy(&CB, client_index_callbacks, ClientCBSize);
285 CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
287 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
288 setThreadBackgroundPriority();
290 CaptureDiagnosticConsumer *CaptureDiag = new CaptureDiagnosticConsumer();
292 // Configure the diagnostics.
293 IntrusiveRefCntPtr<DiagnosticsEngine>
294 Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions,
295 num_command_line_args,
298 /*ShouldOwnClient=*/true,
299 /*ShouldCloneClient=*/false));
301 // Recover resources if we crash before exiting this function.
302 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
303 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
304 DiagCleanup(Diags.getPtr());
306 OwningPtr<std::vector<const char *> >
307 Args(new std::vector<const char*>());
309 // Recover resources if we crash before exiting this method.
310 llvm::CrashRecoveryContextCleanupRegistrar<std::vector<const char*> >
311 ArgsCleanup(Args.get());
313 Args->insert(Args->end(), command_line_args,
314 command_line_args + num_command_line_args);
316 // The 'source_filename' argument is optional. If the caller does not
317 // specify it then it is assumed that the source file is specified
318 // in the actual argument list.
319 // Put the source file after command_line_args otherwise if '-x' flag is
320 // present it will be unused.
322 Args->push_back(source_filename);
324 IntrusiveRefCntPtr<CompilerInvocation>
325 CInvok(createInvocationFromCommandLine(*Args, Diags));
330 // Recover resources if we crash before exiting this function.
331 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation,
332 llvm::CrashRecoveryContextReleaseRefCleanup<CompilerInvocation> >
333 CInvokCleanup(CInvok.getPtr());
335 if (CInvok->getFrontendOpts().Inputs.empty())
338 OwningPtr<MemBufferOwner> BufOwner(new MemBufferOwner());
340 // Recover resources if we crash before exiting this method.
341 llvm::CrashRecoveryContextCleanupRegistrar<MemBufferOwner>
342 BufOwnerCleanup(BufOwner.get());
344 for (unsigned I = 0; I != num_unsaved_files; ++I) {
345 StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
346 const llvm::MemoryBuffer *Buffer
347 = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
348 CInvok->getPreprocessorOpts().addRemappedFile(unsaved_files[I].Filename, Buffer);
349 BufOwner->Buffers.push_back(Buffer);
352 // Since libclang is primarily used by batch tools dealing with
353 // (often very broken) source code, where spell-checking can have a
354 // significant negative impact on performance (particularly when
355 // precompiled headers are involved), we disable it.
356 CInvok->getLangOpts()->SpellChecking = false;
358 if (index_options & CXIndexOpt_SuppressWarnings)
359 CInvok->getDiagnosticOpts().IgnoreWarnings = true;
361 ASTUnit *Unit = ASTUnit::create(CInvok.getPtr(), Diags,
362 /*CaptureDiagnostics=*/true,
363 /*UserFilesAreVolatile=*/true);
364 OwningPtr<CXTUOwner> CXTU(new CXTUOwner(MakeCXTranslationUnit(CXXIdx, Unit)));
366 // Recover resources if we crash before exiting this method.
367 llvm::CrashRecoveryContextCleanupRegistrar<CXTUOwner>
368 CXTUCleanup(CXTU.get());
370 OwningPtr<IndexingFrontendAction> IndexAction;
371 IndexAction.reset(new IndexingFrontendAction(client_data, CB,
372 index_options, CXTU->getTU()));
374 // Recover resources if we crash before exiting this method.
375 llvm::CrashRecoveryContextCleanupRegistrar<IndexingFrontendAction>
376 IndexActionCleanup(IndexAction.get());
378 bool Persistent = requestedToGetTU;
379 bool OnlyLocalDecls = false;
380 bool PrecompilePreamble = false;
381 bool CacheCodeCompletionResults = false;
382 PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
383 PPOpts.AllowPCHWithCompilerErrors = true;
385 if (requestedToGetTU) {
386 OnlyLocalDecls = CXXIdx->getOnlyLocalDecls();
387 PrecompilePreamble = TU_options & CXTranslationUnit_PrecompiledPreamble;
388 // FIXME: Add a flag for modules.
389 CacheCodeCompletionResults
390 = TU_options & CXTranslationUnit_CacheCompletionResults;
393 if (TU_options & CXTranslationUnit_DetailedPreprocessingRecord) {
394 PPOpts.DetailedRecord = true;
397 if (!requestedToGetTU && !CInvok->getLangOpts()->Modules)
398 PPOpts.DetailedRecord = false;
400 DiagnosticErrorTrap DiagTrap(*Diags);
401 bool Success = ASTUnit::LoadFromCompilerInvocationAction(CInvok.getPtr(), Diags,
405 CXXIdx->getClangResourcesPath(),
407 /*CaptureDiagnostics=*/true,
409 CacheCodeCompletionResults,
410 /*IncludeBriefCommentsInCodeCompletion=*/false,
411 /*UserFilesAreVolatile=*/true);
412 if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
413 printDiagsToStderr(Unit);
419 *out_TU = CXTU->takeTU();
421 ITUI->result = 0; // success.
424 //===----------------------------------------------------------------------===//
425 // clang_indexTranslationUnit Implementation
426 //===----------------------------------------------------------------------===//
430 struct IndexTranslationUnitInfo {
431 CXIndexAction idxAction;
432 CXClientData client_data;
433 IndexerCallbacks *index_callbacks;
434 unsigned index_callbacks_size;
435 unsigned index_options;
436 CXTranslationUnit TU;
440 } // anonymous namespace
442 static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
443 Preprocessor &PP = Unit.getPreprocessor();
444 if (!PP.getPreprocessingRecord())
447 // FIXME: Only deserialize inclusion directives.
449 PreprocessingRecord::iterator I, E;
450 llvm::tie(I, E) = Unit.getLocalPreprocessingEntities();
452 bool isModuleFile = Unit.isModuleFile();
453 for (; I != E; ++I) {
454 PreprocessedEntity *PPE = *I;
456 if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
457 SourceLocation Loc = ID->getSourceRange().getBegin();
458 // Modules have synthetic main files as input, give an invalid location
459 // if the location points to such a file.
460 if (isModuleFile && Unit.isInMainFileID(Loc))
461 Loc = SourceLocation();
462 IdxCtx.ppIncludedFile(Loc, ID->getFileName(),
464 ID->getKind() == InclusionDirective::Import,
465 !ID->wasInQuotes(), ID->importedModule());
470 static bool topLevelDeclVisitor(void *context, const Decl *D) {
471 IndexingContext &IdxCtx = *static_cast<IndexingContext*>(context);
472 IdxCtx.indexTopLevelDecl(D);
473 if (IdxCtx.shouldAbort())
478 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) {
479 Unit.visitLocalTopLevelDecls(&IdxCtx, topLevelDeclVisitor);
482 static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) {
483 if (!IdxCtx.hasDiagnosticCallback())
486 CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(TU);
487 IdxCtx.handleDiagnosticSet(DiagSet);
490 static void clang_indexTranslationUnit_Impl(void *UserData) {
491 IndexTranslationUnitInfo *ITUI =
492 static_cast<IndexTranslationUnitInfo*>(UserData);
493 CXTranslationUnit TU = ITUI->TU;
494 CXClientData client_data = ITUI->client_data;
495 IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
496 unsigned index_callbacks_size = ITUI->index_callbacks_size;
497 unsigned index_options = ITUI->index_options;
498 ITUI->result = 1; // init as error.
502 if (!client_index_callbacks || index_callbacks_size == 0)
505 CIndexer *CXXIdx = (CIndexer*)TU->CIdx;
506 if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForIndexing))
507 setThreadBackgroundPriority();
510 memset(&CB, 0, sizeof(CB));
511 unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
512 ? index_callbacks_size : sizeof(CB);
513 memcpy(&CB, client_index_callbacks, ClientCBSize);
515 OwningPtr<IndexingContext> IndexCtx;
516 IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU));
518 // Recover resources if we crash before exiting this method.
519 llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext>
520 IndexCtxCleanup(IndexCtx.get());
522 OwningPtr<IndexingConsumer> IndexConsumer;
523 IndexConsumer.reset(new IndexingConsumer(*IndexCtx));
525 // Recover resources if we crash before exiting this method.
526 llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer>
527 IndexConsumerCleanup(IndexConsumer.get());
529 ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);
533 ASTUnit::ConcurrencyCheck Check(*Unit);
535 if (const FileEntry *PCHFile = Unit->getPCHFile())
536 IndexCtx->importedPCH(PCHFile);
538 FileManager &FileMgr = Unit->getFileManager();
540 if (Unit->getOriginalSourceFileName().empty())
541 IndexCtx->enteredMainFile(0);
543 IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
545 IndexConsumer->Initialize(Unit->getASTContext());
547 indexPreprocessingRecord(*Unit, *IndexCtx);
548 indexTranslationUnit(*Unit, *IndexCtx);
549 indexDiagnostics(TU, *IndexCtx);
554 //===----------------------------------------------------------------------===//
555 // libclang public APIs.
556 //===----------------------------------------------------------------------===//
560 int clang_index_isEntityObjCContainerKind(CXIdxEntityKind K) {
561 return CXIdxEntity_ObjCClass <= K && K <= CXIdxEntity_ObjCCategory;
564 const CXIdxObjCContainerDeclInfo *
565 clang_index_getObjCContainerDeclInfo(const CXIdxDeclInfo *DInfo) {
569 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
570 if (const ObjCContainerDeclInfo *
571 ContInfo = dyn_cast<ObjCContainerDeclInfo>(DI))
572 return &ContInfo->ObjCContDeclInfo;
577 const CXIdxObjCInterfaceDeclInfo *
578 clang_index_getObjCInterfaceDeclInfo(const CXIdxDeclInfo *DInfo) {
582 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
583 if (const ObjCInterfaceDeclInfo *
584 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
585 return &InterInfo->ObjCInterDeclInfo;
590 const CXIdxObjCCategoryDeclInfo *
591 clang_index_getObjCCategoryDeclInfo(const CXIdxDeclInfo *DInfo){
595 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
596 if (const ObjCCategoryDeclInfo *
597 CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
598 return &CatInfo->ObjCCatDeclInfo;
603 const CXIdxObjCProtocolRefListInfo *
604 clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *DInfo) {
608 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
610 if (const ObjCInterfaceDeclInfo *
611 InterInfo = dyn_cast<ObjCInterfaceDeclInfo>(DI))
612 return InterInfo->ObjCInterDeclInfo.protocols;
614 if (const ObjCProtocolDeclInfo *
615 ProtInfo = dyn_cast<ObjCProtocolDeclInfo>(DI))
616 return &ProtInfo->ObjCProtoRefListInfo;
618 if (const ObjCCategoryDeclInfo *CatInfo = dyn_cast<ObjCCategoryDeclInfo>(DI))
619 return CatInfo->ObjCCatDeclInfo.protocols;
624 const CXIdxObjCPropertyDeclInfo *
625 clang_index_getObjCPropertyDeclInfo(const CXIdxDeclInfo *DInfo) {
629 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
630 if (const ObjCPropertyDeclInfo *PropInfo = dyn_cast<ObjCPropertyDeclInfo>(DI))
631 return &PropInfo->ObjCPropDeclInfo;
636 const CXIdxIBOutletCollectionAttrInfo *
637 clang_index_getIBOutletCollectionAttrInfo(const CXIdxAttrInfo *AInfo) {
641 const AttrInfo *DI = static_cast<const AttrInfo *>(AInfo);
642 if (const IBOutletCollectionInfo *
643 IBInfo = dyn_cast<IBOutletCollectionInfo>(DI))
644 return &IBInfo->IBCollInfo;
649 const CXIdxCXXClassDeclInfo *
650 clang_index_getCXXClassDeclInfo(const CXIdxDeclInfo *DInfo) {
654 const DeclInfo *DI = static_cast<const DeclInfo *>(DInfo);
655 if (const CXXClassDeclInfo *ClassInfo = dyn_cast<CXXClassDeclInfo>(DI))
656 return &ClassInfo->CXXClassInfo;
662 clang_index_getClientContainer(const CXIdxContainerInfo *info) {
665 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
666 return Container->IndexCtx->getClientContainerForDC(Container->DC);
669 void clang_index_setClientContainer(const CXIdxContainerInfo *info,
670 CXIdxClientContainer client) {
673 const ContainerInfo *Container = static_cast<const ContainerInfo *>(info);
674 Container->IndexCtx->addContainerInMap(Container->DC, client);
677 CXIdxClientEntity clang_index_getClientEntity(const CXIdxEntityInfo *info) {
680 const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
681 return Entity->IndexCtx->getClientEntity(Entity->Dcl);
684 void clang_index_setClientEntity(const CXIdxEntityInfo *info,
685 CXIdxClientEntity client) {
688 const EntityInfo *Entity = static_cast<const EntityInfo *>(info);
689 Entity->IndexCtx->setClientEntity(Entity->Dcl, client);
692 CXIndexAction clang_IndexAction_create(CXIndex CIdx) {
693 // For now, CXIndexAction is featureless.
697 void clang_IndexAction_dispose(CXIndexAction idxAction) {
698 // For now, CXIndexAction is featureless.
701 int clang_indexSourceFile(CXIndexAction idxAction,
702 CXClientData client_data,
703 IndexerCallbacks *index_callbacks,
704 unsigned index_callbacks_size,
705 unsigned index_options,
706 const char *source_filename,
707 const char * const *command_line_args,
708 int num_command_line_args,
709 struct CXUnsavedFile *unsaved_files,
710 unsigned num_unsaved_files,
711 CXTranslationUnit *out_TU,
712 unsigned TU_options) {
714 IndexSourceFileInfo ITUI = { idxAction, client_data, index_callbacks,
715 index_callbacks_size, index_options,
716 source_filename, command_line_args,
717 num_command_line_args, unsaved_files,
718 num_unsaved_files, out_TU, TU_options, 0 };
720 if (getenv("LIBCLANG_NOTHREADS")) {
721 clang_indexSourceFile_Impl(&ITUI);
725 llvm::CrashRecoveryContext CRC;
727 if (!RunSafely(CRC, clang_indexSourceFile_Impl, &ITUI)) {
728 fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
729 fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
730 fprintf(stderr, " 'command_line_args' : [");
731 for (int i = 0; i != num_command_line_args; ++i) {
733 fprintf(stderr, ", ");
734 fprintf(stderr, "'%s'", command_line_args[i]);
736 fprintf(stderr, "],\n");
737 fprintf(stderr, " 'unsaved_files' : [");
738 for (unsigned i = 0; i != num_unsaved_files; ++i) {
740 fprintf(stderr, ", ");
741 fprintf(stderr, "('%s', '...', %ld)", unsaved_files[i].Filename,
742 unsaved_files[i].Length);
744 fprintf(stderr, "],\n");
745 fprintf(stderr, " 'options' : %d,\n", TU_options);
746 fprintf(stderr, "}\n");
749 } else if (getenv("LIBCLANG_RESOURCE_USAGE")) {
751 PrintLibclangResourceUsage(*out_TU);
757 int clang_indexTranslationUnit(CXIndexAction idxAction,
758 CXClientData client_data,
759 IndexerCallbacks *index_callbacks,
760 unsigned index_callbacks_size,
761 unsigned index_options,
762 CXTranslationUnit TU) {
764 IndexTranslationUnitInfo ITUI = { idxAction, client_data, index_callbacks,
765 index_callbacks_size, index_options, TU,
768 if (getenv("LIBCLANG_NOTHREADS")) {
769 clang_indexTranslationUnit_Impl(&ITUI);
773 llvm::CrashRecoveryContext CRC;
775 if (!RunSafely(CRC, clang_indexTranslationUnit_Impl, &ITUI)) {
776 fprintf(stderr, "libclang: crash detected during indexing TU\n");
784 void clang_indexLoc_getFileLocation(CXIdxLoc location,
785 CXIdxClientFile *indexFile,
790 if (indexFile) *indexFile = 0;
793 if (column) *column = 0;
794 if (offset) *offset = 0;
796 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
797 if (!location.ptr_data[0] || Loc.isInvalid())
800 IndexingContext &IndexCtx =
801 *static_cast<IndexingContext*>(location.ptr_data[0]);
802 IndexCtx.translateLoc(Loc, indexFile, file, line, column, offset);
805 CXSourceLocation clang_indexLoc_getCXSourceLocation(CXIdxLoc location) {
806 SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
807 if (!location.ptr_data[0] || Loc.isInvalid())
808 return clang_getNullLocation();
810 IndexingContext &IndexCtx =
811 *static_cast<IndexingContext*>(location.ptr_data[0]);
812 return cxloc::translateSourceLocation(IndexCtx.getASTContext(), Loc);