1 #include "../../lib/Format/Macros.h"
2 #include "../../lib/Format/UnwrappedLineParser.h"
4 #include "llvm/ADT/ArrayRef.h"
5 #include "llvm/ADT/SmallVector.h"
6 #include "llvm/ADT/StringRef.h"
8 #include "gmock/gmock.h"
9 #include "gtest/gtest.h"
19 llvm::DenseMap
<FormatToken
*, std::unique_ptr
<UnwrappedLine
>>;
21 // Keeps track of a sequence of macro expansions.
23 // The expanded tokens are accessible via getTokens(), while a map of macro call
24 // identifier token to unexpanded token stream is accessible via
28 Expansion(TestLexer
&Lex
, MacroExpander
&Macros
) : Lex(Lex
), Macros(Macros
) {}
30 // Appends the token stream obtained from expanding the macro Name given
31 // the provided arguments, to be later retrieved with getTokens().
32 // Returns the list of tokens making up the unexpanded macro call.
34 expand(llvm::StringRef Name
,
35 const SmallVector
<llvm::SmallVector
<FormatToken
*, 8>, 1> &Args
) {
36 return expandInternal(Name
, Args
);
39 TokenList
expand(llvm::StringRef Name
) { return expandInternal(Name
, {}); }
41 TokenList
expand(llvm::StringRef Name
, const std::vector
<std::string
> &Args
) {
42 return expandInternal(Name
, lexArgs(Args
));
45 const UnexpandedMap
&getUnexpanded() const { return Unexpanded
; }
47 const TokenList
&getTokens() const { return Tokens
; }
50 TokenList
expandInternal(
52 const std::optional
<SmallVector
<llvm::SmallVector
<FormatToken
*, 8>, 1>>
54 auto *ID
= Lex
.id(Name
);
55 auto UnexpandedLine
= std::make_unique
<UnwrappedLine
>();
56 UnexpandedLine
->Tokens
.push_back(ID
);
57 if (Args
&& !Args
->empty()) {
58 UnexpandedLine
->Tokens
.push_back(Lex
.id("("));
59 for (auto I
= Args
->begin(), E
= Args
->end(); I
!= E
; ++I
) {
60 if (I
!= Args
->begin())
61 UnexpandedLine
->Tokens
.push_back(Lex
.id(","));
62 UnexpandedLine
->Tokens
.insert(UnexpandedLine
->Tokens
.end(), I
->begin(),
65 UnexpandedLine
->Tokens
.push_back(Lex
.id(")"));
67 Unexpanded
[ID
] = std::move(UnexpandedLine
);
69 auto Expanded
= uneof(Macros
.expand(ID
, Args
));
70 Tokens
.append(Expanded
.begin(), Expanded
.end());
72 TokenList UnexpandedTokens
;
73 for (const UnwrappedLineNode
&Node
: Unexpanded
[ID
]->Tokens
)
74 UnexpandedTokens
.push_back(Node
.Tok
);
75 return UnexpandedTokens
;
78 llvm::SmallVector
<TokenList
, 1>
79 lexArgs(const std::vector
<std::string
> &Args
) {
80 llvm::SmallVector
<TokenList
, 1> Result
;
81 for (const auto &Arg
: Args
)
82 Result
.push_back(uneof(Lex
.lex(Arg
)));
85 llvm::DenseMap
<FormatToken
*, std::unique_ptr
<UnwrappedLine
>> Unexpanded
;
86 llvm::SmallVector
<FormatToken
*, 8> Tokens
;
88 MacroExpander
&Macros
;
92 Chunk(llvm::ArrayRef
<FormatToken
*> Tokens
)
93 : Tokens(Tokens
.begin(), Tokens
.end()) {}
94 Chunk(llvm::ArrayRef
<UnwrappedLine
> Children
)
95 : Children(Children
.begin(), Children
.end()) {}
96 llvm::SmallVector
<UnwrappedLineNode
, 1> Tokens
;
97 llvm::SmallVector
<UnwrappedLine
, 0> Children
;
100 // Allows to produce chunks of a token list by typing the code of equal tokens.
102 // Created from a list of tokens, users call "consume" to get the next chunk
103 // of tokens, checking that they match the written code.
105 Matcher(const TokenList
&Tokens
, TestLexer
&Lex
)
106 : Tokens(Tokens
), It(this->Tokens
.begin()), Lex(Lex
) {}
108 bool tokenMatches(const FormatToken
*Left
, const FormatToken
*Right
) {
109 if (Left
->getType() == Right
->getType() &&
110 Left
->TokenText
== Right
->TokenText
) {
113 llvm::dbgs() << Left
->TokenText
<< " != " << Right
->TokenText
<< "\n";
117 Chunk
consume(StringRef Tokens
) {
119 for (const FormatToken
*Token
: uneof(Lex
.lex(Tokens
))) {
120 (void)Token
; // Fix unused variable warning when asserts are disabled.
121 assert(tokenMatches(*It
, Token
));
122 Result
.push_back(*It
);
125 return Chunk(Result
);
129 TokenList::iterator It
;
133 UnexpandedMap
mergeUnexpanded(const UnexpandedMap
&M1
,
134 const UnexpandedMap
&M2
) {
135 UnexpandedMap Result
;
136 for (const auto &KV
: M1
)
137 Result
[KV
.first
] = std::make_unique
<UnwrappedLine
>(*KV
.second
);
138 for (const auto &KV
: M2
)
139 Result
[KV
.first
] = std::make_unique
<UnwrappedLine
>(*KV
.second
);
143 class MacroCallReconstructorTest
: public ::testing::Test
{
145 MacroCallReconstructorTest() : Lex(Allocator
, Buffers
) {}
147 std::unique_ptr
<MacroExpander
>
148 createExpander(const std::vector
<std::string
> &MacroDefinitions
) {
149 return std::make_unique
<MacroExpander
>(MacroDefinitions
,
150 Lex
.SourceMgr
.get(), Lex
.Style
,
151 Lex
.Allocator
, Lex
.IdentTable
);
154 UnwrappedLine
line(llvm::ArrayRef
<FormatToken
*> Tokens
) {
155 UnwrappedLine Result
;
156 for (FormatToken
*Tok
: Tokens
)
157 Result
.Tokens
.push_back(UnwrappedLineNode(Tok
));
161 UnwrappedLine
line(llvm::StringRef Text
) { return line({lex(Text
)}); }
163 UnwrappedLine
line(llvm::ArrayRef
<Chunk
> Chunks
) {
164 UnwrappedLine Result
;
165 for (const Chunk
&Chunk
: Chunks
) {
166 Result
.Tokens
.insert(Result
.Tokens
.end(), Chunk
.Tokens
.begin(),
168 assert(!Result
.Tokens
.empty());
169 Result
.Tokens
.back().Children
.append(Chunk
.Children
.begin(),
170 Chunk
.Children
.end());
175 TokenList
lex(llvm::StringRef Text
) { return uneof(Lex
.lex(Text
)); }
177 Chunk
tokens(llvm::StringRef Text
) { return Chunk(lex(Text
)); }
179 Chunk
children(llvm::ArrayRef
<UnwrappedLine
> Children
) {
180 return Chunk(Children
);
183 llvm::SpecificBumpPtrAllocator
<FormatToken
> Allocator
;
184 std::vector
<std::unique_ptr
<llvm::MemoryBuffer
>> Buffers
;
188 bool matchesTokens(const UnwrappedLine
&L1
, const UnwrappedLine
&L2
) {
189 if (L1
.Tokens
.size() != L2
.Tokens
.size())
191 for (auto L1It
= L1
.Tokens
.begin(), L2It
= L2
.Tokens
.begin();
192 L1It
!= L1
.Tokens
.end(); ++L1It
, ++L2It
) {
193 if (L1It
->Tok
!= L2It
->Tok
)
195 if (L1It
->Children
.size() != L2It
->Children
.size())
197 for (auto L1ChildIt
= L1It
->Children
.begin(),
198 L2ChildIt
= L2It
->Children
.begin();
199 L1ChildIt
!= L1It
->Children
.end(); ++L1ChildIt
, ++L2ChildIt
) {
200 if (!matchesTokens(*L1ChildIt
, *L2ChildIt
))
206 MATCHER_P(matchesLine
, line
, "") { return matchesTokens(arg
, line
); }
208 TEST_F(MacroCallReconstructorTest
, Identifier
) {
209 auto Macros
= createExpander({"X=x"});
210 Expansion
Exp(Lex
, *Macros
);
211 TokenList Call
= Exp
.expand("X");
213 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
214 Unexp
.addLine(line(Exp
.getTokens()));
215 EXPECT_TRUE(Unexp
.finished());
216 Matcher
U(Call
, Lex
);
217 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(line(U
.consume("X"))));
220 TEST_F(MacroCallReconstructorTest
, NestedLineWithinCall
) {
221 auto Macros
= createExpander({"C(a)=class X { a; };"});
222 Expansion
Exp(Lex
, *Macros
);
223 TokenList Call
= Exp
.expand("C", {"void f()"});
225 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
226 Matcher
E(Exp
.getTokens(), Lex
);
227 Unexp
.addLine(line(E
.consume("class X {")));
228 EXPECT_FALSE(Unexp
.finished());
229 Unexp
.addLine(line(E
.consume("void f();")));
230 EXPECT_FALSE(Unexp
.finished());
231 Unexp
.addLine(line(E
.consume("};")));
232 EXPECT_TRUE(Unexp
.finished());
233 Matcher
U(Call
, Lex
);
234 EXPECT_THAT(std::move(Unexp
).takeResult(),
235 matchesLine(line(U
.consume("C(void f())"))));
238 TEST_F(MacroCallReconstructorTest
, MultipleLinesInNestedMultiParamsExpansion
) {
239 auto Macros
= createExpander({"C(a, b)=a b", "B(a)={a}"});
240 Expansion
Exp1(Lex
, *Macros
);
241 TokenList Call1
= Exp1
.expand("B", {"b"});
242 Expansion
Exp2(Lex
, *Macros
);
243 TokenList Call2
= Exp2
.expand("C", {uneof(Lex
.lex("a")), Exp1
.getTokens()});
245 UnexpandedMap Unexpanded
=
246 mergeUnexpanded(Exp1
.getUnexpanded(), Exp2
.getUnexpanded());
247 MacroCallReconstructor
Unexp(0, Unexpanded
);
248 Matcher
E(Exp2
.getTokens(), Lex
);
249 Unexp
.addLine(line(E
.consume("a")));
250 EXPECT_FALSE(Unexp
.finished());
251 Unexp
.addLine(line(E
.consume("{")));
252 EXPECT_FALSE(Unexp
.finished());
253 Unexp
.addLine(line(E
.consume("b")));
254 EXPECT_FALSE(Unexp
.finished());
255 Unexp
.addLine(line(E
.consume("}")));
256 EXPECT_TRUE(Unexp
.finished());
258 Matcher
U1(Call1
, Lex
);
259 auto Middle
= U1
.consume("B(b)");
260 Matcher
U2(Call2
, Lex
);
261 auto Chunk1
= U2
.consume("C(a, ");
262 auto Chunk2
= U2
.consume("{ b }");
263 auto Chunk3
= U2
.consume(")");
265 EXPECT_THAT(std::move(Unexp
).takeResult(),
266 matchesLine(line({Chunk1
, Middle
, Chunk3
})));
269 TEST_F(MacroCallReconstructorTest
, StatementSequence
) {
270 auto Macros
= createExpander({"SEMI=;"});
271 Expansion
Exp(Lex
, *Macros
);
272 TokenList Call1
= Exp
.expand("SEMI");
273 TokenList Call2
= Exp
.expand("SEMI");
274 TokenList Call3
= Exp
.expand("SEMI");
276 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
277 Matcher
E(Exp
.getTokens(), Lex
);
278 Unexp
.addLine(line(E
.consume(";")));
279 EXPECT_TRUE(Unexp
.finished());
280 Unexp
.addLine(line(E
.consume(";")));
281 EXPECT_TRUE(Unexp
.finished());
282 Unexp
.addLine(line(E
.consume(";")));
283 EXPECT_TRUE(Unexp
.finished());
284 Matcher
U1(Call1
, Lex
);
285 Matcher
U2(Call2
, Lex
);
286 Matcher
U3(Call3
, Lex
);
287 EXPECT_THAT(std::move(Unexp
).takeResult(),
290 children({line({U2
.consume("SEMI"),
291 children({line(U3
.consume("SEMI"))})})})})));
294 TEST_F(MacroCallReconstructorTest
, NestedBlock
) {
295 auto Macros
= createExpander({"ID(x)=x"});
296 // Test: ID({ ID(a *b); })
297 // 1. expand ID(a *b) -> a *b
298 Expansion
Exp1(Lex
, *Macros
);
299 TokenList Call1
= Exp1
.expand("ID", {"a *b"});
300 // 2. expand ID({ a *b; })
302 Arg
.push_back(Lex
.id("{"));
303 Arg
.append(Exp1
.getTokens().begin(), Exp1
.getTokens().end());
304 Arg
.push_back(Lex
.id(";"));
305 Arg
.push_back(Lex
.id("}"));
306 Expansion
Exp2(Lex
, *Macros
);
307 TokenList Call2
= Exp2
.expand("ID", {Arg
});
309 // Consume as-if formatted:
313 UnexpandedMap Unexpanded
=
314 mergeUnexpanded(Exp1
.getUnexpanded(), Exp2
.getUnexpanded());
315 MacroCallReconstructor
Unexp(0, Unexpanded
);
316 Matcher
E(Exp2
.getTokens(), Lex
);
317 Unexp
.addLine(line(E
.consume("{")));
318 EXPECT_FALSE(Unexp
.finished());
319 Unexp
.addLine(line(E
.consume("a *b;")));
320 EXPECT_FALSE(Unexp
.finished());
321 Unexp
.addLine(line(E
.consume("}")));
322 EXPECT_TRUE(Unexp
.finished());
328 Matcher
U1(Call1
, Lex
);
329 Matcher
U2(Call2
, Lex
);
330 auto Chunk2Start
= U2
.consume("ID(");
331 auto Chunk2LBrace
= U2
.consume("{");
333 auto Chunk2Mid
= U2
.consume(";");
334 auto Chunk2RBrace
= U2
.consume("}");
335 auto Chunk2End
= U2
.consume(")");
336 auto Chunk1
= U1
.consume("ID(a *b)");
338 auto Expected
= line({Chunk2Start
,
341 line({Chunk1
, Chunk2Mid
}),
345 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
348 TEST_F(MacroCallReconstructorTest
, NestedChildBlocks
) {
349 auto Macros
= createExpander({"ID(x)=x", "CALL(x)=f([] { x })"});
350 // Test: ID(CALL(CALL(return a * b;)))
351 // 1. expand CALL(return a * b;)
352 Expansion
Exp1(Lex
, *Macros
);
353 TokenList Call1
= Exp1
.expand("CALL", {"return a * b;"});
354 // 2. expand CALL(f([] { return a * b; }))
355 Expansion
Exp2(Lex
, *Macros
);
356 TokenList Call2
= Exp2
.expand("CALL", {Exp1
.getTokens()});
357 // 3. expand ID({ f([] { f([] { return a * b; }) }) })
359 Arg3
.push_back(Lex
.id("{"));
360 Arg3
.append(Exp2
.getTokens().begin(), Exp2
.getTokens().end());
361 Arg3
.push_back(Lex
.id("}"));
362 Expansion
Exp3(Lex
, *Macros
);
363 TokenList Call3
= Exp3
.expand("ID", {Arg3
});
365 // Consume as-if formatted in three unwrapped lines:
373 UnexpandedMap Unexpanded
= mergeUnexpanded(
374 Exp1
.getUnexpanded(),
375 mergeUnexpanded(Exp2
.getUnexpanded(), Exp3
.getUnexpanded()));
376 MacroCallReconstructor
Unexp(0, Unexpanded
);
377 Matcher
E(Exp3
.getTokens(), Lex
);
378 Unexp
.addLine(line(E
.consume("{")));
380 line({E
.consume("f([] {"),
381 children({line({E
.consume("f([] {"),
382 children({line(E
.consume("return a * b;"))}),
385 Unexp
.addLine(line(E
.consume("}")));
386 EXPECT_TRUE(Unexp
.finished());
391 // CALL(CALL(return a * b;))
394 Matcher
U1(Call1
, Lex
);
395 Matcher
U2(Call2
, Lex
);
396 Matcher
U3(Call3
, Lex
);
397 auto Chunk3Start
= U3
.consume("ID(");
398 auto Chunk3LBrace
= U3
.consume("{");
399 U3
.consume("f([] { f([] { return a * b; }) })");
400 auto Chunk3RBrace
= U3
.consume("}");
401 auto Chunk3End
= U3
.consume(")");
402 auto Chunk2Start
= U2
.consume("CALL(");
403 U2
.consume("f([] { return a * b; })");
404 auto Chunk2End
= U2
.consume(")");
405 auto Chunk1
= U1
.consume("CALL(return a * b;)");
407 auto Expected
= line({
420 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
423 TEST_F(MacroCallReconstructorTest
, NestedChildrenMultipleArguments
) {
424 auto Macros
= createExpander({"CALL(a, b)=f([] { a; b; })"});
425 Expansion
Exp(Lex
, *Macros
);
426 TokenList Call
= Exp
.expand("CALL", {std::string("int a"), "int b"});
428 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
429 Matcher
E(Exp
.getTokens(), Lex
);
433 line(E
.consume("int a;")),
434 line(E
.consume("int b;")),
438 EXPECT_TRUE(Unexp
.finished());
439 Matcher
U(Call
, Lex
);
440 auto Expected
= line(U
.consume("CALL(int a, int b)"));
441 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
444 TEST_F(MacroCallReconstructorTest
, ReverseOrderArgumentsInExpansion
) {
445 auto Macros
= createExpander({"CALL(a, b)=b + a"});
446 Expansion
Exp(Lex
, *Macros
);
447 TokenList Call
= Exp
.expand("CALL", {std::string("x"), "y"});
449 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
450 Matcher
E(Exp
.getTokens(), Lex
);
451 Unexp
.addLine(line(E
.consume("y + x")));
452 EXPECT_TRUE(Unexp
.finished());
453 Matcher
U(Call
, Lex
);
454 auto Expected
= line(U
.consume("CALL(x, y)"));
455 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
458 TEST_F(MacroCallReconstructorTest
, MultipleToplevelUnwrappedLines
) {
459 auto Macros
= createExpander({"ID(a, b)=a b"});
460 Expansion
Exp(Lex
, *Macros
);
461 TokenList Call
= Exp
.expand("ID", {std::string("x; x"), "y"});
463 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
464 Matcher
E(Exp
.getTokens(), Lex
);
465 Unexp
.addLine(line(E
.consume("x;")));
466 Unexp
.addLine(line(E
.consume("x y")));
467 EXPECT_TRUE(Unexp
.finished());
468 Matcher
U(Call
, Lex
);
469 auto Expected
= line({
472 line(U
.consume("x;")),
473 line(U
.consume("x")),
477 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
480 TEST_F(MacroCallReconstructorTest
, NestedCallsMultipleLines
) {
481 auto Macros
= createExpander({"ID(x)=x"});
482 // Test: ID({ID(a * b);})
483 // 1. expand ID(a * b)
484 Expansion
Exp1(Lex
, *Macros
);
485 TokenList Call1
= Exp1
.expand("ID", {"a * b"});
486 // 2. expand ID({ a * b; })
487 Expansion
Exp2(Lex
, *Macros
);
489 Arg2
.push_back(Lex
.id("{"));
490 Arg2
.append(Exp1
.getTokens().begin(), Exp1
.getTokens().end());
491 Arg2
.push_back(Lex
.id(";"));
492 Arg2
.push_back(Lex
.id("}"));
493 TokenList Call2
= Exp2
.expand("ID", {Arg2
});
495 // Consume as-if formatted in three unwrapped lines:
499 UnexpandedMap Unexpanded
=
500 mergeUnexpanded(Exp1
.getUnexpanded(), Exp2
.getUnexpanded());
501 MacroCallReconstructor
Unexp(0, Unexpanded
);
502 Matcher
E(Exp2
.getTokens(), Lex
);
503 Unexp
.addLine(line(E
.consume("{")));
504 Unexp
.addLine(line(E
.consume("a * b;")));
505 Unexp
.addLine(line(E
.consume("}")));
506 EXPECT_TRUE(Unexp
.finished());
514 Matcher
U1(Call1
, Lex
);
515 Matcher
U2(Call2
, Lex
);
516 auto Chunk2Start
= U2
.consume("ID(");
517 auto Chunk2LBrace
= U2
.consume("{");
519 auto Chunk2Semi
= U2
.consume(";");
520 auto Chunk2RBrace
= U2
.consume("}");
521 auto Chunk2End
= U2
.consume(")");
522 auto Chunk1
= U1
.consume("ID(a * b)");
524 auto Expected
= line({
527 line({Chunk2LBrace
}),
528 line({Chunk1
, Chunk2Semi
}),
529 line({Chunk2RBrace
}),
533 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
536 TEST_F(MacroCallReconstructorTest
, ParentOutsideMacroCall
) {
537 auto Macros
= createExpander({"ID(a)=a"});
538 Expansion
Exp(Lex
, *Macros
);
539 TokenList Call
= Exp
.expand("ID", {std::string("x; y; z;")});
541 auto Prefix
= tokens("int a = []() {");
542 auto Postfix
= tokens("}();");
543 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
544 Matcher
E(Exp
.getTokens(), Lex
);
548 line(E
.consume("x;")),
549 line(E
.consume("y;")),
550 line(E
.consume("z;")),
554 EXPECT_TRUE(Unexp
.finished());
555 Matcher
U(Call
, Lex
);
556 auto Expected
= line({
562 line(U
.consume("x;")),
563 line(U
.consume("y;")),
564 line(U
.consume("z;")),
571 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
574 TEST_F(MacroCallReconstructorTest
, ChildrenSplitAcrossArguments
) {
575 auto Macros
= createExpander({"CALL(a, b)=f([]() a b)"});
576 Expansion
Exp(Lex
, *Macros
);
577 TokenList Call
= Exp
.expand("CALL", {std::string("{ a;"), "b; }"});
579 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
580 Matcher
E(Exp
.getTokens(), Lex
);
582 E
.consume("f([]() {"),
584 line(E
.consume("a;")),
585 line(E
.consume("b;")),
589 EXPECT_TRUE(Unexp
.finished());
590 Matcher
U(Call
, Lex
);
591 auto Expected
= line({
593 children(line(U
.consume("a;"))),
594 U
.consume(", b; })"),
596 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
599 TEST_F(MacroCallReconstructorTest
, ChildrenAfterMacroCall
) {
600 auto Macros
= createExpander({"CALL(a, b)=f([]() a b"});
601 Expansion
Exp(Lex
, *Macros
);
602 TokenList Call
= Exp
.expand("CALL", {std::string("{ a"), "b"});
604 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
605 Matcher
E(Exp
.getTokens(), Lex
);
606 auto Semi
= tokens(";");
607 auto SecondLine
= tokens("c d;");
608 auto ThirdLine
= tokens("e f;");
609 auto Postfix
= tokens("})");
611 E
.consume("f([]() {"),
613 line({E
.consume("a b"), Semi
}),
619 EXPECT_TRUE(Unexp
.finished());
620 Matcher
U(Call
, Lex
);
621 auto Expected
= line({
623 children(line(U
.consume("a"))),
634 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
637 TEST_F(MacroCallReconstructorTest
, InvalidCodeSplittingBracesAcrossArgs
) {
638 auto Macros
= createExpander({"M(a, b, c)=(a) (b) c"});
639 Expansion
Exp(Lex
, *Macros
);
640 TokenList Call
= Exp
.expand("M", {std::string("{"), "x", ""});
642 MacroCallReconstructor
Unexp(0, Exp
.getUnexpanded());
643 Matcher
E(Exp
.getTokens(), Lex
);
644 auto Prefix
= tokens("({");
650 children({line(E
.consume(")(x)"))}),
654 EXPECT_TRUE(Unexp
.finished());
655 Matcher
U(Call
, Lex
);
656 auto Expected
= line({
658 children({line(U
.consume("M({,x,)"))}),
660 EXPECT_THAT(std::move(Unexp
).takeResult(), matchesLine(Expected
));
664 } // namespace format