Author: cameron314 Date: Thu Aug 18 10:43:55 2016 New Revision: 279076 URL: http://llvm.org/viewvc/llvm-project?rev=279076&view=rev Log: [libclang] Add clang_getAllSkippedRanges function
This complements the clang_getSkippedRanges function which returns skipped ranges filtered by a specific file. This function is useful when all the ranges are desired (and a lot more efficient than the equivalent of asking for the ranges file by file, since the implementation of clang_getSkippedRanges iterates over all ranges anyway). Differential Revision: https://reviews.llvm.org/D20132 Modified: cfe/trunk/include/clang-c/Index.h cfe/trunk/tools/libclang/CIndex.cpp cfe/trunk/unittests/libclang/LibclangTest.cpp Modified: cfe/trunk/include/clang-c/Index.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=279076&r1=279075&r2=279076&view=diff ============================================================================== --- cfe/trunk/include/clang-c/Index.h (original) +++ cfe/trunk/include/clang-c/Index.h Thu Aug 18 10:43:55 2016 @@ -627,6 +627,15 @@ CINDEX_LINKAGE CXSourceRangeList *clang_ CXFile file); /** + * \brief Retrieve all ranges from all files that were skipped by the + * preprocessor. + * + * The preprocessor will skip lines when they are surrounded by an + * if/ifdef/ifndef directive whose condition does not evaluate to true. + */ +CINDEX_LINKAGE CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit tu); + +/** * \brief Destroy the given \c CXSourceRangeList. */ CINDEX_LINKAGE void clang_disposeSourceRangeList(CXSourceRangeList *ranges); Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=279076&r1=279075&r2=279076&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Thu Aug 18 10:43:55 2016 @@ -7773,6 +7773,33 @@ CXSourceRangeList *clang_getSkippedRange return skipped; } +CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit TU) { + CXSourceRangeList *skipped = new CXSourceRangeList; + skipped->count = 0; + skipped->ranges = nullptr; + + if (isNotUsableTU(TU)) { + LOG_BAD_TU(TU); + return skipped; + } + + ASTUnit *astUnit = cxtu::getASTUnit(TU); + PreprocessingRecord *ppRec = astUnit->getPreprocessor().getPreprocessingRecord(); + if (!ppRec) + return skipped; + + ASTContext &Ctx = astUnit->getASTContext(); + + const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges(); + + skipped->count = SkippedRanges.size(); + skipped->ranges = new CXSourceRange[skipped->count]; + for (unsigned i = 0, ei = skipped->count; i != ei; ++i) + skipped->ranges[i] = cxloc::translateSourceRange(Ctx, SkippedRanges[i]); + + return skipped; +} + void clang_disposeSourceRangeList(CXSourceRangeList *ranges) { if (ranges) { delete[] ranges->ranges; Modified: cfe/trunk/unittests/libclang/LibclangTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/libclang/LibclangTest.cpp?rev=279076&r1=279075&r2=279076&view=diff ============================================================================== --- cfe/trunk/unittests/libclang/LibclangTest.cpp (original) +++ cfe/trunk/unittests/libclang/LibclangTest.cpp Thu Aug 18 10:43:55 2016 @@ -14,6 +14,9 @@ #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" #include <fstream> +#include <functional> +#include <map> +#include <memory> #include <set> #define DEBUG_TYPE "libclang-test" @@ -349,21 +352,25 @@ TEST(libclang, ModuleMapDescriptor) { clang_ModuleMapDescriptor_dispose(MMD); } -class LibclangReparseTest : public ::testing::Test { +class LibclangParseTest : public ::testing::Test { std::set<std::string> Files; + typedef std::unique_ptr<std::string> fixed_addr_string; + std::map<fixed_addr_string, fixed_addr_string> UnsavedFileContents; public: std::string TestDir; CXIndex Index; CXTranslationUnit ClangTU; unsigned TUFlags; + std::vector<CXUnsavedFile> UnsavedFiles; void SetUp() override { llvm::SmallString<256> Dir; ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("libclang-test", Dir)); TestDir = Dir.str(); TUFlags = CXTranslationUnit_DetailedPreprocessingRecord | - clang_defaultEditingTranslationUnitOptions(); + clang_defaultEditingTranslationUnitOptions(); Index = clang_createIndex(0, 0); + ClangTU = nullptr; } void TearDown() override { clang_disposeTranslationUnit(ClangTU); @@ -384,6 +391,77 @@ public: OS << Contents; assert(OS.good()); } + void MapUnsavedFile(std::string Filename, const std::string &Contents) { + if (!llvm::sys::path::is_absolute(Filename)) { + llvm::SmallString<256> Path(TestDir); + llvm::sys::path::append(Path, Filename); + Filename = Path.str(); + } + auto it = UnsavedFileContents.emplace( + fixed_addr_string(new std::string(Filename)), + fixed_addr_string(new std::string(Contents))); + UnsavedFiles.push_back({ + it.first->first->c_str(), // filename + it.first->second->c_str(), // contents + it.first->second->size() // length + }); + } + template<typename F> + void Traverse(const F &TraversalFunctor) { + CXCursor TuCursor = clang_getTranslationUnitCursor(ClangTU); + std::reference_wrapper<const F> FunctorRef = std::cref(TraversalFunctor); + clang_visitChildren(TuCursor, + &TraverseStateless<std::reference_wrapper<const F>>, + &FunctorRef); + } +private: + template<typename TState> + static CXChildVisitResult TraverseStateless(CXCursor cx, CXCursor parent, + CXClientData data) { + TState *State = static_cast<TState*>(data); + return State->get()(cx, parent); + } +}; + +TEST_F(LibclangParseTest, AllSkippedRanges) { + std::string Header = "header.h", Main = "main.cpp"; + WriteFile(Header, + "#ifdef MANGOS\n" + "printf(\"mmm\");\n" + "#endif"); + WriteFile(Main, + "#include \"header.h\"\n" + "#ifdef KIWIS\n" + "printf(\"mmm!!\");\n" + "#endif"); + + ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0, + nullptr, 0, TUFlags); + + CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU); + EXPECT_EQ(2, Ranges->count); + + CXSourceLocation cxl; + unsigned line; + cxl = clang_getRangeStart(Ranges->ranges[0]); + clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr); + EXPECT_EQ(1, line); + cxl = clang_getRangeEnd(Ranges->ranges[0]); + clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr); + EXPECT_EQ(3, line); + + cxl = clang_getRangeStart(Ranges->ranges[1]); + clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr); + EXPECT_EQ(2, line); + cxl = clang_getRangeEnd(Ranges->ranges[1]); + clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr); + EXPECT_EQ(4, line); + + clang_disposeSourceRangeList(Ranges); +} + +class LibclangReparseTest : public LibclangParseTest { +public: void DisplayDiagnostics() { unsigned NumDiagnostics = clang_getNumDiagnostics(ClangTU); for (unsigned i = 0; i < NumDiagnostics; ++i) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits