r176682 - [libclang] Introduce clang_findIncludesInFile, that can be used to retrieve all #import/#include directives in a specific file.

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Mar 7 18:32:35 PST 2013


Author: akirtzidis
Date: Thu Mar  7 20:32:34 2013
New Revision: 176682

URL: http://llvm.org/viewvc/llvm-project?rev=176682&view=rev
Log:
[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.

Added:
    cfe/trunk/test/Index/file-includes.c
Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/tools/c-index-test/c-index-test.c
    cfe/trunk/tools/libclang/CIndexHigh.cpp
    cfe/trunk/tools/libclang/libclang.exports

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=176682&r1=176681&r2=176682&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Thu Mar  7 20:32:34 2013
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 12
+#define CINDEX_VERSION_MINOR 13
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
       ((major) * 10000)                       \
@@ -5021,6 +5021,19 @@ typedef struct {
 CINDEX_LINKAGE void clang_findReferencesInFile(CXCursor cursor, CXFile file,
                                                CXCursorAndRangeVisitor visitor);
 
+/**
+ * \brief Find #import/#include directives in a specific file.
+ *
+ * \param TU translation unit containing the file to query.
+ *
+ * \param file to search for #import/#include directives.
+ *
+ * \param visitor callback that will receive pairs of CXCursor/CXSourceRange for
+ * each directive found.
+ */
+CINDEX_LINKAGE void clang_findIncludesInFile(CXTranslationUnit TU, CXFile file,
+                                             CXCursorAndRangeVisitor visitor);
+
 #ifdef __has_feature
 #  if __has_feature(blocks)
 
@@ -5031,6 +5044,10 @@ CINDEX_LINKAGE
 void clang_findReferencesInFileWithBlock(CXCursor, CXFile,
                                          CXCursorAndRangeVisitorBlock);
 
+CINDEX_LINKAGE
+void clang_findIncludesInFileWithBlock(CXTranslationUnit, CXFile,
+                                       CXCursorAndRangeVisitorBlock);
+
 #  endif
 #endif
 

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=176682&r1=176681&r2=176682&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Mar  7 20:32:34 2013
@@ -4000,7 +4000,7 @@ ASTReader::findBeginPreprocessedEntity(S
 
   GlobalSLocOffsetMapType::const_iterator
     SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
-                                        BLoc.getOffset());
+                                        BLoc.getOffset() - 1);
   assert(SLocMapI != GlobalSLocOffsetMap.end() &&
          "Corrupted global sloc offset map");
 
@@ -4048,7 +4048,7 @@ ASTReader::findEndPreprocessedEntity(Sou
 
   GlobalSLocOffsetMapType::const_iterator
     SLocMapI = GlobalSLocOffsetMap.find(SourceManager::MaxLoadedOffset -
-                                        ELoc.getOffset());
+                                        ELoc.getOffset() - 1);
   assert(SLocMapI != GlobalSLocOffsetMap.end() &&
          "Corrupted global sloc offset map");
 

Added: cfe/trunk/test/Index/file-includes.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/file-includes.c?rev=176682&view=auto
==============================================================================
--- cfe/trunk/test/Index/file-includes.c (added)
+++ cfe/trunk/test/Index/file-includes.c Thu Mar  7 20:32:34 2013
@@ -0,0 +1,24 @@
+
+#include "targeted-top.h"
+#include "targeted-preamble.h"
+
+extern int LocalVar;
+int LocalVar;
+
+// RUN: c-index-test -write-pch %t.h.pch %S/targeted-top.h -Xclang -detailed-preprocessing-record
+
+// RUN: c-index-test -file-includes-in=%s %s | FileCheck %s -check-prefix=LOCAL
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -file-includes-in=%s %s | FileCheck %s -check-prefix=LOCAL
+// RUN: c-index-test -file-includes-in=%s %s -include %t.h | FileCheck %s -check-prefix=LOCAL
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -file-includes-in=%s %s -include %t.h | FileCheck %s -check-prefix=LOCAL
+
+// LOCAL: inclusion directive=targeted-top.h ({{.*}}/test/Index/targeted-top.h) {{.*}}=[2:1 - 2:2]
+// LOCAL: inclusion directive=targeted-preamble.h ({{.*}}/test/Index/targeted-preamble.h) =[3:1 - 3:2]
+
+// RUN: c-index-test -file-includes-in=%S/targeted-top.h %s | FileCheck %s -check-prefix=TOP
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -file-includes-in=%S/targeted-top.h %s | FileCheck %s -check-prefix=TOP
+// RUN: c-index-test -file-includes-in=%S/targeted-top.h %s -include %t.h | FileCheck %s -check-prefix=TOP
+// RUN: env CINDEXTEST_EDITING=1 c-index-test -file-includes-in=%S/targeted-top.h %s -include %t.h | FileCheck %s -check-prefix=TOP
+
+// TOP: inclusion directive=targeted-nested1.h ({{.*}}/test/Index/targeted-nested1.h) =[5:1 - 5:2]
+// TOP: inclusion directive=targeted-fields.h ({{.*}}/test/Index/targeted-fields.h) =[16:1 - 16:2]

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=176682&r1=176681&r2=176682&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Thu Mar  7 20:32:34 2013
@@ -2135,6 +2135,99 @@ static int find_file_refs_at(int argc, c
   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
     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)

Modified: cfe/trunk/tools/libclang/CIndexHigh.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndexHigh.cpp?rev=176682&r1=176681&r2=176682&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndexHigh.cpp (original)
+++ cfe/trunk/tools/libclang/CIndexHigh.cpp Thu Mar  7 20:32:34 2013
@@ -337,6 +337,72 @@ static void findMacroRefsInFile(CXTransl
   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
                    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
   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"
 

Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=176682&r1=176681&r2=176682&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Thu Mar  7 20:32:34 2013
@@ -98,6 +98,8 @@ clang_equalLocations
 clang_equalRanges
 clang_equalTypes
 clang_executeOnThread
+clang_findIncludesInFile
+clang_findIncludesInFileWithBlock
 clang_findReferencesInFile
 clang_findReferencesInFileWithBlock
 clang_formatDiagnostic





More information about the cfe-commits mailing list