[AMDGPU][AsmParser][NFC] Get rid of custom default operand handlers.
[llvm-project.git] / clang / unittests / Format / MacroCallReconstructorTest.cpp
blob6e6900577d165ceb8b4ba37164a9608b18b48b7e
1 #include "../../lib/Format/Macros.h"
2 #include "../../lib/Format/UnwrappedLineParser.h"
3 #include "TestLexer.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"
10 #include <map>
11 #include <memory>
12 #include <vector>
14 namespace clang {
15 namespace format {
16 namespace {
18 using UnexpandedMap =
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
25 // getUnexpanded().
26 class Expansion {
27 public:
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.
33 TokenList
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; }
49 private:
50 TokenList expandInternal(
51 llvm::StringRef Name,
52 const std::optional<SmallVector<llvm::SmallVector<FormatToken *, 8>, 1>>
53 &Args) {
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(),
63 I->end());
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)));
83 return Result;
85 llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>> Unexpanded;
86 llvm::SmallVector<FormatToken *, 8> Tokens;
87 TestLexer &Lex;
88 MacroExpander &Macros;
91 struct Chunk {
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.
104 struct Matcher {
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) {
111 return true;
113 llvm::dbgs() << Left->TokenText << " != " << Right->TokenText << "\n";
114 return false;
117 Chunk consume(StringRef Tokens) {
118 TokenList Result;
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);
123 ++It;
125 return Chunk(Result);
128 TokenList Tokens;
129 TokenList::iterator It;
130 TestLexer &Lex;
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);
140 return Result;
143 class MacroCallReconstructorTest : public ::testing::Test {
144 public:
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));
158 return Result;
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(),
167 Chunk.Tokens.end());
168 assert(!Result.Tokens.empty());
169 Result.Tokens.back().Children.append(Chunk.Children.begin(),
170 Chunk.Children.end());
172 return Result;
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;
185 TestLexer Lex;
188 bool matchesTokens(const UnwrappedLine &L1, const UnwrappedLine &L2) {
189 if (L1.Tokens.size() != L2.Tokens.size())
190 return false;
191 for (auto L1It = L1.Tokens.begin(), L2It = L2.Tokens.begin();
192 L1It != L1.Tokens.end(); ++L1It, ++L2It) {
193 if (L1It->Tok != L2It->Tok)
194 return false;
195 if (L1It->Children.size() != L2It->Children.size())
196 return false;
197 for (auto L1ChildIt = L1It->Children.begin(),
198 L2ChildIt = L2It->Children.begin();
199 L1ChildIt != L1It->Children.end(); ++L1ChildIt, ++L2ChildIt) {
200 if (!matchesTokens(*L1ChildIt, *L2ChildIt))
201 return false;
204 return true;
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(),
288 matchesLine(line(
289 {U1.consume("SEMI"),
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; })
301 TokenList Arg;
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:
310 // {
311 // a *b;
312 // }
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());
324 // Expect lines:
325 // ID({
326 // ID(a *b);
327 // })
328 Matcher U1(Call1, Lex);
329 Matcher U2(Call2, Lex);
330 auto Chunk2Start = U2.consume("ID(");
331 auto Chunk2LBrace = U2.consume("{");
332 U2.consume("a *b");
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,
339 children({
340 line(Chunk2LBrace),
341 line({Chunk1, Chunk2Mid}),
342 line(Chunk2RBrace),
344 Chunk2End});
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; }) }) })
358 TokenList Arg3;
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:
366 // 0: {
367 // 1: f([] {
368 // f([] {
369 // return a * b;
370 // })
371 // })
372 // 2: }
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("{")));
379 Unexp.addLine(
380 line({E.consume("f([] {"),
381 children({line({E.consume("f([] {"),
382 children({line(E.consume("return a * b;"))}),
383 E.consume("})")})}),
384 E.consume("})")}));
385 Unexp.addLine(line(E.consume("}")));
386 EXPECT_TRUE(Unexp.finished());
388 // Expect lines:
389 // ID(
390 // {
391 // CALL(CALL(return a * b;))
392 // }
393 // )
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({
408 Chunk3Start,
409 children({
410 line(Chunk3LBrace),
411 line({
412 Chunk2Start,
413 Chunk1,
414 Chunk2End,
416 line(Chunk3RBrace),
418 Chunk3End,
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);
430 Unexp.addLine(line({
431 E.consume("f([] {"),
432 children({
433 line(E.consume("int a;")),
434 line(E.consume("int b;")),
436 E.consume("})"),
437 }));
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({
470 U.consume("ID("),
471 children({
472 line(U.consume("x;")),
473 line(U.consume("x")),
475 U.consume(", y)"),
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);
488 TokenList Arg2;
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:
496 // 0: {
497 // 1: a * b;
498 // 2: }
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());
508 // Expect lines:
509 // ID(
510 // {
511 // ID(a * b);
512 // }
513 // )
514 Matcher U1(Call1, Lex);
515 Matcher U2(Call2, Lex);
516 auto Chunk2Start = U2.consume("ID(");
517 auto Chunk2LBrace = U2.consume("{");
518 U2.consume("a * b");
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({
525 Chunk2Start,
526 children({
527 line({Chunk2LBrace}),
528 line({Chunk1, Chunk2Semi}),
529 line({Chunk2RBrace}),
531 Chunk2End,
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);
545 Unexp.addLine(line({
546 Prefix,
547 children({
548 line(E.consume("x;")),
549 line(E.consume("y;")),
550 line(E.consume("z;")),
552 Postfix,
553 }));
554 EXPECT_TRUE(Unexp.finished());
555 Matcher U(Call, Lex);
556 auto Expected = line({
557 Prefix,
558 children({
559 line({
560 U.consume("ID("),
561 children({
562 line(U.consume("x;")),
563 line(U.consume("y;")),
564 line(U.consume("z;")),
566 U.consume(")"),
569 Postfix,
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);
581 Unexp.addLine(line({
582 E.consume("f([]() {"),
583 children({
584 line(E.consume("a;")),
585 line(E.consume("b;")),
587 E.consume("})"),
588 }));
589 EXPECT_TRUE(Unexp.finished());
590 Matcher U(Call, Lex);
591 auto Expected = line({
592 U.consume("CALL({"),
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("})");
610 Unexp.addLine(line({
611 E.consume("f([]() {"),
612 children({
613 line({E.consume("a b"), Semi}),
614 line(SecondLine),
615 line(ThirdLine),
617 Postfix,
618 }));
619 EXPECT_TRUE(Unexp.finished());
620 Matcher U(Call, Lex);
621 auto Expected = line({
622 U.consume("CALL({"),
623 children(line(U.consume("a"))),
624 U.consume(", b)"),
625 Semi,
626 children(line({
627 SecondLine,
628 children(line({
629 ThirdLine,
630 Postfix,
631 })),
632 })),
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("({");
645 Unexp.addLine(line({
646 Prefix,
647 children({
648 line({
649 E.consume("({"),
650 children({line(E.consume(")(x)"))}),
653 }));
654 EXPECT_TRUE(Unexp.finished());
655 Matcher U(Call, Lex);
656 auto Expected = line({
657 Prefix,
658 children({line(U.consume("M({,x,)"))}),
660 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
663 } // namespace
664 } // namespace format
665 } // namespace clang