summaryrefslogtreecommitdiffstats
path: root/clang/tools
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2013-03-08 02:32:34 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2013-03-08 02:32:34 +0000
commit503c83ad819a8d396448a5243ee0637bc56343ad (patch)
treee1bf3bd8ad60350cbed5407a019d6829432eb6f9 /clang/tools
parent733136952e0eb4031a1206dfb836948baec78c81 (diff)
downloadbcm5719-llvm-503c83ad819a8d396448a5243ee0637bc56343ad.tar.gz
bcm5719-llvm-503c83ad819a8d396448a5243ee0637bc56343ad.zip
[libclang] Introduce clang_findIncludesInFile, that can be used to retrieve all #import/#include directives in a specific file.
It passes to the visitor, that the caller provides, CXCursor_InclusionDirective cursors for all the include directives in a particular file. llvm-svn: 176682
Diffstat (limited to 'clang/tools')
-rw-r--r--clang/tools/c-index-test/c-index-test.c98
-rw-r--r--clang/tools/libclang/CIndexHigh.cpp106
-rw-r--r--clang/tools/libclang/libclang.exports2
3 files changed, 205 insertions, 1 deletions
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index 72a8c74fc02..b749bf50e96 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -2135,6 +2135,99 @@ static int find_file_refs_at(int argc, const char **argv) {
return 0;
}
+static enum CXVisitorResult findFileIncludesVisit(void *context,
+ CXCursor cursor, CXSourceRange range) {
+ PrintCursor(cursor, NULL);
+ PrintRange(range, "");
+ printf("\n");
+ return CXVisit_Continue;
+}
+
+static int find_file_includes_in(int argc, const char **argv) {
+ CXIndex CIdx;
+ struct CXUnsavedFile *unsaved_files = 0;
+ int num_unsaved_files = 0;
+ CXTranslationUnit TU;
+ const char **Filenames = 0;
+ unsigned NumFilenames = 0;
+ unsigned Repeats = 1;
+ unsigned I, FI;
+
+ /* Count the number of locations. */
+ while (strstr(argv[NumFilenames+1], "-file-includes-in=") == argv[NumFilenames+1])
+ ++NumFilenames;
+
+ /* Parse the locations. */
+ assert(NumFilenames > 0 && "Unable to count filenames?");
+ Filenames = (const char **)malloc(NumFilenames * sizeof(const char *));
+ for (I = 0; I < NumFilenames; ++I) {
+ const char *input = argv[I + 1] + strlen("-file-includes-in=");
+ /* Copy the file name. */
+ Filenames[I] = input;
+ }
+
+ if (parse_remapped_files(argc, argv, NumFilenames + 1, &unsaved_files,
+ &num_unsaved_files))
+ return -1;
+
+ if (getenv("CINDEXTEST_EDITING"))
+ Repeats = 2;
+
+ /* Parse the translation unit. When we're testing clang_getCursor() after
+ reparsing, don't remap unsaved files until the second parse. */
+ CIdx = clang_createIndex(1, 1);
+ TU = clang_parseTranslationUnit(CIdx, argv[argc - 1],
+ argv + num_unsaved_files + 1 + NumFilenames,
+ argc - num_unsaved_files - 2 - NumFilenames,
+ unsaved_files,
+ Repeats > 1? 0 : num_unsaved_files,
+ getDefaultParsingOptions());
+
+ if (!TU) {
+ fprintf(stderr, "unable to parse input\n");
+ return -1;
+ }
+
+ if (checkForErrors(TU) != 0)
+ return -1;
+
+ for (I = 0; I != Repeats; ++I) {
+ if (Repeats > 1 &&
+ clang_reparseTranslationUnit(TU, num_unsaved_files, unsaved_files,
+ clang_defaultReparseOptions(TU))) {
+ clang_disposeTranslationUnit(TU);
+ return 1;
+ }
+
+ if (checkForErrors(TU) != 0)
+ return -1;
+
+ for (FI = 0; FI < NumFilenames; ++FI) {
+ CXFile file = clang_getFile(TU, Filenames[FI]);
+ if (!file)
+ continue;
+
+ if (checkForErrors(TU) != 0)
+ return -1;
+
+ if (I + 1 == Repeats) {
+ CXCursorAndRangeVisitor visitor = { 0, findFileIncludesVisit };
+ clang_findIncludesInFile(TU, file, visitor);
+
+ if (checkForErrors(TU) != 0)
+ return -1;
+ }
+ }
+ }
+
+ PrintDiagnostics(TU);
+ clang_disposeTranslationUnit(TU);
+ clang_disposeIndex(CIdx);
+ free(Filenames);
+ free_remapped_files(unsaved_files, num_unsaved_files);
+ return 0;
+}
+
#define MAX_IMPORTED_ASTFILES 200
typedef struct {
@@ -3520,7 +3613,8 @@ static void print_usage(void) {
"usage: c-index-test -code-completion-at=<site> <compiler arguments>\n"
" c-index-test -code-completion-timing=<site> <compiler arguments>\n"
" c-index-test -cursor-at=<site> <compiler arguments>\n"
- " c-index-test -file-refs-at=<site> <compiler arguments>\n");
+ " c-index-test -file-refs-at=<site> <compiler arguments>\n"
+ " c-index-test -file-includes-in=<filename> <compiler arguments>\n");
fprintf(stderr,
" c-index-test -index-file [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
" c-index-test -index-file-full [-check-prefix=<FileCheck prefix>] <compiler arguments>\n"
@@ -3582,6 +3676,8 @@ int cindextest_main(int argc, const char **argv) {
return inspect_cursor_at(argc, argv);
if (argc > 2 && strstr(argv[1], "-file-refs-at=") == argv[1])
return find_file_refs_at(argc, argv);
+ if (argc > 2 && strstr(argv[1], "-file-includes-in=") == argv[1])
+ return find_file_includes_in(argc, argv);
if (argc > 2 && strcmp(argv[1], "-index-file") == 0)
return index_file(argc - 2, argv + 2, /*full=*/0);
if (argc > 2 && strcmp(argv[1], "-index-file-full") == 0)
diff --git a/clang/tools/libclang/CIndexHigh.cpp b/clang/tools/libclang/CIndexHigh.cpp
index 7e123868419..6af55e8eb7f 100644
--- a/clang/tools/libclang/CIndexHigh.cpp
+++ b/clang/tools/libclang/CIndexHigh.cpp
@@ -337,6 +337,72 @@ static void findMacroRefsInFile(CXTranslationUnit TU, CXCursor Cursor,
FindMacroRefsVisitor.visitPreprocessedEntitiesInRegion();
}
+namespace {
+
+struct FindFileIncludesVisitor {
+ ASTUnit &Unit;
+ const FileEntry *File;
+ CXCursorAndRangeVisitor visitor;
+
+ FindFileIncludesVisitor(ASTUnit &Unit, const FileEntry *File,
+ CXCursorAndRangeVisitor visitor)
+ : Unit(Unit), File(File), visitor(visitor) { }
+
+ ASTContext &getASTContext() const {
+ return Unit.getASTContext();
+ }
+
+ enum CXChildVisitResult visit(CXCursor cursor, CXCursor parent) {
+ if (cursor.kind != CXCursor_InclusionDirective)
+ return CXChildVisit_Continue;
+
+ SourceLocation
+ Loc = cxloc::translateSourceLocation(clang_getCursorLocation(cursor));
+
+ ASTContext &Ctx = getASTContext();
+ SourceManager &SM = Ctx.getSourceManager();
+
+ // We are looking for includes in a specific file.
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ if (SM.getFileEntryForID(LocInfo.first) != File)
+ return CXChildVisit_Continue;
+
+ if (visitor.visit(visitor.context, cursor,
+ cxloc::translateSourceRange(Ctx, Loc)) == CXVisit_Break)
+ return CXChildVisit_Break;
+ return CXChildVisit_Continue;
+ }
+
+ static enum CXChildVisitResult visit(CXCursor cursor, CXCursor parent,
+ CXClientData client_data) {
+ return static_cast<FindFileIncludesVisitor*>(client_data)->
+ visit(cursor, parent);
+ }
+};
+
+} // anonymous namespace
+
+static void findIncludesInFile(CXTranslationUnit TU, const FileEntry *File,
+ CXCursorAndRangeVisitor Visitor) {
+ assert(TU && File && Visitor.visit);
+
+ ASTUnit *Unit = cxtu::getASTUnit(TU);
+ SourceManager &SM = Unit->getSourceManager();
+
+ FileID FID = SM.translateFile(File);
+
+ FindFileIncludesVisitor IncludesVisitor(*Unit, File, Visitor);
+
+ SourceRange Range(SM.getLocForStartOfFile(FID), SM.getLocForEndOfFile(FID));
+ CursorVisitor InclusionCursorsVisitor(TU,
+ FindFileIncludesVisitor::visit,
+ &IncludesVisitor,
+ /*VisitPreprocessorLast=*/false,
+ /*VisitIncludedEntities=*/false,
+ Range);
+ InclusionCursorsVisitor.visitPreprocessedEntitiesInRegion();
+}
+
//===----------------------------------------------------------------------===//
// libclang public APIs.
@@ -410,6 +476,38 @@ void clang_findReferencesInFile(CXCursor cursor, CXFile file,
visitor);
}
+void clang_findIncludesInFile(CXTranslationUnit TU, CXFile file,
+ CXCursorAndRangeVisitor visitor) {
+ LogRef Log = Logger::make(LLVM_FUNCTION_NAME);
+
+ if (!TU) {
+ if (Log)
+ *Log << "Null CXTranslationUnit";
+ return;
+ }
+ if (!file) {
+ if (Log)
+ *Log << "Null file";
+ return;
+ }
+ if (!visitor.visit) {
+ if (Log)
+ *Log << "Null visitor";
+ return;
+ }
+
+ if (Log)
+ *Log << TU << " @" << static_cast<const FileEntry *>(file);
+
+ ASTUnit *CXXUnit = cxtu::getASTUnit(TU);
+ if (!CXXUnit)
+ return;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ findIncludesInFile(TU, static_cast<const FileEntry *>(file), visitor);
+}
+
static enum CXVisitorResult _visitCursorAndRange(void *context,
CXCursor cursor,
CXSourceRange range) {
@@ -425,5 +523,13 @@ void clang_findReferencesInFileWithBlock(CXCursor cursor,
return clang_findReferencesInFile(cursor, file, visitor);
}
+void clang_findIncludesInFileWithBlock(CXTranslationUnit TU,
+ CXFile file,
+ CXCursorAndRangeVisitorBlock block) {
+ CXCursorAndRangeVisitor visitor = { block,
+ block ? _visitCursorAndRange : 0 };
+ return clang_findIncludesInFile(TU, file, visitor);
+}
+
} // end: extern "C"
diff --git a/clang/tools/libclang/libclang.exports b/clang/tools/libclang/libclang.exports
index e0c4db07f4e..d99f24ef038 100644
--- a/clang/tools/libclang/libclang.exports
+++ b/clang/tools/libclang/libclang.exports
@@ -98,6 +98,8 @@ clang_equalLocations
clang_equalRanges
clang_equalTypes
clang_executeOnThread
+clang_findIncludesInFile
+clang_findIncludesInFileWithBlock
clang_findReferencesInFile
clang_findReferencesInFileWithBlock
clang_formatDiagnostic
OpenPOWER on IntegriCloud