diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-01-26 19:31:51 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-01-26 19:31:51 +0000 |
commit | 16b55a71695a33c094383295cc7b7a2080e098da (patch) | |
tree | d2be08df7dc22a67c22827d3e72003f2aa1e83b5 | |
parent | 46766dc31c09d89024de5aba9e22112a56eadbdf (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.h | 32 | ||||
-rw-r--r-- | include/clang/Basic/SourceManager.h | 5 | ||||
-rw-r--r-- | test/Index/cindex-test-inclusions.c | 13 | ||||
-rw-r--r-- | test/Index/include_test.h | 1 | ||||
-rw-r--r-- | test/Index/include_test_2.h | 0 | ||||
-rw-r--r-- | tools/CIndex/CIndex.exports | 1 | ||||
-rw-r--r-- | tools/CIndex/CIndexInclusionStack.cpp | 65 | ||||
-rw-r--r-- | tools/CIndex/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tools/c-index-test/c-index-test.c | 34 |
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; } |