]> granicus.if.org Git - clang/commitdiff
Implement 'clang_getInclusions()' in CIndex. This API allows clients to walk the...
authorTed Kremenek <kremenek@apple.com>
Tue, 26 Jan 2010 19:31:51 +0000 (19:31 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 26 Jan 2010 19:31:51 +0000 (19:31 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94575 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang-c/Index.h
include/clang/Basic/SourceManager.h
test/Index/cindex-test-inclusions.c [new file with mode: 0644]
test/Index/include_test.h [new file with mode: 0644]
test/Index/include_test_2.h [new file with mode: 0644]
tools/CIndex/CIndex.exports
tools/CIndex/CIndexInclusionStack.cpp [new file with mode: 0644]
tools/CIndex/CMakeLists.txt
tools/c-index-test/c-index-test.c

index 3a0260d86c8b80005892b916d692926cac3f7eb1..0470592a0fdd6c89542a6b57c3d6fe5ca227c246 100644 (file)
@@ -1402,6 +1402,38 @@ void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
  */
 CINDEX_LINKAGE const char *clang_getClangVersion();
 
+/**
+ * \brief Return a version string, suitable for showing to a user, but not
+ *        intended to be parsed (the format is not guaranteed to be stable).
+ */
+ /**
+  * \brief Visitor invoked for each file in a translation unit 
+  *        (used with clang_getInclusions()).
+  *
+  * This visitor function will be invoked by clang_getInclusions() for each
+  * file included (either at the top-level or by #include directives) within
+  * a translation unit.  The first argument is the file being included, and
+  * the second and third arguments provide the inclusion stack.  The
+  * array is sorted in order of immediate inclusion.  For example,
+  * the first element refers to the location that included 'included_file'.
+  */
+typedef void (*CXInclusionVisitor)(CXFile included_file,
+                                   CXSourceLocation* inclusion_stack,
+                                   unsigned include_len,
+                                   CXClientData client_data);
+
+/**
+ * \brief Visit the set of preprocessor inclusions in a translation unit.
+ *   The visitor function is called with the provided data for every included
+ *   file.  This does not include headers included by the PCH file (unless one
+ *   is inspecting the inclusions in the PCH file itself).
+ */
+CINDEX_LINKAGE void clang_getInclusions(CXTranslationUnit tu,
+                                        CXInclusionVisitor visitor,
+                                        CXClientData client_data);
+
 /**
  * @}
  */
index b4cf959dc551a72a5d8cbd07ceb94b4c76d112d0..59984e7ee858a602a59260dc37b5787451d95bdf 100644 (file)
@@ -675,6 +675,11 @@ public:
   void PrintStats() const;
 
   unsigned sloc_entry_size() const { return SLocEntryTable.size(); }
+  
+  // FIXME: Exposing this is a little gross; what we want is a good way
+  //  to iterate the entries that were not defined in a PCH file (or
+  //  any other external source).
+  unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); }
 
   const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const {
     assert(ID < SLocEntryTable.size() && "Invalid id");
diff --git a/test/Index/cindex-test-inclusions.c b/test/Index/cindex-test-inclusions.c
new file mode 100644 (file)
index 0000000..9c7de2e
--- /dev/null
@@ -0,0 +1,13 @@
+// RUN: c-index-test -test-inclusion-stack-source %s 2>&1 | FileCheck %s
+
+#include "include_test.h"
+
+// CHECK: cindex-test-inclusions.c
+// CHECK: included by:
+// CHECK: include_test.h
+// CHECK: included by:
+// CHECK: cindex-test-inclusions.c:3:10
+// CHECK: include_test_2.h
+// CHECK: included by:
+// CHECK: include_test.h:1:10
+// CHECK: cindex-test-inclusions.c:3:10
diff --git a/test/Index/include_test.h b/test/Index/include_test.h
new file mode 100644 (file)
index 0000000..3c40c8d
--- /dev/null
@@ -0,0 +1 @@
+#include "include_test_2.h"
diff --git a/test/Index/include_test_2.h b/test/Index/include_test_2.h
new file mode 100644 (file)
index 0000000..e69de29
index ef77fede5360005456116639cd74908765297e99..12e2788e4aff2b2afd93e970768691878c72f37e 100644 (file)
@@ -28,6 +28,7 @@ _clang_getDefinitionSpellingAndExtent
 _clang_getFile
 _clang_getFileName
 _clang_getFileTime
+_clang_getInclusions
 _clang_getInstantiationLocation
 _clang_getLocation
 _clang_getNullCursor
diff --git a/tools/CIndex/CIndexInclusionStack.cpp b/tools/CIndex/CIndexInclusionStack.cpp
new file mode 100644 (file)
index 0000000..4a884e5
--- /dev/null
@@ -0,0 +1,65 @@
+//===- CIndexInclusionStack.cpp - Clang-C Source Indexing Library ---------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a callback mechanism for clients to get the inclusion
+// stack from a translation unit.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXSourceLocation.h"
+#include "clang/AST/DeclVisitor.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+extern "C" {
+void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
+                         CXClientData clientData) {
+  
+  ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
+  SourceManager &SM = CXXUnit->getSourceManager();
+  ASTContext &Ctx = CXXUnit->getASTContext();
+
+  llvm::SmallVector<CXSourceLocation, 10> InclusionStack;
+  unsigned i = SM.sloc_loaded_entry_size();
+  unsigned n =  SM.sloc_entry_size();
+
+  // In the case where all the SLocEntries are in an external source, traverse
+  // those SLocEntries as well.  This is the case where we are looking
+  // at the inclusion stack of an AST/PCH file.
+  if (i >= n)
+    i = 0;
+  
+  for ( ; i < n ; ++i) {
+
+    const SrcMgr::SLocEntry &SL = SM.getSLocEntry(i);
+    
+    if (!SL.isFile())
+      continue;
+
+    const SrcMgr::FileInfo &FI = SL.getFile();
+    if (!FI.getContentCache()->Entry)
+      continue;
+    
+    // Build the inclusion stack.
+    SourceLocation L = FI.getIncludeLoc();
+    InclusionStack.clear();
+    while (L.isValid()) {
+      PresumedLoc PLoc = SM.getPresumedLoc(L);
+      InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L));
+      L = PLoc.getIncludeLoc();
+    }
+            
+    // Callback to the client.
+    // FIXME: We should have a function to construct CXFiles.
+    CB((CXFile) FI.getContentCache()->Entry, 
+       InclusionStack.data(), InclusionStack.size(), clientData);
+  }    
+}
+} // end extern C
index 730eaafb5a2e917c1c8ec28da9b811d5434207f0..f4d22253107d753449896ef0521d1832e48a08bf 100644 (file)
@@ -21,6 +21,7 @@ set( LLVM_LINK_COMPONENTS
 add_clang_library(CIndex
   CIndex.cpp
   CIndexCodeCompletion.cpp
+  CIndexInclusionStack.cpp
   CIndexUSRs.cpp
   CIndexer.cpp
   CXCursor.cpp
index 7250cc72577e18014e2ebf4537b9111655ad6bb7..2ad9da12bb65ee124995445b65f78e8eaeb5fce9 100644 (file)
@@ -302,6 +302,29 @@ enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
   return CXChildVisit_Continue;
 }
 
+/******************************************************************************/
+/* Inclusion stack testing.                                                   */
+/******************************************************************************/
+
+void InclusionVisitor(CXFile includedFile, CXSourceLocation *includeStack,
+                      unsigned includeStackLen, CXClientData data) {
+  
+  unsigned i;
+  printf("file: %s\nincluded by:\n", clang_getFileName(includedFile));
+  for (i = 0; i < includeStackLen; ++i) {
+    CXFile includingFile;
+    unsigned line, column;
+    clang_getInstantiationLocation(includeStack[i], &includingFile, &line,
+                                   &column, 0);
+    printf("  %s:%d:%d\n", clang_getFileName(includingFile), line, column);
+  }
+  printf("\n");
+}
+
+void PrintInclusionStack(CXTranslationUnit TU) {
+  clang_getInclusions(TU, InclusionVisitor, NULL);  
+}
+
 /******************************************************************************/
 /* Loading ASTs/source.                                                       */
 /******************************************************************************/
@@ -853,7 +876,9 @@ static void print_usage(void) {
     "       c-index-test -test-load-source <symbol filter> {<args>}*\n"
     "       c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n");
   fprintf(stderr,
-    "       c-index-test -test-annotate-tokens=<range> {<args>}* \n\n"
+    "       c-index-test -test-annotate-tokens=<range> {<args>}*\n"
+    "       c-index-test -test-inclusion-stack-source {<args>}*\n"
+    "       c-index-test -test-inclusion-stack-tu <AST file>\n\n"
     " <symbol filter> values:\n%s",
     "   all - load all symbols, including those from PCH\n"
     "   local - load all symbols except those in PCH\n"
@@ -886,6 +911,13 @@ int main(int argc, const char **argv) {
                              argc >= 5 ? argv[4] : 0);
   else if (argc > 2 && strstr(argv[1], "-test-annotate-tokens=") == argv[1])
     return perform_token_annotation(argc, argv);
+  else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-source") == 0)
+    return perform_test_load_source(argc - 2, argv + 2, "all", NULL,
+                                    PrintInclusionStack);
+  else if (argc > 2 && strcmp(argv[1], "-test-inclusion-stack-tu") == 0)
+    return perform_test_load_tu(argv[2], "all", NULL, NULL,
+                                PrintInclusionStack);
+    
   print_usage();
   return 1;
 }