r279076 - [libclang] Add clang_getAllSkippedRanges function

Cameron Desrochers via cfe-commits cfe-commits at lists.llvm.org
Thu Aug 18 08:43:55 PDT 2016


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) {




More information about the cfe-commits mailing list