[libclang] Introduce a new function to apply the indexing callbacks on an existing
CXTranslationUnit, mainly to be used for indexing a PCH.
llvm-svn: 144623
diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp
index 3332c65..1eb3da2 100644
--- a/clang/tools/libclang/Indexing.cpp
+++ b/clang/tools/libclang/Indexing.cpp
@@ -200,10 +200,10 @@
};
//===----------------------------------------------------------------------===//
-// clang_indexTranslationUnit Implementation
+// clang_indexSourceFileUnit Implementation
//===----------------------------------------------------------------------===//
-struct IndexTranslationUnitInfo {
+struct IndexSourceFileInfo {
CXIndex CIdx;
CXClientData client_data;
IndexerCallbacks *index_callbacks;
@@ -231,9 +231,9 @@
} // anonymous namespace
-static void clang_indexTranslationUnit_Impl(void *UserData) {
- IndexTranslationUnitInfo *ITUI =
- static_cast<IndexTranslationUnitInfo*>(UserData);
+static void clang_indexSourceFile_Impl(void *UserData) {
+ IndexSourceFileInfo *ITUI =
+ static_cast<IndexSourceFileInfo*>(UserData);
CXIndex CIdx = ITUI->CIdx;
CXClientData client_data = ITUI->client_data;
IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
@@ -367,6 +367,141 @@
}
//===----------------------------------------------------------------------===//
+// clang_indexTranslationUnit Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+struct IndexTranslationUnitInfo {
+ CXTranslationUnit TU;
+ CXClientData client_data;
+ IndexerCallbacks *index_callbacks;
+ unsigned index_callbacks_size;
+ unsigned index_options;
+ int result;
+};
+
+} // anonymous namespace
+
+static void indexPreprocessingRecord(ASTUnit &Unit, IndexingContext &IdxCtx) {
+ Preprocessor &PP = Unit.getPreprocessor();
+ if (!PP.getPreprocessingRecord())
+ return;
+
+ PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
+
+ // FIXME: Only deserialize inclusion directives.
+ // FIXME: Only deserialize stuff from the last chained PCH, not the PCH/Module
+ // that it depends on.
+
+ bool OnlyLocal = !Unit.isMainFileAST() && Unit.getOnlyLocalDecls();
+ PreprocessingRecord::iterator I, E;
+ if (OnlyLocal) {
+ I = PPRec.local_begin();
+ E = PPRec.local_end();
+ } else {
+ I = PPRec.begin();
+ E = PPRec.end();
+ }
+
+ for (; I != E; ++I) {
+ PreprocessedEntity *PPE = *I;
+
+ if (InclusionDirective *ID = dyn_cast<InclusionDirective>(PPE)) {
+ IdxCtx.ppIncludedFile(ID->getSourceRange().getBegin(), ID->getFileName(),
+ ID->getFile(), ID->getKind() == InclusionDirective::Import,
+ !ID->wasInQuotes());
+ }
+ }
+}
+
+static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IdxCtx) {
+ // FIXME: Only deserialize stuff from the last chained PCH, not the PCH/Module
+ // that it depends on.
+
+ bool OnlyLocal = !Unit.isMainFileAST() && Unit.getOnlyLocalDecls();
+
+ if (OnlyLocal) {
+ for (ASTUnit::top_level_iterator TL = Unit.top_level_begin(),
+ TLEnd = Unit.top_level_end();
+ TL != TLEnd; ++TL) {
+ IdxCtx.indexTopLevelDecl(*TL);
+ }
+
+ } else {
+ TranslationUnitDecl *TUDecl = Unit.getASTContext().getTranslationUnitDecl();
+ for (TranslationUnitDecl::decl_iterator
+ I = TUDecl->decls_begin(), E = TUDecl->decls_end(); I != E; ++I) {
+ IdxCtx.indexTopLevelDecl(*I);
+ }
+ }
+}
+
+static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx) {
+ unsigned Num = clang_getNumDiagnostics(TU);
+ for (unsigned i = 0; i != Num; ++i) {
+ CXDiagnostic Diag = clang_getDiagnostic(TU, i);
+ IdxCtx.handleDiagnostic(Diag);
+ clang_disposeDiagnostic(Diag);
+ }
+}
+
+static void clang_indexTranslationUnit_Impl(void *UserData) {
+ IndexTranslationUnitInfo *ITUI =
+ static_cast<IndexTranslationUnitInfo*>(UserData);
+ CXTranslationUnit TU = ITUI->TU;
+ CXClientData client_data = ITUI->client_data;
+ IndexerCallbacks *client_index_callbacks = ITUI->index_callbacks;
+ unsigned index_callbacks_size = ITUI->index_callbacks_size;
+ unsigned index_options = ITUI->index_options;
+ ITUI->result = 1; // init as error.
+
+ if (!TU)
+ return;
+ if (!client_index_callbacks || index_callbacks_size == 0)
+ return;
+
+ IndexerCallbacks CB;
+ memset(&CB, 0, sizeof(CB));
+ unsigned ClientCBSize = index_callbacks_size < sizeof(CB)
+ ? index_callbacks_size : sizeof(CB);
+ memcpy(&CB, client_index_callbacks, ClientCBSize);
+
+ llvm::OwningPtr<IndexingContext> IndexCtx;
+ IndexCtx.reset(new IndexingContext(client_data, CB, index_options, TU));
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<IndexingContext>
+ IndexCtxCleanup(IndexCtx.get());
+
+ llvm::OwningPtr<IndexingConsumer> IndexConsumer;
+ IndexConsumer.reset(new IndexingConsumer(*IndexCtx));
+
+ // Recover resources if we crash before exiting this method.
+ llvm::CrashRecoveryContextCleanupRegistrar<IndexingConsumer>
+ IndexConsumerCleanup(IndexConsumer.get());
+
+ ASTUnit *Unit = static_cast<ASTUnit *>(TU->TUData);
+ if (!Unit)
+ return;
+
+ FileManager &FileMgr = Unit->getFileManager();
+
+ if (Unit->getOriginalSourceFileName().empty())
+ IndexCtx->enteredMainFile(0);
+ else
+ IndexCtx->enteredMainFile(FileMgr.getFile(Unit->getOriginalSourceFileName()));
+
+ IndexConsumer->Initialize(Unit->getASTContext());
+
+ indexPreprocessingRecord(*Unit, *IndexCtx);
+ indexTranslationUnit(*Unit, *IndexCtx);
+ indexDiagnostics(TU, *IndexCtx);
+
+ ITUI->result = 0;
+}
+
+//===----------------------------------------------------------------------===//
// libclang public APIs.
//===----------------------------------------------------------------------===//
@@ -433,7 +568,7 @@
return 0;
}
-int clang_indexTranslationUnit(CXIndex CIdx,
+int clang_indexSourceFile(CXIndex CIdx,
CXClientData client_data,
IndexerCallbacks *index_callbacks,
unsigned index_callbacks_size,
@@ -445,21 +580,22 @@
unsigned num_unsaved_files,
CXTranslationUnit *out_TU,
unsigned TU_options) {
- IndexTranslationUnitInfo ITUI = { CIdx, client_data, index_callbacks,
+
+ IndexSourceFileInfo ITUI = { CIdx, client_data, index_callbacks,
index_callbacks_size, index_options,
source_filename, command_line_args,
num_command_line_args, unsaved_files,
num_unsaved_files, out_TU, TU_options, 0 };
if (getenv("LIBCLANG_NOTHREADS")) {
- clang_indexTranslationUnit_Impl(&ITUI);
+ clang_indexSourceFile_Impl(&ITUI);
return ITUI.result;
}
llvm::CrashRecoveryContext CRC;
- if (!RunSafely(CRC, clang_indexTranslationUnit_Impl, &ITUI)) {
- fprintf(stderr, "libclang: crash detected during parsing: {\n");
+ if (!RunSafely(CRC, clang_indexSourceFile_Impl, &ITUI)) {
+ fprintf(stderr, "libclang: crash detected during indexing source file: {\n");
fprintf(stderr, " 'source_filename' : '%s'\n", source_filename);
fprintf(stderr, " 'command_line_args' : [");
for (int i = 0; i != num_command_line_args; ++i) {
@@ -488,6 +624,31 @@
return ITUI.result;
}
+int clang_indexTranslationUnit(CXTranslationUnit TU,
+ CXClientData client_data,
+ IndexerCallbacks *index_callbacks,
+ unsigned index_callbacks_size,
+ unsigned index_options) {
+
+ IndexTranslationUnitInfo ITUI = { TU, client_data, index_callbacks,
+ index_callbacks_size, index_options, 0 };
+
+ if (getenv("LIBCLANG_NOTHREADS")) {
+ clang_indexTranslationUnit_Impl(&ITUI);
+ return ITUI.result;
+ }
+
+ llvm::CrashRecoveryContext CRC;
+
+ if (!RunSafely(CRC, clang_indexTranslationUnit_Impl, &ITUI)) {
+ fprintf(stderr, "libclang: crash detected during indexing TU\n");
+
+ return 1;
+ }
+
+ return ITUI.result;
+}
+
void clang_indexLoc_getFileLocation(CXIdxLoc location,
CXIdxClientFile *indexFile,
CXFile *file,