aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests
diff options
context:
space:
mode:
authorSam McCall <sam.mccall@gmail.com>2022-09-26 03:22:09 +0200
committerTobias Hieta <tobias@hieta.se>2022-10-10 08:49:22 +0200
commit27e075fcfad137b43367734052c63abe12555403 (patch)
treecb49363975cfa94f0eae951bc4660ce4d8a1f03d /clang/unittests
parent359ef0c932404d31347ce25895fdcadee1004381 (diff)
downloadllvm-27e075fcfad137b43367734052c63abe12555403.zip
llvm-27e075fcfad137b43367734052c63abe12555403.tar.gz
llvm-27e075fcfad137b43367734052c63abe12555403.tar.bz2
[Syntax] Fix macro-arg handling in TokenBuffer::spelledForExpanded
A few cases were not handled correctly. Notably: #define ID(X) X #define HIDE a ID(b) HIDE spelledForExpanded() would claim HIDE is an equivalent range of the 'b' it contains, despite the fact that HIDE also covers 'a'. While trying to fix this bug, I found findCommonRangeForMacroArgs hard to understand (both the implementation and how it's used in spelledForExpanded). It relies on details of the SourceLocation graph that are IMO fairly obscure. So I've added/revised quite a lot of comments and made some naming tweaks. Fixes https://github.com/clangd/clangd/issues/1289 Differential Revision: https://reviews.llvm.org/D134618 (cherry picked from commit 67268ee11c220b1dfdf84afb10a12371c5ae6400)
Diffstat (limited to 'clang/unittests')
-rw-r--r--clang/unittests/Tooling/Syntax/TokensTest.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/clang/unittests/Tooling/Syntax/TokensTest.cpp b/clang/unittests/Tooling/Syntax/TokensTest.cpp
index 77f719c..85fc837 100644
--- a/clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -743,6 +743,62 @@ TEST_F(TokenBufferTest, SpelledByExpanded) {
ValueIs(SameRange(findSpelled("ID2 ( a4 , a5 a6 a7 )"))));
// Should fail, spans multiple invocations.
EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("a1 a2 a3 a4")), llvm::None);
+
+ // https://github.com/clangd/clangd/issues/1289
+ recordTokens(R"cpp(
+ #define FOO(X) foo(X)
+ #define INDIRECT FOO(y)
+ INDIRECT // expands to foo(y)
+ )cpp");
+ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("y")), llvm::None);
+
+ recordTokens(R"cpp(
+ #define FOO(X) a X b
+ FOO(y)
+ )cpp");
+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("y")),
+ ValueIs(SameRange(findSpelled("y"))));
+
+ recordTokens(R"cpp(
+ #define ID(X) X
+ #define BAR ID(1)
+ BAR
+ )cpp");
+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("1")),
+ ValueIs(SameRange(findSpelled(") BAR").drop_front())));
+
+ // Critical cases for mapping of Prev/Next in spelledForExpandedSlow.
+ recordTokens(R"cpp(
+ #define ID(X) X
+ ID(prev ID(good))
+ #define LARGE ID(prev ID(bad))
+ LARGE
+ )cpp");
+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")),
+ ValueIs(SameRange(findSpelled("good"))));
+ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None);
+
+ recordTokens(R"cpp(
+ #define PREV prev
+ #define ID(X) X
+ PREV ID(good)
+ #define LARGE PREV ID(bad)
+ LARGE
+ )cpp");
+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")),
+ ValueIs(SameRange(findSpelled("good"))));
+ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None);
+
+ recordTokens(R"cpp(
+ #define ID(X) X
+ #define ID2(X, Y) X Y
+ ID2(prev, ID(good))
+ #define LARGE ID2(prev, bad)
+ LARGE
+ )cpp");
+ EXPECT_THAT(Buffer.spelledForExpanded(findExpanded("good")),
+ ValueIs(SameRange(findSpelled("good"))));
+ EXPECT_EQ(Buffer.spelledForExpanded(findExpanded("bad")), llvm::None);
}
TEST_F(TokenBufferTest, ExpandedTokensForRange) {