typedef struct {
const CXIdxObjCContainerDeclInfo *containerInfo;
const CXIdxEntityInfo *objcClass;
+ CXCursor classCursor;
+ CXIdxLoc classLoc;
} CXIdxObjCCategoryDeclInfo;
typedef struct {
CINDEX_LINKAGE const CXIdxObjCProtocolRefListInfo *
clang_index_getObjCProtocolRefListInfo(const CXIdxDeclInfo *);
+typedef enum {
+ /**
+ * \brief Used to indicate that no special indexing options are needed.
+ */
+ CXIndexOpt_None = 0x0,
+
+ /**
+ * \brief Used to indicate that \see indexEntityReference should be invoked
+ * for only one reference of an entity per source file.
+ */
+ CXIndexOpt_OneRefPerFile = 0x1
+} CXIndexOptFlags;
+
/**
* \brief Index the given source file and the translation unit corresponding
* to that file via callbacks implemented through \see IndexerCallbacks.
* \param index_callbacks_size Size of \see IndexerCallbacks structure that gets
* passed in index_callbacks.
*
- * \param index_options Options affecting indexing; reserved.
+ * \param index_options A bitmask of options that affects how indexing is
+ * performed. This should be a bitwise OR of the CXIndexOpt_XXX flags.
*
* \param out_TU [out] pointer to store a CXTranslationUnit that can be reused
* after indexing is finished. Set to NULL if you do not require it.
*
- * \returns If there is a failure from which the compiler cannot recover returns
+ * \returns If there is a failure from which the there is no recovery, returns
* non-zero, otherwise returns 0.
- *
+ *
* The rest of the parameters are the same as \see clang_parseTranslationUnit.
*/
-CINDEX_LINKAGE int clang_indexTranslationUnit(CXIndex CIdx,
+CINDEX_LINKAGE int clang_indexSourceFile(CXIndex CIdx,
CXClientData client_data,
IndexerCallbacks *index_callbacks,
unsigned index_callbacks_size,
CXTranslationUnit *out_TU,
unsigned TU_options);
+/**
+ * \brief Index the given translation unit via callbacks implemented through
+ * \see IndexerCallbacks.
+ *
+ * The order of callback invocations is not guaranteed to be the same as
+ * when indexing a source file. The high level order will be:
+ *
+ * -Preprocessor callbacks invocations
+ * -Declaration/reference callbacks invocations
+ * -Diagnostic callback invocations
+ *
+ * The parameters are the same as \see clang_indexSourceFile.
+ *
+ * \returns If there is a failure from which the there is no recovery, returns
+ * non-zero, otherwise returns 0.
+ */
+CINDEX_LINKAGE int clang_indexTranslationUnit(CXTranslationUnit,
+ CXClientData client_data,
+ IndexerCallbacks *index_callbacks,
+ unsigned index_callbacks_size,
+ unsigned index_options);
+
/**
* \brief Retrieve the CXIdxFile, file, line, column, and offset represented by
* the given CXIdxLoc.
if ((CatInfo = clang_index_getObjCCategoryDeclInfo(info))) {
printEntityInfo(" <ObjCCategoryInfo>: class", client_data,
CatInfo->objcClass);
+ printf(" | cursor: ");
+ PrintCursor(CatInfo->classCursor);
+ printf(" | loc: ");
+ printCXIndexLoc(CatInfo->classLoc);
printf("\n");
}
index_data.first_check_printed = 0;
index_data.fail_for_error = 0;
- result = clang_indexTranslationUnit(CIdx, &index_data,
- &IndexCB,sizeof(IndexCB),
- 0, 0, argv, argc, 0, 0, 0, 0);
+ result = clang_indexSourceFile(CIdx, &index_data,
+ &IndexCB,sizeof(IndexCB),
+ 0, 0, argv, argc, 0, 0, 0, 0);
+ if (index_data.fail_for_error)
+ return -1;
+
+ return result;
+}
+
+static int index_tu(int argc, const char **argv) {
+ CXIndex Idx;
+ CXTranslationUnit TU;
+ const char *check_prefix;
+ IndexData index_data;
+ int result;
+
+ check_prefix = 0;
+ if (argc > 0) {
+ if (strstr(argv[0], "-check-prefix=") == argv[0]) {
+ check_prefix = argv[0] + strlen("-check-prefix=");
+ ++argv;
+ --argc;
+ }
+ }
+
+ if (argc == 0) {
+ fprintf(stderr, "no ast file\n");
+ return -1;
+ }
+
+ if (!(Idx = clang_createIndex(/* excludeDeclsFromPCH */ 1,
+ /* displayDiagnosics=*/1))) {
+ fprintf(stderr, "Could not create Index\n");
+ return 1;
+ }
+
+ if (!CreateTranslationUnit(Idx, argv[0], &TU))
+ return 1;
+
+ index_data.check_prefix = check_prefix;
+ index_data.first_check_printed = 0;
+ index_data.fail_for_error = 0;
+
+ result = clang_indexTranslationUnit(TU, &index_data,
+ &IndexCB,sizeof(IndexCB), 0);
if (index_data.fail_for_error)
return -1;
" c-index-test -cursor-at=<site> <compiler arguments>\n"
" c-index-test -file-refs-at=<site> <compiler arguments>\n"
" c-index-test -index-file [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
+ " c-index-test -index-tu [-check-prefix=<FileCheck prefix>] <AST file>\n"
" c-index-test -test-file-scan <AST file> <source file> "
"[FileCheck prefix]\n");
fprintf(stderr,
return find_file_refs_at(argc, argv);
if (argc > 2 && strcmp(argv[1], "-index-file") == 0)
return index_file(argc - 2, argv + 2);
+ if (argc > 2 && strcmp(argv[1], "-index-tu") == 0)
+ return index_tu(argc - 2, argv + 2);
else if (argc >= 4 && strncmp(argv[1], "-test-load-tu", 13) == 0) {
CXCursorVisitor I = GetVisitor(argv[1] + 13);
if (I)
};
//===----------------------------------------------------------------------===//
-// clang_indexTranslationUnit Implementation
+// clang_indexSourceFileUnit Implementation
//===----------------------------------------------------------------------===//
-struct IndexTranslationUnitInfo {
+struct IndexSourceFileInfo {
CXIndex CIdx;
CXClientData client_data;
IndexerCallbacks *index_callbacks;
} // 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;
ITUI->result = 0; // success.
}
+//===----------------------------------------------------------------------===//
+// 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.
//===----------------------------------------------------------------------===//
return 0;
}
-int clang_indexTranslationUnit(CXIndex CIdx,
+int clang_indexSourceFile(CXIndex CIdx,
CXClientData client_data,
IndexerCallbacks *index_callbacks,
unsigned index_callbacks_size,
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) {
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,