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"
7
8 #include "gmock/gmock.h"
9 #include "gtest/gtest.h"
10 #include <map>
11 #include <memory>
12 #include <vector>
13
14 namespace clang {
15 namespace format {
16 namespace {
17
18 using UnexpandedMap =
19 llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>>;
20
21 // Keeps track of a sequence of macro expansions.
22 //
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:
Expansion(TestLexer & Lex,MacroExpander & Macros)28 Expansion(TestLexer &Lex, MacroExpander &Macros) : Lex(Lex), Macros(Macros) {}
29
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
expand(llvm::StringRef Name,const SmallVector<llvm::SmallVector<FormatToken *,8>,1> & Args)34 expand(llvm::StringRef Name,
35 const SmallVector<llvm::SmallVector<FormatToken *, 8>, 1> &Args) {
36 auto *ID = Lex.id(Name);
37 auto UnexpandedLine = std::make_unique<UnwrappedLine>();
38 UnexpandedLine->Tokens.push_back(ID);
39 if (!Args.empty()) {
40 UnexpandedLine->Tokens.push_back(Lex.id("("));
41 for (auto I = Args.begin(), E = Args.end(); I != E; ++I) {
42 if (I != Args.begin())
43 UnexpandedLine->Tokens.push_back(Lex.id(","));
44 UnexpandedLine->Tokens.insert(UnexpandedLine->Tokens.end(), I->begin(),
45 I->end());
46 }
47 UnexpandedLine->Tokens.push_back(Lex.id(")"));
48 }
49 Unexpanded[ID] = std::move(UnexpandedLine);
50
51 auto Expanded = uneof(Macros.expand(ID, Args));
52 Tokens.append(Expanded.begin(), Expanded.end());
53
54 TokenList UnexpandedTokens;
55 for (const UnwrappedLineNode &Node : Unexpanded[ID]->Tokens) {
56 UnexpandedTokens.push_back(Node.Tok);
57 }
58 return UnexpandedTokens;
59 }
60
expand(llvm::StringRef Name,const std::vector<std::string> & Args={})61 TokenList expand(llvm::StringRef Name,
62 const std::vector<std::string> &Args = {}) {
63 return expand(Name, lexArgs(Args));
64 }
65
getUnexpanded() const66 const UnexpandedMap &getUnexpanded() const { return Unexpanded; }
67
getTokens() const68 const TokenList &getTokens() const { return Tokens; }
69
70 private:
71 llvm::SmallVector<TokenList, 1>
lexArgs(const std::vector<std::string> & Args)72 lexArgs(const std::vector<std::string> &Args) {
73 llvm::SmallVector<TokenList, 1> Result;
74 for (const auto &Arg : Args) {
75 Result.push_back(uneof(Lex.lex(Arg)));
76 }
77 return Result;
78 }
79 llvm::DenseMap<FormatToken *, std::unique_ptr<UnwrappedLine>> Unexpanded;
80 llvm::SmallVector<FormatToken *, 8> Tokens;
81 TestLexer &Lex;
82 MacroExpander &Macros;
83 };
84
85 struct Chunk {
Chunkclang::format::__anon35b0f3090111::Chunk86 Chunk(llvm::ArrayRef<FormatToken *> Tokens)
87 : Tokens(Tokens.begin(), Tokens.end()) {}
Chunkclang::format::__anon35b0f3090111::Chunk88 Chunk(llvm::ArrayRef<UnwrappedLine> Children)
89 : Children(Children.begin(), Children.end()) {}
90 llvm::SmallVector<UnwrappedLineNode, 1> Tokens;
91 llvm::SmallVector<UnwrappedLine, 0> Children;
92 };
93
94 // Allows to produce chunks of a token list by typing the code of equal tokens.
95 //
96 // Created from a list of tokens, users call "consume" to get the next chunk
97 // of tokens, checking that they match the written code.
98 struct Matcher {
Matcherclang::format::__anon35b0f3090111::Matcher99 Matcher(const TokenList &Tokens, TestLexer &Lex)
100 : Tokens(Tokens), It(this->Tokens.begin()), Lex(Lex) {}
101
consumeclang::format::__anon35b0f3090111::Matcher102 Chunk consume(StringRef Tokens) {
103 TokenList Result;
104 for (const FormatToken *Token : uneof(Lex.lex(Tokens))) {
105 (void)Token; // Fix unused variable warning when asserts are disabled.
106 assert((*It)->getType() == Token->getType() &&
107 (*It)->TokenText == Token->TokenText);
108 Result.push_back(*It);
109 ++It;
110 }
111 return Chunk(Result);
112 }
113
114 TokenList Tokens;
115 TokenList::iterator It;
116 TestLexer &Lex;
117 };
118
mergeUnexpanded(const UnexpandedMap & M1,const UnexpandedMap & M2)119 UnexpandedMap mergeUnexpanded(const UnexpandedMap &M1,
120 const UnexpandedMap &M2) {
121 UnexpandedMap Result;
122 for (const auto &KV : M1) {
123 Result[KV.first] = std::make_unique<UnwrappedLine>(*KV.second);
124 }
125 for (const auto &KV : M2) {
126 Result[KV.first] = std::make_unique<UnwrappedLine>(*KV.second);
127 }
128 return Result;
129 }
130
131 class MacroCallReconstructorTest : public ::testing::Test {
132 public:
MacroCallReconstructorTest()133 MacroCallReconstructorTest() : Lex(Allocator, Buffers) {}
134
135 std::unique_ptr<MacroExpander>
createExpander(const std::vector<std::string> & MacroDefinitions)136 createExpander(const std::vector<std::string> &MacroDefinitions) {
137 return std::make_unique<MacroExpander>(MacroDefinitions,
138 Lex.SourceMgr.get(), Lex.Style,
139 Lex.Allocator, Lex.IdentTable);
140 }
141
line(llvm::ArrayRef<FormatToken * > Tokens)142 UnwrappedLine line(llvm::ArrayRef<FormatToken *> Tokens) {
143 UnwrappedLine Result;
144 for (FormatToken *Tok : Tokens) {
145 Result.Tokens.push_back(UnwrappedLineNode(Tok));
146 }
147 return Result;
148 }
149
line(llvm::StringRef Text)150 UnwrappedLine line(llvm::StringRef Text) { return line({lex(Text)}); }
151
line(llvm::ArrayRef<Chunk> Chunks)152 UnwrappedLine line(llvm::ArrayRef<Chunk> Chunks) {
153 UnwrappedLine Result;
154 for (const Chunk &Chunk : Chunks) {
155 Result.Tokens.insert(Result.Tokens.end(), Chunk.Tokens.begin(),
156 Chunk.Tokens.end());
157 assert(!Result.Tokens.empty());
158 Result.Tokens.back().Children.append(Chunk.Children.begin(),
159 Chunk.Children.end());
160 }
161 return Result;
162 }
163
lex(llvm::StringRef Text)164 TokenList lex(llvm::StringRef Text) { return uneof(Lex.lex(Text)); }
165
tokens(llvm::StringRef Text)166 Chunk tokens(llvm::StringRef Text) { return Chunk(lex(Text)); }
167
children(llvm::ArrayRef<UnwrappedLine> Children)168 Chunk children(llvm::ArrayRef<UnwrappedLine> Children) {
169 return Chunk(Children);
170 }
171
172 llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
173 std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers;
174 TestLexer Lex;
175 };
176
matchesTokens(const UnwrappedLine & L1,const UnwrappedLine & L2)177 bool matchesTokens(const UnwrappedLine &L1, const UnwrappedLine &L2) {
178 if (L1.Tokens.size() != L2.Tokens.size())
179 return false;
180 for (auto L1It = L1.Tokens.begin(), L2It = L2.Tokens.begin();
181 L1It != L1.Tokens.end(); ++L1It, ++L2It) {
182 if (L1It->Tok != L2It->Tok)
183 return false;
184 if (L1It->Children.size() != L2It->Children.size())
185 return false;
186 for (auto L1ChildIt = L1It->Children.begin(),
187 L2ChildIt = L2It->Children.begin();
188 L1ChildIt != L1It->Children.end(); ++L1ChildIt, ++L2ChildIt) {
189 if (!matchesTokens(*L1ChildIt, *L2ChildIt))
190 return false;
191 }
192 }
193 return true;
194 }
195 MATCHER_P(matchesLine, line, "") { return matchesTokens(arg, line); }
196
TEST_F(MacroCallReconstructorTest,Identifier)197 TEST_F(MacroCallReconstructorTest, Identifier) {
198 auto Macros = createExpander({"X=x"});
199 Expansion Exp(Lex, *Macros);
200 TokenList Call = Exp.expand("X");
201
202 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
203 Unexp.addLine(line(Exp.getTokens()));
204 EXPECT_TRUE(Unexp.finished());
205 Matcher U(Call, Lex);
206 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(line(U.consume("X"))));
207 }
208
TEST_F(MacroCallReconstructorTest,NestedLineWithinCall)209 TEST_F(MacroCallReconstructorTest, NestedLineWithinCall) {
210 auto Macros = createExpander({"C(a)=class X { a; };"});
211 Expansion Exp(Lex, *Macros);
212 TokenList Call = Exp.expand("C", {"void f()"});
213
214 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
215 Matcher E(Exp.getTokens(), Lex);
216 Unexp.addLine(line(E.consume("class X {")));
217 EXPECT_FALSE(Unexp.finished());
218 Unexp.addLine(line(E.consume("void f();")));
219 EXPECT_FALSE(Unexp.finished());
220 Unexp.addLine(line(E.consume("};")));
221 EXPECT_TRUE(Unexp.finished());
222 Matcher U(Call, Lex);
223 EXPECT_THAT(std::move(Unexp).takeResult(),
224 matchesLine(line(U.consume("C(void f())"))));
225 }
226
TEST_F(MacroCallReconstructorTest,MultipleLinesInNestedMultiParamsExpansion)227 TEST_F(MacroCallReconstructorTest, MultipleLinesInNestedMultiParamsExpansion) {
228 auto Macros = createExpander({"C(a, b)=a b", "B(a)={a}"});
229 Expansion Exp1(Lex, *Macros);
230 TokenList Call1 = Exp1.expand("B", {"b"});
231 Expansion Exp2(Lex, *Macros);
232 TokenList Call2 = Exp2.expand("C", {uneof(Lex.lex("a")), Exp1.getTokens()});
233
234 UnexpandedMap Unexpanded =
235 mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded());
236 MacroCallReconstructor Unexp(0, Unexpanded);
237 Matcher E(Exp2.getTokens(), Lex);
238 Unexp.addLine(line(E.consume("a")));
239 EXPECT_FALSE(Unexp.finished());
240 Unexp.addLine(line(E.consume("{")));
241 EXPECT_FALSE(Unexp.finished());
242 Unexp.addLine(line(E.consume("b")));
243 EXPECT_FALSE(Unexp.finished());
244 Unexp.addLine(line(E.consume("}")));
245 EXPECT_TRUE(Unexp.finished());
246
247 Matcher U1(Call1, Lex);
248 auto Middle = U1.consume("B(b)");
249 Matcher U2(Call2, Lex);
250 auto Chunk1 = U2.consume("C(a, ");
251 auto Chunk2 = U2.consume("{ b }");
252 auto Chunk3 = U2.consume(")");
253
254 EXPECT_THAT(std::move(Unexp).takeResult(),
255 matchesLine(line({Chunk1, Middle, Chunk3})));
256 }
257
TEST_F(MacroCallReconstructorTest,StatementSequence)258 TEST_F(MacroCallReconstructorTest, StatementSequence) {
259 auto Macros = createExpander({"SEMI=;"});
260 Expansion Exp(Lex, *Macros);
261 TokenList Call1 = Exp.expand("SEMI");
262 TokenList Call2 = Exp.expand("SEMI");
263 TokenList Call3 = Exp.expand("SEMI");
264
265 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
266 Matcher E(Exp.getTokens(), Lex);
267 Unexp.addLine(line(E.consume(";")));
268 EXPECT_TRUE(Unexp.finished());
269 Unexp.addLine(line(E.consume(";")));
270 EXPECT_TRUE(Unexp.finished());
271 Unexp.addLine(line(E.consume(";")));
272 EXPECT_TRUE(Unexp.finished());
273 Matcher U1(Call1, Lex);
274 Matcher U2(Call2, Lex);
275 Matcher U3(Call3, Lex);
276 EXPECT_THAT(std::move(Unexp).takeResult(),
277 matchesLine(line(
278 {U1.consume("SEMI"),
279 children({line({U2.consume("SEMI"),
280 children({line(U3.consume("SEMI"))})})})})));
281 }
282
TEST_F(MacroCallReconstructorTest,NestedBlock)283 TEST_F(MacroCallReconstructorTest, NestedBlock) {
284 auto Macros = createExpander({"ID(x)=x"});
285 // Test: ID({ ID(a *b); })
286 // 1. expand ID(a *b) -> a *b
287 Expansion Exp1(Lex, *Macros);
288 TokenList Call1 = Exp1.expand("ID", {"a *b"});
289 // 2. expand ID({ a *b; })
290 TokenList Arg;
291 Arg.push_back(Lex.id("{"));
292 Arg.append(Exp1.getTokens().begin(), Exp1.getTokens().end());
293 Arg.push_back(Lex.id(";"));
294 Arg.push_back(Lex.id("}"));
295 Expansion Exp2(Lex, *Macros);
296 TokenList Call2 = Exp2.expand("ID", {Arg});
297
298 // Consume as-if formatted:
299 // {
300 // a *b;
301 // }
302 UnexpandedMap Unexpanded =
303 mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded());
304 MacroCallReconstructor Unexp(0, Unexpanded);
305 Matcher E(Exp2.getTokens(), Lex);
306 Unexp.addLine(line(E.consume("{")));
307 EXPECT_FALSE(Unexp.finished());
308 Unexp.addLine(line(E.consume("a *b;")));
309 EXPECT_FALSE(Unexp.finished());
310 Unexp.addLine(line(E.consume("}")));
311 EXPECT_TRUE(Unexp.finished());
312
313 // Expect lines:
314 // ID({
315 // ID(a *b);
316 // })
317 Matcher U1(Call1, Lex);
318 Matcher U2(Call2, Lex);
319 auto Chunk2Start = U2.consume("ID(");
320 auto Chunk2LBrace = U2.consume("{");
321 U2.consume("a *b");
322 auto Chunk2Mid = U2.consume(";");
323 auto Chunk2RBrace = U2.consume("}");
324 auto Chunk2End = U2.consume(")");
325 auto Chunk1 = U1.consume("ID(a *b)");
326
327 auto Expected = line({Chunk2Start,
328 children({
329 line(Chunk2LBrace),
330 line({Chunk1, Chunk2Mid}),
331 line(Chunk2RBrace),
332 }),
333 Chunk2End});
334 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
335 }
336
TEST_F(MacroCallReconstructorTest,NestedChildBlocks)337 TEST_F(MacroCallReconstructorTest, NestedChildBlocks) {
338 auto Macros = createExpander({"ID(x)=x", "CALL(x)=f([] { x })"});
339 // Test: ID(CALL(CALL(return a * b;)))
340 // 1. expand CALL(return a * b;)
341 Expansion Exp1(Lex, *Macros);
342 TokenList Call1 = Exp1.expand("CALL", {"return a * b;"});
343 // 2. expand CALL(f([] { return a * b; }))
344 Expansion Exp2(Lex, *Macros);
345 TokenList Call2 = Exp2.expand("CALL", {Exp1.getTokens()});
346 // 3. expand ID({ f([] { f([] { return a * b; }) }) })
347 TokenList Arg3;
348 Arg3.push_back(Lex.id("{"));
349 Arg3.append(Exp2.getTokens().begin(), Exp2.getTokens().end());
350 Arg3.push_back(Lex.id("}"));
351 Expansion Exp3(Lex, *Macros);
352 TokenList Call3 = Exp3.expand("ID", {Arg3});
353
354 // Consume as-if formatted in three unwrapped lines:
355 // 0: {
356 // 1: f([] {
357 // f([] {
358 // return a * b;
359 // })
360 // })
361 // 2: }
362 UnexpandedMap Unexpanded = mergeUnexpanded(
363 Exp1.getUnexpanded(),
364 mergeUnexpanded(Exp2.getUnexpanded(), Exp3.getUnexpanded()));
365 MacroCallReconstructor Unexp(0, Unexpanded);
366 Matcher E(Exp3.getTokens(), Lex);
367 Unexp.addLine(line(E.consume("{")));
368 Unexp.addLine(
369 line({E.consume("f([] {"),
370 children({line({E.consume("f([] {"),
371 children({line(E.consume("return a * b;"))}),
372 E.consume("})")})}),
373 E.consume("})")}));
374 Unexp.addLine(line(E.consume("}")));
375 EXPECT_TRUE(Unexp.finished());
376
377 // Expect lines:
378 // ID(
379 // {
380 // CALL(CALL(return a * b;))
381 // }
382 // )
383 Matcher U1(Call1, Lex);
384 Matcher U2(Call2, Lex);
385 Matcher U3(Call3, Lex);
386 auto Chunk3Start = U3.consume("ID(");
387 auto Chunk3LBrace = U3.consume("{");
388 U3.consume("f([] { f([] { return a * b; }) })");
389 auto Chunk3RBrace = U3.consume("}");
390 auto Chunk3End = U3.consume(")");
391 auto Chunk2Start = U2.consume("CALL(");
392 U2.consume("f([] { return a * b; })");
393 auto Chunk2End = U2.consume(")");
394 auto Chunk1 = U1.consume("CALL(return a * b;)");
395
396 auto Expected = line({
397 Chunk3Start,
398 children({
399 line(Chunk3LBrace),
400 line({
401 Chunk2Start,
402 Chunk1,
403 Chunk2End,
404 }),
405 line(Chunk3RBrace),
406 }),
407 Chunk3End,
408 });
409 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
410 }
411
TEST_F(MacroCallReconstructorTest,NestedChildrenMultipleArguments)412 TEST_F(MacroCallReconstructorTest, NestedChildrenMultipleArguments) {
413 auto Macros = createExpander({"CALL(a, b)=f([] { a; b; })"});
414 Expansion Exp(Lex, *Macros);
415 TokenList Call = Exp.expand("CALL", {std::string("int a"), "int b"});
416
417 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
418 Matcher E(Exp.getTokens(), Lex);
419 Unexp.addLine(line({
420 E.consume("f([] {"),
421 children({
422 line(E.consume("int a;")),
423 line(E.consume("int b;")),
424 }),
425 E.consume("})"),
426 }));
427 EXPECT_TRUE(Unexp.finished());
428 Matcher U(Call, Lex);
429 auto Expected = line(U.consume("CALL(int a, int b)"));
430 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
431 }
432
TEST_F(MacroCallReconstructorTest,ReverseOrderArgumentsInExpansion)433 TEST_F(MacroCallReconstructorTest, ReverseOrderArgumentsInExpansion) {
434 auto Macros = createExpander({"CALL(a, b)=b + a"});
435 Expansion Exp(Lex, *Macros);
436 TokenList Call = Exp.expand("CALL", {std::string("x"), "y"});
437
438 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
439 Matcher E(Exp.getTokens(), Lex);
440 Unexp.addLine(line(E.consume("y + x")));
441 EXPECT_TRUE(Unexp.finished());
442 Matcher U(Call, Lex);
443 auto Expected = line(U.consume("CALL(x, y)"));
444 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
445 }
446
TEST_F(MacroCallReconstructorTest,MultipleToplevelUnwrappedLines)447 TEST_F(MacroCallReconstructorTest, MultipleToplevelUnwrappedLines) {
448 auto Macros = createExpander({"ID(a, b)=a b"});
449 Expansion Exp(Lex, *Macros);
450 TokenList Call = Exp.expand("ID", {std::string("x; x"), "y"});
451
452 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
453 Matcher E(Exp.getTokens(), Lex);
454 Unexp.addLine(line(E.consume("x;")));
455 Unexp.addLine(line(E.consume("x y")));
456 EXPECT_TRUE(Unexp.finished());
457 Matcher U(Call, Lex);
458 auto Expected = line({
459 U.consume("ID("),
460 children({
461 line(U.consume("x;")),
462 line(U.consume("x")),
463 }),
464 U.consume(", y)"),
465 });
466 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
467 }
468
TEST_F(MacroCallReconstructorTest,NestedCallsMultipleLines)469 TEST_F(MacroCallReconstructorTest, NestedCallsMultipleLines) {
470 auto Macros = createExpander({"ID(x)=x"});
471 // Test: ID({ID(a * b);})
472 // 1. expand ID(a * b)
473 Expansion Exp1(Lex, *Macros);
474 TokenList Call1 = Exp1.expand("ID", {"a * b"});
475 // 2. expand ID({ a * b; })
476 Expansion Exp2(Lex, *Macros);
477 TokenList Arg2;
478 Arg2.push_back(Lex.id("{"));
479 Arg2.append(Exp1.getTokens().begin(), Exp1.getTokens().end());
480 Arg2.push_back(Lex.id(";"));
481 Arg2.push_back(Lex.id("}"));
482 TokenList Call2 = Exp2.expand("ID", {Arg2});
483
484 // Consume as-if formatted in three unwrapped lines:
485 // 0: {
486 // 1: a * b;
487 // 2: }
488 UnexpandedMap Unexpanded =
489 mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded());
490 MacroCallReconstructor Unexp(0, Unexpanded);
491 Matcher E(Exp2.getTokens(), Lex);
492 Unexp.addLine(line(E.consume("{")));
493 Unexp.addLine(line(E.consume("a * b;")));
494 Unexp.addLine(line(E.consume("}")));
495 EXPECT_TRUE(Unexp.finished());
496
497 // Expect lines:
498 // ID(
499 // {
500 // ID(a * b);
501 // }
502 // )
503 Matcher U1(Call1, Lex);
504 Matcher U2(Call2, Lex);
505 auto Chunk2Start = U2.consume("ID(");
506 auto Chunk2LBrace = U2.consume("{");
507 U2.consume("a * b");
508 auto Chunk2Semi = U2.consume(";");
509 auto Chunk2RBrace = U2.consume("}");
510 auto Chunk2End = U2.consume(")");
511 auto Chunk1 = U1.consume("ID(a * b)");
512
513 auto Expected = line({
514 Chunk2Start,
515 children({
516 line({Chunk2LBrace}),
517 line({Chunk1, Chunk2Semi}),
518 line({Chunk2RBrace}),
519 }),
520 Chunk2End,
521 });
522 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
523 }
524
TEST_F(MacroCallReconstructorTest,ParentOutsideMacroCall)525 TEST_F(MacroCallReconstructorTest, ParentOutsideMacroCall) {
526 auto Macros = createExpander({"ID(a)=a"});
527 Expansion Exp(Lex, *Macros);
528 TokenList Call = Exp.expand("ID", {std::string("x; y; z;")});
529
530 auto Prefix = tokens("int a = []() {");
531 auto Postfix = tokens("}();");
532 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
533 Matcher E(Exp.getTokens(), Lex);
534 Unexp.addLine(line({
535 Prefix,
536 children({
537 line(E.consume("x;")),
538 line(E.consume("y;")),
539 line(E.consume("z;")),
540 }),
541 Postfix,
542 }));
543 EXPECT_TRUE(Unexp.finished());
544 Matcher U(Call, Lex);
545 auto Expected = line({
546 Prefix,
547 children({
548 line({
549 U.consume("ID("),
550 children({
551 line(U.consume("x;")),
552 line(U.consume("y;")),
553 line(U.consume("z;")),
554 }),
555 U.consume(")"),
556 }),
557 }),
558 Postfix,
559 });
560 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
561 }
562
TEST_F(MacroCallReconstructorTest,UnusedMacroArguments)563 TEST_F(MacroCallReconstructorTest, UnusedMacroArguments) {
564 auto Macros = createExpander({"X=x"});
565 Expansion Exp(Lex, *Macros);
566 TokenList Call = Exp.expand("X", {"a", "b", "c"});
567
568 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
569 Unexp.addLine(line(Exp.getTokens()));
570 EXPECT_TRUE(Unexp.finished());
571 Matcher U(Call, Lex);
572 EXPECT_THAT(std::move(Unexp).takeResult(),
573 matchesLine(line(U.consume("X(a, b, c)"))));
574 }
575
TEST_F(MacroCallReconstructorTest,UnusedEmptyMacroArgument)576 TEST_F(MacroCallReconstructorTest, UnusedEmptyMacroArgument) {
577 auto Macros = createExpander({"X=x"});
578 Expansion Exp(Lex, *Macros);
579 TokenList Call = Exp.expand("X", {std::string("")});
580
581 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
582 Matcher E(Exp.getTokens(), Lex);
583 auto Semi = tokens(";");
584 Unexp.addLine(line({E.consume("x"), Semi}));
585 EXPECT_TRUE(Unexp.finished());
586 Matcher U(Call, Lex);
587 EXPECT_THAT(std::move(Unexp).takeResult(),
588 matchesLine(line({U.consume("X()"), Semi})));
589 }
590
TEST_F(MacroCallReconstructorTest,ChildrenSplitAcrossArguments)591 TEST_F(MacroCallReconstructorTest, ChildrenSplitAcrossArguments) {
592 auto Macros = createExpander({"CALL(a, b)=f([]() a b)"});
593 Expansion Exp(Lex, *Macros);
594 TokenList Call = Exp.expand("CALL", {std::string("{ a;"), "b; }"});
595
596 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
597 Matcher E(Exp.getTokens(), Lex);
598 Unexp.addLine(line({
599 E.consume("f([]() {"),
600 children({
601 line(E.consume("a;")),
602 line(E.consume("b;")),
603 }),
604 E.consume("})"),
605 }));
606 EXPECT_TRUE(Unexp.finished());
607 Matcher U(Call, Lex);
608 auto Expected = line({
609 U.consume("CALL({"),
610 children(line(U.consume("a;"))),
611 U.consume(", b; })"),
612 });
613 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
614 }
615
TEST_F(MacroCallReconstructorTest,ChildrenAfterMacroCall)616 TEST_F(MacroCallReconstructorTest, ChildrenAfterMacroCall) {
617 auto Macros = createExpander({"CALL(a, b)=f([]() a b"});
618 Expansion Exp(Lex, *Macros);
619 TokenList Call = Exp.expand("CALL", {std::string("{ a"), "b"});
620
621 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
622 Matcher E(Exp.getTokens(), Lex);
623 auto Semi = tokens(";");
624 auto SecondLine = tokens("c d;");
625 auto ThirdLine = tokens("e f;");
626 auto Postfix = tokens("})");
627 Unexp.addLine(line({
628 E.consume("f([]() {"),
629 children({
630 line({E.consume("a b"), Semi}),
631 line(SecondLine),
632 line(ThirdLine),
633 }),
634 Postfix,
635 }));
636 EXPECT_TRUE(Unexp.finished());
637 Matcher U(Call, Lex);
638 auto Expected = line({
639 U.consume("CALL({"),
640 children(line(U.consume("a"))),
641 U.consume(", b)"),
642 Semi,
643 children(line({
644 SecondLine,
645 children(line({
646 ThirdLine,
647 Postfix,
648 })),
649 })),
650 });
651 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
652 }
653
TEST_F(MacroCallReconstructorTest,InvalidCodeSplittingBracesAcrossArgs)654 TEST_F(MacroCallReconstructorTest, InvalidCodeSplittingBracesAcrossArgs) {
655 auto Macros = createExpander({"M(a, b)=(a) (b)"});
656 Expansion Exp(Lex, *Macros);
657 TokenList Call = Exp.expand("M", {std::string("{"), "x", ""});
658
659 MacroCallReconstructor Unexp(0, Exp.getUnexpanded());
660 Matcher E(Exp.getTokens(), Lex);
661 auto Prefix = tokens("({");
662 Unexp.addLine(line({
663 Prefix,
664 children({
665 line({
666 E.consume("({"),
667 children({line(E.consume(")(x)"))}),
668 }),
669 }),
670 }));
671 EXPECT_TRUE(Unexp.finished());
672 Matcher U(Call, Lex);
673 auto Expected = line({
674 Prefix,
675 children({line(U.consume("M({,x,)"))}),
676 });
677 EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(Expected));
678 }
679
680 } // namespace
681 } // namespace format
682 } // namespace clang
683