aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-01-26 19:31:51 +0000
committerTed Kremenek <kremenek@apple.com>2010-01-26 19:31:51 +0000
commit16b55a71695a33c094383295cc7b7a2080e098da (patch)
treed2be08df7dc22a67c22827d3e72003f2aa1e83b5
parent46766dc31c09d89024de5aba9e22112a56eadbdf (diff)
Implement 'clang_getInclusions()' in CIndex. This API allows clients to walk the set of files included in a translation unit via the C API.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94575 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang-c/Index.h32
-rw-r--r--include/clang/Basic/SourceManager.h5
-rw-r--r--test/Index/cindex-test-inclusions.c13
-rw-r--r--test/Index/include_test.h1
-rw-r--r--test/Index/include_test_2.h0
-rw-r--r--tools/CIndex/CIndex.exports1
-rw-r--r--tools/CIndex/CIndexInclusionStack.cpp65
-rw-r--r--tools/CIndex/CMakeLists.txt1
-rw-r--r--tools/c-index-test/c-index-test.c34
9 files changed, 151 insertions, 1 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 3a0260d86c..0470592a0f 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -1403,6 +1403,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);
+
+/**
* @}
*/
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index b4cf959dc5..59984e7ee8 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -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
index 0000000000..9c7de2e2c6
--- /dev/null
+++ b/test/Index/cindex-test-inclusions.c
@@ -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
index 0000000000..3c40c8dc4d
--- /dev/null
+++ b/test/Index/include_test.h
@@ -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
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/Index/include_test_2.h
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index ef77fede53..12e2788e4a 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -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
index 0000000000..4a884e5884
--- /dev/null
+++ b/tools/CIndex/CIndexInclusionStack.cpp
@@ -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
diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt
index 730eaafb5a..f4d2225310 100644
--- a/tools/CIndex/CMakeLists.txt
+++ b/tools/CIndex/CMakeLists.txt
@@ -21,6 +21,7 @@ set( LLVM_LINK_COMPONENTS
add_clang_library(CIndex
CIndex.cpp
CIndexCodeCompletion.cpp
+ CIndexInclusionStack.cpp
CIndexUSRs.cpp
CIndexer.cpp
CXCursor.cpp
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 7250cc7257..2ad9da12bb 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -303,6 +303,29 @@ enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
}
/******************************************************************************/
+/* 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;
}