aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2019-01-10 21:22:13 +0000
committerAaron Ballman <aaron@aaronballman.com>2019-01-10 21:22:13 +0000
commit70bdcdf55d70b2bf8b156f9fb467dde869b6f84b (patch)
tree1a1c67119c9eb5450c4460ca0becd8f4004f0ed5 /clang/unittests
parent1224321623f952bfd85f72bdf1b5762cf81dd43b (diff)
Correct the source range returned from preprocessor callbacks.
This adjusts the source range passed in to the preprocessor callbacks to only include the condition range itself, rather than all of the conditionally skipped tokens. llvm-svn: 350891
Diffstat (limited to 'clang/unittests')
-rw-r--r--clang/unittests/Lex/PPCallbacksTest.cpp119
1 files changed, 118 insertions, 1 deletions
diff --git a/clang/unittests/Lex/PPCallbacksTest.cpp b/clang/unittests/Lex/PPCallbacksTest.cpp
index d0ff45ec7cc4..29d5268921a4 100644
--- a/clang/unittests/Lex/PPCallbacksTest.cpp
+++ b/clang/unittests/Lex/PPCallbacksTest.cpp
@@ -65,6 +65,29 @@ public:
SrcMgr::CharacteristicKind FileType;
};
+class CondDirectiveCallbacks : public PPCallbacks {
+public:
+ struct Result {
+ SourceRange ConditionRange;
+ ConditionValueKind ConditionValue;
+
+ Result(SourceRange R, ConditionValueKind K)
+ : ConditionRange(R), ConditionValue(K) {}
+ };
+
+ std::vector<Result> Results;
+
+ void If(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue) override {
+ Results.emplace_back(ConditionRange, ConditionValue);
+ }
+
+ void Elif(SourceLocation Loc, SourceRange ConditionRange,
+ ConditionValueKind ConditionValue, SourceLocation IfLoc) override {
+ Results.emplace_back(ConditionRange, ConditionValue);
+ }
+};
+
// Stub to collect data from PragmaOpenCLExtension callbacks.
class PragmaOpenCLExtensionCallbacks : public PPCallbacks {
public:
@@ -137,6 +160,15 @@ protected:
return StringRef(B, E - B);
}
+ StringRef GetSourceStringToEnd(CharSourceRange Range) {
+ const char *B = SourceMgr.getCharacterData(Range.getBegin());
+ const char *E = SourceMgr.getCharacterData(Range.getEnd());
+
+ return StringRef(
+ B,
+ E - B + Lexer::MeasureTokenLength(Range.getEnd(), SourceMgr, LangOpts));
+ }
+
// Run lexer over SourceText and collect FilenameRange from
// the InclusionDirective callback.
CharSourceRange InclusionDirectiveFilenameRange(const char *SourceText,
@@ -199,6 +231,36 @@ protected:
return Callbacks;
}
+ std::vector<CondDirectiveCallbacks::Result>
+ DirectiveExprRange(StringRef SourceText) {
+ TrivialModuleLoader ModLoader;
+ MemoryBufferCache PCMCache;
+ std::unique_ptr<llvm::MemoryBuffer> Buf =
+ llvm::MemoryBuffer::getMemBuffer(SourceText);
+ SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
+ HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
+ Diags, LangOpts, Target.get());
+ Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
+ SourceMgr, PCMCache, HeaderInfo, ModLoader,
+ /*IILookup =*/nullptr,
+ /*OwnsHeaderSearch =*/false);
+ PP.Initialize(*Target);
+ auto *Callbacks = new CondDirectiveCallbacks;
+ PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));
+
+ // Lex source text.
+ PP.EnterMainSourceFile();
+
+ while (true) {
+ Token Tok;
+ PP.Lex(Tok);
+ if (Tok.is(tok::eof))
+ break;
+ }
+
+ return Callbacks->Results;
+ }
+
PragmaOpenCLExtensionCallbacks::CallbackParameters
PragmaOpenCLExtensionCall(const char *SourceText) {
LangOptions OpenCLLangOpts;
@@ -368,4 +430,59 @@ TEST_F(PPCallbacksTest, OpenCLExtensionPragmaDisabled) {
ASSERT_EQ(ExpectedState, Parameters.State);
}
-} // anonoymous namespace
+TEST_F(PPCallbacksTest, DirectiveExprRanges) {
+ const auto &Results1 = DirectiveExprRange("#if FLUZZY_FLOOF\n#endif\n");
+ EXPECT_EQ(Results1.size(), 1);
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results1[0].ConditionRange, false)),
+ "FLUZZY_FLOOF");
+
+ const auto &Results2 = DirectiveExprRange("#if 1 + 4 < 7\n#endif\n");
+ EXPECT_EQ(Results2.size(), 1);
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results2[0].ConditionRange, false)),
+ "1 + 4 < 7");
+
+ const auto &Results3 = DirectiveExprRange("#if 1 + \\\n 2\n#endif\n");
+ EXPECT_EQ(Results3.size(), 1);
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results3[0].ConditionRange, false)),
+ "1 + \\\n 2");
+
+ const auto &Results4 = DirectiveExprRange("#if 0\n#elif FLOOFY\n#endif\n");
+ EXPECT_EQ(Results4.size(), 2);
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results4[0].ConditionRange, false)),
+ "0");
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results4[1].ConditionRange, false)),
+ "FLOOFY");
+
+ const auto &Results5 = DirectiveExprRange("#if 1\n#elif FLOOFY\n#endif\n");
+ EXPECT_EQ(Results5.size(), 2);
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results5[0].ConditionRange, false)),
+ "1");
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results5[1].ConditionRange, false)),
+ "FLOOFY");
+
+ const auto &Results6 =
+ DirectiveExprRange("#if defined(FLUZZY_FLOOF)\n#endif\n");
+ EXPECT_EQ(Results6.size(), 1);
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results6[0].ConditionRange, false)),
+ "defined(FLUZZY_FLOOF)");
+
+ const auto &Results7 =
+ DirectiveExprRange("#if 1\n#elif defined(FLOOFY)\n#endif\n");
+ EXPECT_EQ(Results7.size(), 2);
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results7[0].ConditionRange, false)),
+ "1");
+ EXPECT_EQ(
+ GetSourceStringToEnd(CharSourceRange(Results7[1].ConditionRange, false)),
+ "defined(FLOOFY)");
+}
+
+} // namespace