Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 840ee0d

Browse files
committedAug 18, 2016
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@279076 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent ac46444 commit 840ee0d

File tree

3 files changed

+116
-2
lines changed

3 files changed

+116
-2
lines changed
 

‎include/clang-c/Index.h

+9
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,15 @@ typedef struct {
626626
CINDEX_LINKAGE CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit tu,
627627
CXFile file);
628628

629+
/**
630+
* \brief Retrieve all ranges from all files that were skipped by the
631+
* preprocessor.
632+
*
633+
* The preprocessor will skip lines when they are surrounded by an
634+
* if/ifdef/ifndef directive whose condition does not evaluate to true.
635+
*/
636+
CINDEX_LINKAGE CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit tu);
637+
629638
/**
630639
* \brief Destroy the given \c CXSourceRangeList.
631640
*/

‎tools/libclang/CIndex.cpp

+27
Original file line numberDiff line numberDiff line change
@@ -7773,6 +7773,33 @@ CXSourceRangeList *clang_getSkippedRanges(CXTranslationUnit TU, CXFile file) {
77737773
return skipped;
77747774
}
77757775

7776+
CXSourceRangeList *clang_getAllSkippedRanges(CXTranslationUnit TU) {
7777+
CXSourceRangeList *skipped = new CXSourceRangeList;
7778+
skipped->count = 0;
7779+
skipped->ranges = nullptr;
7780+
7781+
if (isNotUsableTU(TU)) {
7782+
LOG_BAD_TU(TU);
7783+
return skipped;
7784+
}
7785+
7786+
ASTUnit *astUnit = cxtu::getASTUnit(TU);
7787+
PreprocessingRecord *ppRec = astUnit->getPreprocessor().getPreprocessingRecord();
7788+
if (!ppRec)
7789+
return skipped;
7790+
7791+
ASTContext &Ctx = astUnit->getASTContext();
7792+
7793+
const std::vector<SourceRange> &SkippedRanges = ppRec->getSkippedRanges();
7794+
7795+
skipped->count = SkippedRanges.size();
7796+
skipped->ranges = new CXSourceRange[skipped->count];
7797+
for (unsigned i = 0, ei = skipped->count; i != ei; ++i)
7798+
skipped->ranges[i] = cxloc::translateSourceRange(Ctx, SkippedRanges[i]);
7799+
7800+
return skipped;
7801+
}
7802+
77767803
void clang_disposeSourceRangeList(CXSourceRangeList *ranges) {
77777804
if (ranges) {
77787805
delete[] ranges->ranges;

‎unittests/libclang/LibclangTest.cpp

+80-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include "llvm/Support/raw_ostream.h"
1515
#include "gtest/gtest.h"
1616
#include <fstream>
17+
#include <functional>
18+
#include <map>
19+
#include <memory>
1720
#include <set>
1821
#define DEBUG_TYPE "libclang-test"
1922

@@ -349,21 +352,25 @@ TEST(libclang, ModuleMapDescriptor) {
349352
clang_ModuleMapDescriptor_dispose(MMD);
350353
}
351354

352-
class LibclangReparseTest : public ::testing::Test {
355+
class LibclangParseTest : public ::testing::Test {
353356
std::set<std::string> Files;
357+
typedef std::unique_ptr<std::string> fixed_addr_string;
358+
std::map<fixed_addr_string, fixed_addr_string> UnsavedFileContents;
354359
public:
355360
std::string TestDir;
356361
CXIndex Index;
357362
CXTranslationUnit ClangTU;
358363
unsigned TUFlags;
364+
std::vector<CXUnsavedFile> UnsavedFiles;
359365

360366
void SetUp() override {
361367
llvm::SmallString<256> Dir;
362368
ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("libclang-test", Dir));
363369
TestDir = Dir.str();
364370
TUFlags = CXTranslationUnit_DetailedPreprocessingRecord |
365-
clang_defaultEditingTranslationUnitOptions();
371+
clang_defaultEditingTranslationUnitOptions();
366372
Index = clang_createIndex(0, 0);
373+
ClangTU = nullptr;
367374
}
368375
void TearDown() override {
369376
clang_disposeTranslationUnit(ClangTU);
@@ -384,6 +391,77 @@ class LibclangReparseTest : public ::testing::Test {
384391
OS << Contents;
385392
assert(OS.good());
386393
}
394+
void MapUnsavedFile(std::string Filename, const std::string &Contents) {
395+
if (!llvm::sys::path::is_absolute(Filename)) {
396+
llvm::SmallString<256> Path(TestDir);
397+
llvm::sys::path::append(Path, Filename);
398+
Filename = Path.str();
399+
}
400+
auto it = UnsavedFileContents.emplace(
401+
fixed_addr_string(new std::string(Filename)),
402+
fixed_addr_string(new std::string(Contents)));
403+
UnsavedFiles.push_back({
404+
it.first->first->c_str(), // filename
405+
it.first->second->c_str(), // contents
406+
it.first->second->size() // length
407+
});
408+
}
409+
template<typename F>
410+
void Traverse(const F &TraversalFunctor) {
411+
CXCursor TuCursor = clang_getTranslationUnitCursor(ClangTU);
412+
std::reference_wrapper<const F> FunctorRef = std::cref(TraversalFunctor);
413+
clang_visitChildren(TuCursor,
414+
&TraverseStateless<std::reference_wrapper<const F>>,
415+
&FunctorRef);
416+
}
417+
private:
418+
template<typename TState>
419+
static CXChildVisitResult TraverseStateless(CXCursor cx, CXCursor parent,
420+
CXClientData data) {
421+
TState *State = static_cast<TState*>(data);
422+
return State->get()(cx, parent);
423+
}
424+
};
425+
426+
TEST_F(LibclangParseTest, AllSkippedRanges) {
427+
std::string Header = "header.h", Main = "main.cpp";
428+
WriteFile(Header,
429+
"#ifdef MANGOS\n"
430+
"printf(\"mmm\");\n"
431+
"#endif");
432+
WriteFile(Main,
433+
"#include \"header.h\"\n"
434+
"#ifdef KIWIS\n"
435+
"printf(\"mmm!!\");\n"
436+
"#endif");
437+
438+
ClangTU = clang_parseTranslationUnit(Index, Main.c_str(), nullptr, 0,
439+
nullptr, 0, TUFlags);
440+
441+
CXSourceRangeList *Ranges = clang_getAllSkippedRanges(ClangTU);
442+
EXPECT_EQ(2, Ranges->count);
443+
444+
CXSourceLocation cxl;
445+
unsigned line;
446+
cxl = clang_getRangeStart(Ranges->ranges[0]);
447+
clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
448+
EXPECT_EQ(1, line);
449+
cxl = clang_getRangeEnd(Ranges->ranges[0]);
450+
clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
451+
EXPECT_EQ(3, line);
452+
453+
cxl = clang_getRangeStart(Ranges->ranges[1]);
454+
clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
455+
EXPECT_EQ(2, line);
456+
cxl = clang_getRangeEnd(Ranges->ranges[1]);
457+
clang_getSpellingLocation(cxl, nullptr, &line, nullptr, nullptr);
458+
EXPECT_EQ(4, line);
459+
460+
clang_disposeSourceRangeList(Ranges);
461+
}
462+
463+
class LibclangReparseTest : public LibclangParseTest {
464+
public:
387465
void DisplayDiagnostics() {
388466
unsigned NumDiagnostics = clang_getNumDiagnostics(ClangTU);
389467
for (unsigned i = 0; i < NumDiagnostics; ++i) {

0 commit comments

Comments
 (0)
This repository has been archived.