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

Aaron Ballman aaron at aaronballman.com
Mon Mar 11 07:26:55 PDT 2013


Patch LGTM, thanks for it!

~Aaron

On Sun, Mar 10, 2013 at 8:55 AM, Benyei, Guy <guy.benyei at intel.com> wrote:
> Hi Argyrios,
> The file-includes test you've added fails in Windows, since it doesn't expect backslash characters in the paths. Also, the freeing of a 'const char **' in c-index-test.c triggers a warning in windows.
> Attached a fix for both issues - please review.
>
> Thanks
>     Guy
>
>
> -----Original Message-----
> From: cfe-commits-bounces at cs.uiuc.edu [mailto:cfe-commits-bounces at cs.uiuc.edu] On Behalf Of Argyrios Kyrtzidis
> Sent: Friday, March 08, 2013 04:33
> To: cfe-commits at cs.uiuc.edu
> Subject: r176682 - [libclang] Introduce clang_findIncludesInFile, that can be used to retrieve all #import/#include directives in a specific file.
>
> 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
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
> ---------------------------------------------------------------------
> Intel Israel (74) Limited
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>



More information about the cfe-commits mailing list