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;
#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"
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);
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) {