xref: /llvm-project/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp (revision c493d49cefeefa87532a2987a776b5433265e49f)
1 //===- BuildTreeTest.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file tests the syntax tree generation from the ClangAST.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "TreeTestBase.h"
14 
15 using namespace clang;
16 using namespace clang::syntax;
17 
18 namespace {
19 
20 class BuildSyntaxTreeTest : public SyntaxTreeTest {
21 protected:
22   ::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree) {
23     SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
24 
25     auto *Root = buildTree(Code, GetParam());
26     auto ErrorOK = errorOK(Code);
27     if (!ErrorOK)
28       return ErrorOK;
29     auto Actual = StringRef(Root->dump(*TM)).trim().str();
30     // EXPECT_EQ shows the diff between the two strings if they are different.
31     EXPECT_EQ(Tree.trim().str(), Actual);
32     if (Actual != Tree.trim().str()) {
33       return ::testing::AssertionFailure();
34     }
35     return ::testing::AssertionSuccess();
36   }
37 
38   ::testing::AssertionResult
39   treeDumpEqualOnAnnotations(StringRef CodeWithAnnotations,
40                              ArrayRef<StringRef> TreeDumps) {
41     SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
42 
43     auto AnnotatedCode = llvm::Annotations(CodeWithAnnotations);
44     auto *Root = buildTree(AnnotatedCode.code(), GetParam());
45 
46     auto ErrorOK = errorOK(AnnotatedCode.code());
47     if (!ErrorOK)
48       return ErrorOK;
49 
50     auto AnnotatedRanges = AnnotatedCode.ranges();
51     if (AnnotatedRanges.size() != TreeDumps.size()) {
52       return ::testing::AssertionFailure()
53              << "The number of annotated ranges in the source code is "
54                 "different "
55                 "to the number of their corresponding tree dumps.";
56     }
57     bool Failed = false;
58     for (unsigned i = 0; i < AnnotatedRanges.size(); i++) {
59       auto *AnnotatedNode = nodeByRange(AnnotatedRanges[i], Root);
60       assert(AnnotatedNode);
61       auto AnnotatedNodeDump =
62           StringRef(AnnotatedNode->dump(*TM))
63               .trim()
64               .str();
65       // EXPECT_EQ shows the diff between the two strings if they are different.
66       EXPECT_EQ(TreeDumps[i].trim().str(), AnnotatedNodeDump)
67           << "Dumps diverged for the code:\n"
68           << AnnotatedCode.code().slice(AnnotatedRanges[i].Begin,
69                                         AnnotatedRanges[i].End);
70       if (AnnotatedNodeDump != TreeDumps[i].trim().str())
71         Failed = true;
72     }
73     return Failed ? ::testing::AssertionFailure()
74                   : ::testing::AssertionSuccess();
75   }
76 
77 private:
78   ::testing::AssertionResult errorOK(StringRef RawCode) {
79     if (!RawCode.contains("error-ok")) {
80       if (Diags->getClient()->getNumErrors() != 0) {
81         return ::testing::AssertionFailure()
82                << "Source file has syntax errors (suppress with /*error-ok*/), "
83                   "they were printed to the "
84                   "test log";
85       }
86     }
87     return ::testing::AssertionSuccess();
88   }
89 };
90 
91 INSTANTIATE_TEST_SUITE_P(SyntaxTreeTests, BuildSyntaxTreeTest,
92                         testing::ValuesIn(allTestClangConfigs()) );
93 
94 TEST_P(BuildSyntaxTreeTest, Simple) {
95   EXPECT_TRUE(treeDumpEqual(
96       R"cpp(
97 int main() {}
98 void foo() {}
99 )cpp",
100       R"txt(
101 TranslationUnit Detached
102 |-SimpleDeclaration
103 | |-'int'
104 | |-DeclaratorList Declarators
105 | | `-SimpleDeclarator ListElement
106 | |   |-'main'
107 | |   `-ParametersAndQualifiers
108 | |     |-'(' OpenParen
109 | |     `-')' CloseParen
110 | `-CompoundStatement
111 |   |-'{' OpenParen
112 |   `-'}' CloseParen
113 `-SimpleDeclaration
114   |-'void'
115   |-DeclaratorList Declarators
116   | `-SimpleDeclarator ListElement
117   |   |-'foo'
118   |   `-ParametersAndQualifiers
119   |     |-'(' OpenParen
120   |     `-')' CloseParen
121   `-CompoundStatement
122     |-'{' OpenParen
123     `-'}' CloseParen
124 )txt"));
125 }
126 
127 TEST_P(BuildSyntaxTreeTest, SimpleVariable) {
128   EXPECT_TRUE(treeDumpEqual(
129       R"cpp(
130 int a;
131 int b = 42;
132 )cpp",
133       R"txt(
134 TranslationUnit Detached
135 |-SimpleDeclaration
136 | |-'int'
137 | |-DeclaratorList Declarators
138 | | `-SimpleDeclarator ListElement
139 | |   `-'a'
140 | `-';'
141 `-SimpleDeclaration
142   |-'int'
143   |-DeclaratorList Declarators
144   | `-SimpleDeclarator ListElement
145   |   |-'b'
146   |   |-'='
147   |   `-IntegerLiteralExpression
148   |     `-'42' LiteralToken
149   `-';'
150 )txt"));
151 }
152 
153 TEST_P(BuildSyntaxTreeTest, SimpleFunction) {
154   EXPECT_TRUE(treeDumpEqual(
155       R"cpp(
156 void foo(int a, int b) {}
157 )cpp",
158       R"txt(
159 TranslationUnit Detached
160 `-SimpleDeclaration
161   |-'void'
162   |-DeclaratorList Declarators
163   | `-SimpleDeclarator ListElement
164   |   |-'foo'
165   |   `-ParametersAndQualifiers
166   |     |-'(' OpenParen
167   |     |-ParameterDeclarationList Parameters
168   |     | |-SimpleDeclaration ListElement
169   |     | | |-'int'
170   |     | | `-DeclaratorList Declarators
171   |     | |   `-SimpleDeclarator ListElement
172   |     | |     `-'a'
173   |     | |-',' ListDelimiter
174   |     | `-SimpleDeclaration ListElement
175   |     |   |-'int'
176   |     |   `-DeclaratorList Declarators
177   |     |     `-SimpleDeclarator ListElement
178   |     |       `-'b'
179   |     `-')' CloseParen
180   `-CompoundStatement
181     |-'{' OpenParen
182     `-'}' CloseParen
183 )txt"));
184 }
185 
186 TEST_P(BuildSyntaxTreeTest, Simple_BackslashInsideToken) {
187   EXPECT_TRUE(treeDumpEqual(
188       R"cpp(
189 in\
190 t a;
191 )cpp",
192       R"txt(
193 TranslationUnit Detached
194 `-SimpleDeclaration
195   |-'in\
196 t'
197   |-DeclaratorList Declarators
198   | `-SimpleDeclarator ListElement
199   |   `-'a'
200   `-';'
201 )txt"));
202 }
203 
204 TEST_P(BuildSyntaxTreeTest, If) {
205   EXPECT_TRUE(treeDumpEqualOnAnnotations(
206       R"cpp(
207 void test() {
208   [[if (1) {}]]
209   [[if (1) {} else if (0) {}]]
210 }
211 )cpp",
212       {R"txt(
213 IfStatement Statement
214 |-'if' IntroducerKeyword
215 |-'('
216 |-ExpressionStatement Condition
217 | `-IntegerLiteralExpression Expression
218 |   `-'1' LiteralToken
219 |-')'
220 `-CompoundStatement ThenStatement
221   |-'{' OpenParen
222   `-'}' CloseParen
223   )txt",
224        R"txt(
225 IfStatement Statement
226 |-'if' IntroducerKeyword
227 |-'('
228 |-ExpressionStatement Condition
229 | `-IntegerLiteralExpression Expression
230 |   `-'1' LiteralToken
231 |-')'
232 |-CompoundStatement ThenStatement
233 | |-'{' OpenParen
234 | `-'}' CloseParen
235 |-'else' ElseKeyword
236 `-IfStatement ElseStatement
237   |-'if' IntroducerKeyword
238   |-'('
239   |-ExpressionStatement Condition
240   | `-IntegerLiteralExpression Expression
241   |   `-'0' LiteralToken
242   |-')'
243   `-CompoundStatement ThenStatement
244     |-'{' OpenParen
245     `-'}' CloseParen
246 )txt"}));
247 }
248 
249 TEST_P(BuildSyntaxTreeTest, IfDecl) {
250   if (!GetParam().isCXX17OrLater()) {
251     return;
252   }
253   EXPECT_TRUE(treeDumpEqualOnAnnotations(
254       R"cpp(
255 void test() {
256   [[if (int a = 5) {}]]
257   [[if (int a; a == 5) {}]]
258 }
259 )cpp",
260       {R"txt(
261 IfStatement Statement
262 |-'if' IntroducerKeyword
263 |-'('
264 |-DeclarationStatement Condition
265 | `-SimpleDeclaration
266 |   |-'int'
267 |   `-DeclaratorList Declarators
268 |     `-SimpleDeclarator ListElement
269 |       |-'a'
270 |       |-'='
271 |       `-IntegerLiteralExpression
272 |         `-'5' LiteralToken
273 |-')'
274 `-CompoundStatement ThenStatement
275   |-'{' OpenParen
276   `-'}' CloseParen
277       )txt",
278        R"txt(
279 IfStatement Statement
280 |-'if' IntroducerKeyword
281 |-'('
282 |-DeclarationStatement
283 | |-SimpleDeclaration
284 | | |-'int'
285 | | `-DeclaratorList Declarators
286 | |   `-SimpleDeclarator ListElement
287 | |     `-'a'
288 | `-';'
289 |-ExpressionStatement Condition
290 | `-BinaryOperatorExpression Expression
291 |   |-IdExpression LeftHandSide
292 |   | `-UnqualifiedId UnqualifiedId
293 |   |   `-'a'
294 |   |-'==' OperatorToken
295 |   `-IntegerLiteralExpression RightHandSide
296 |     `-'5' LiteralToken
297 |-')'
298 `-CompoundStatement ThenStatement
299   |-'{' OpenParen
300   `-'}' CloseParen
301 )txt"}));
302 }
303 
304 TEST_P(BuildSyntaxTreeTest, For) {
305   EXPECT_TRUE(treeDumpEqualOnAnnotations(
306       R"cpp(
307 void test() {
308   [[for (;;)  {}]]
309 }
310 )cpp",
311       {R"txt(
312 ForStatement Statement
313 |-'for' IntroducerKeyword
314 |-'('
315 |-';'
316 |-';'
317 |-')'
318 `-CompoundStatement BodyStatement
319   |-'{' OpenParen
320   `-'}' CloseParen
321 )txt"}));
322 }
323 
324 TEST_P(BuildSyntaxTreeTest, RangeBasedFor) {
325   if (!GetParam().isCXX11OrLater()) {
326     return;
327   }
328   EXPECT_TRUE(treeDumpEqualOnAnnotations(
329       R"cpp(
330 void test() {
331   int a[3];
332   [[for (int x : a)
333     ;]]
334 }
335 )cpp",
336       {R"txt(
337 RangeBasedForStatement Statement
338 |-'for' IntroducerKeyword
339 |-'('
340 |-SimpleDeclaration
341 | |-'int'
342 | |-DeclaratorList Declarators
343 | | `-SimpleDeclarator ListElement
344 | |   `-'x'
345 | `-':'
346 |-IdExpression
347 | `-UnqualifiedId UnqualifiedId
348 |   `-'a'
349 |-')'
350 `-EmptyStatement BodyStatement
351   `-';'
352 )txt"}));
353 }
354 
355 TEST_P(BuildSyntaxTreeTest, DeclarationStatement) {
356   EXPECT_TRUE(treeDumpEqualOnAnnotations(
357       R"cpp(
358 void test() {
359   [[int a = 10;]]
360 }
361 )cpp",
362       {R"txt(
363 DeclarationStatement Statement
364 |-SimpleDeclaration
365 | |-'int'
366 | `-DeclaratorList Declarators
367 |   `-SimpleDeclarator ListElement
368 |     |-'a'
369 |     |-'='
370 |     `-IntegerLiteralExpression
371 |       `-'10' LiteralToken
372 `-';'
373 )txt"}));
374 }
375 
376 TEST_P(BuildSyntaxTreeTest, Switch) {
377   EXPECT_TRUE(treeDumpEqualOnAnnotations(
378       R"cpp(
379 void test() {
380   [[switch (1) {
381     case 0:
382     default:;
383   }]]
384 }
385 )cpp",
386       {R"txt(
387 SwitchStatement Statement
388 |-'switch' IntroducerKeyword
389 |-'('
390 |-IntegerLiteralExpression
391 | `-'1' LiteralToken
392 |-')'
393 `-CompoundStatement BodyStatement
394   |-'{' OpenParen
395   |-CaseStatement Statement
396   | |-'case' IntroducerKeyword
397   | |-IntegerLiteralExpression CaseValue
398   | | `-'0' LiteralToken
399   | |-':'
400   | `-DefaultStatement BodyStatement
401   |   |-'default' IntroducerKeyword
402   |   |-':'
403   |   `-EmptyStatement BodyStatement
404   |     `-';'
405   `-'}' CloseParen
406 )txt"}));
407 }
408 
409 TEST_P(BuildSyntaxTreeTest, While) {
410   EXPECT_TRUE(treeDumpEqualOnAnnotations(
411       R"cpp(
412 void test() {
413   [[while (1) { continue; break; }]]
414 }
415 )cpp",
416       {R"txt(
417 WhileStatement Statement
418 |-'while' IntroducerKeyword
419 |-'('
420 |-IntegerLiteralExpression
421 | `-'1' LiteralToken
422 |-')'
423 `-CompoundStatement BodyStatement
424   |-'{' OpenParen
425   |-ContinueStatement Statement
426   | |-'continue' IntroducerKeyword
427   | `-';'
428   |-BreakStatement Statement
429   | |-'break' IntroducerKeyword
430   | `-';'
431   `-'}' CloseParen
432 )txt"}));
433 }
434 
435 TEST_P(BuildSyntaxTreeTest, UnhandledStatement) {
436   // Unhandled statements should end up as 'unknown statement'.
437   // This example uses a 'label statement', which does not yet have a syntax
438   // counterpart.
439   EXPECT_TRUE(treeDumpEqualOnAnnotations(
440       R"cpp(
441 int test() {
442   [[foo: return 100;]]
443 }
444 )cpp",
445       {R"txt(
446 UnknownStatement Statement
447 |-'foo'
448 |-':'
449 `-ReturnStatement
450   |-'return' IntroducerKeyword
451   |-IntegerLiteralExpression ReturnValue
452   | `-'100' LiteralToken
453   `-';'
454 )txt"}));
455 }
456 
457 TEST_P(BuildSyntaxTreeTest, Expressions) {
458   // expressions should be wrapped in 'ExpressionStatement' when they appear
459   // in a statement position.
460   EXPECT_TRUE(treeDumpEqual(
461       R"cpp(
462 void test() {
463   test();
464   if (1) test(); else test();
465 }
466 )cpp",
467       R"txt(
468 TranslationUnit Detached
469 `-SimpleDeclaration
470   |-'void'
471   |-DeclaratorList Declarators
472   | `-SimpleDeclarator ListElement
473   |   |-'test'
474   |   `-ParametersAndQualifiers
475   |     |-'(' OpenParen
476   |     `-')' CloseParen
477   `-CompoundStatement
478     |-'{' OpenParen
479     |-ExpressionStatement Statement
480     | |-CallExpression Expression
481     | | |-IdExpression Callee
482     | | | `-UnqualifiedId UnqualifiedId
483     | | |   `-'test'
484     | | |-'(' OpenParen
485     | | `-')' CloseParen
486     | `-';'
487     |-IfStatement Statement
488     | |-'if' IntroducerKeyword
489     | |-'('
490     | |-ExpressionStatement Condition
491     | | `-IntegerLiteralExpression Expression
492     | |   `-'1' LiteralToken
493     | |-')'
494     | |-ExpressionStatement ThenStatement
495     | | |-CallExpression Expression
496     | | | |-IdExpression Callee
497     | | | | `-UnqualifiedId UnqualifiedId
498     | | | |   `-'test'
499     | | | |-'(' OpenParen
500     | | | `-')' CloseParen
501     | | `-';'
502     | |-'else' ElseKeyword
503     | `-ExpressionStatement ElseStatement
504     |   |-CallExpression Expression
505     |   | |-IdExpression Callee
506     |   | | `-UnqualifiedId UnqualifiedId
507     |   | |   `-'test'
508     |   | |-'(' OpenParen
509     |   | `-')' CloseParen
510     |   `-';'
511     `-'}' CloseParen
512 )txt"));
513 }
514 
515 TEST_P(BuildSyntaxTreeTest, ConditionalOperator) {
516   // FIXME: conditional expression is not modeled yet.
517   EXPECT_TRUE(treeDumpEqualOnAnnotations(
518       R"cpp(
519 void test() {
520   [[1?:2]];
521 }
522 )cpp",
523       {R"txt(
524 UnknownExpression Expression
525 |-IntegerLiteralExpression
526 | `-'1' LiteralToken
527 |-'?'
528 |-':'
529 `-IntegerLiteralExpression
530   `-'2' LiteralToken
531 )txt"}));
532 }
533 
534 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_Identifier) {
535   EXPECT_TRUE(treeDumpEqualOnAnnotations(
536       R"cpp(
537 void test(int a) {
538   [[a]];
539 }
540 )cpp",
541       {R"txt(
542 IdExpression Expression
543 `-UnqualifiedId UnqualifiedId
544   `-'a'
545 )txt"}));
546 }
547 
548 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_OperatorFunctionId) {
549   if (!GetParam().isCXX()) {
550     return;
551   }
552   EXPECT_TRUE(treeDumpEqualOnAnnotations(
553       R"cpp(
554 struct X {
555   friend X operator+(const X&, const X&);
556 };
557 void test(X x) {
558   [[operator+(x, x)]];
559 }
560 )cpp",
561       {R"txt(
562 CallExpression Expression
563 |-IdExpression Callee
564 | `-UnqualifiedId UnqualifiedId
565 |   |-'operator'
566 |   `-'+'
567 |-'(' OpenParen
568 |-CallArguments Arguments
569 | |-IdExpression ListElement
570 | | `-UnqualifiedId UnqualifiedId
571 | |   `-'x'
572 | |-',' ListDelimiter
573 | `-IdExpression ListElement
574 |   `-UnqualifiedId UnqualifiedId
575 |     `-'x'
576 `-')' CloseParen
577 )txt"}));
578 }
579 
580 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_ConversionFunctionId) {
581   if (!GetParam().isCXX()) {
582     return;
583   }
584   EXPECT_TRUE(treeDumpEqualOnAnnotations(
585       R"cpp(
586 struct X {
587   operator int();
588 };
589 void test(X x) {
590   [[x.operator int()]];
591 }
592 )cpp",
593       {R"txt(
594 CallExpression Expression
595 |-MemberExpression Callee
596 | |-IdExpression Object
597 | | `-UnqualifiedId UnqualifiedId
598 | |   `-'x'
599 | |-'.' AccessToken
600 | `-IdExpression Member
601 |   `-UnqualifiedId UnqualifiedId
602 |     |-'operator'
603 |     `-'int'
604 |-'(' OpenParen
605 `-')' CloseParen
606 )txt"}));
607 }
608 
609 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_LiteralOperatorId) {
610   if (!GetParam().isCXX11OrLater()) {
611     return;
612   }
613   EXPECT_TRUE(treeDumpEqualOnAnnotations(
614       R"cpp(
615 unsigned operator "" _w(char);
616 void test() {
617   [[operator "" _w('1')]];
618 }
619 )cpp",
620       {R"txt(
621 CallExpression Expression
622 |-IdExpression Callee
623 | `-UnqualifiedId UnqualifiedId
624 |   |-'operator'
625 |   |-'""'
626 |   `-'_w'
627 |-'(' OpenParen
628 |-CallArguments Arguments
629 | `-CharacterLiteralExpression ListElement
630 |   `-''1'' LiteralToken
631 `-')' CloseParen
632 )txt"}));
633 }
634 
635 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_Destructor) {
636   if (!GetParam().isCXX()) {
637     return;
638   }
639   EXPECT_TRUE(treeDumpEqualOnAnnotations(
640       R"cpp(
641 struct X { };
642 void test(X x) {
643   [[x.~X()]];
644 }
645 )cpp",
646       {R"txt(
647 CallExpression Expression
648 |-MemberExpression Callee
649 | |-IdExpression Object
650 | | `-UnqualifiedId UnqualifiedId
651 | |   `-'x'
652 | |-'.' AccessToken
653 | `-IdExpression Member
654 |   `-UnqualifiedId UnqualifiedId
655 |     |-'~'
656 |     `-'X'
657 |-'(' OpenParen
658 `-')' CloseParen
659 )txt"}));
660 }
661 
662 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_DecltypeDestructor) {
663   if (!GetParam().isCXX11OrLater()) {
664     return;
665   }
666   EXPECT_TRUE(treeDumpEqualOnAnnotations(
667       R"cpp(
668 struct X { };
669 void test(X x) {
670   // FIXME: Make `decltype(x)` a child of `MemberExpression`. It is currently
671   // not because `Expr::getSourceRange()` returns the range of `x.~` for the
672   // `MemberExpr` instead of the expected `x.~decltype(x)`, this is a bug in
673   // clang.
674   [[x.~decltype(x)()]];
675 }
676 )cpp",
677       {R"txt(
678 CallExpression Expression
679 |-MemberExpression Callee
680 | |-IdExpression Object
681 | | `-UnqualifiedId UnqualifiedId
682 | |   `-'x'
683 | |-'.' AccessToken
684 | `-IdExpression Member
685 |   `-UnqualifiedId UnqualifiedId
686 |     `-'~'
687 |-'decltype'
688 |-'('
689 |-'x'
690 |-')'
691 |-'('
692 `-')' CloseParen
693 )txt"}));
694 }
695 
696 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_TemplateId) {
697   if (!GetParam().isCXX()) {
698     return;
699   }
700   EXPECT_TRUE(treeDumpEqualOnAnnotations(
701       R"cpp(
702 template<typename T>
703 T f();
704 void test() {
705   [[f<int>()]];
706 }
707 )cpp",
708       {R"txt(
709 CallExpression Expression
710 |-IdExpression Callee
711 | `-UnqualifiedId UnqualifiedId
712 |   |-'f'
713 |   |-'<'
714 |   |-'int'
715 |   `-'>'
716 |-'(' OpenParen
717 `-')' CloseParen
718 )txt"}));
719 }
720 
721 TEST_P(BuildSyntaxTreeTest, QualifiedId_NamespaceSpecifier) {
722   if (!GetParam().isCXX()) {
723     return;
724   }
725   EXPECT_TRUE(treeDumpEqualOnAnnotations(
726       R"cpp(
727 namespace n {
728   struct S { };
729 }
730 void test() {
731   [[::n::S s1]];
732   [[n::S s2]];
733 }
734 )cpp",
735       {R"txt(
736 SimpleDeclaration
737 |-NestedNameSpecifier
738 | |-'::' ListDelimiter
739 | |-IdentifierNameSpecifier ListElement
740 | | `-'n'
741 | `-'::' ListDelimiter
742 |-'S'
743 `-DeclaratorList Declarators
744   `-SimpleDeclarator ListElement
745     `-'s1'
746 )txt",
747        R"txt(
748 SimpleDeclaration
749 |-NestedNameSpecifier
750 | |-IdentifierNameSpecifier ListElement
751 | | `-'n'
752 | `-'::' ListDelimiter
753 |-'S'
754 `-DeclaratorList Declarators
755   `-SimpleDeclarator ListElement
756     `-'s2'
757 )txt"}));
758 }
759 
760 TEST_P(BuildSyntaxTreeTest, QualifiedId_TemplateSpecifier) {
761   if (!GetParam().isCXX()) {
762     return;
763   }
764   EXPECT_TRUE(treeDumpEqualOnAnnotations(
765       R"cpp(
766 template<typename T>
767 struct ST {
768   struct S { };
769 };
770 void test() {
771   [[::template ST<int>::S s1]];
772   [[::ST<int>::S s2]];
773 }
774 )cpp",
775       {R"txt(
776 SimpleDeclaration
777 |-NestedNameSpecifier
778 | |-'::' ListDelimiter
779 | |-SimpleTemplateNameSpecifier ListElement
780 | | |-'template'
781 | | |-'ST'
782 | | |-'<'
783 | | |-'int'
784 | | `-'>'
785 | `-'::' ListDelimiter
786 |-'S'
787 `-DeclaratorList Declarators
788   `-SimpleDeclarator ListElement
789     `-'s1'
790 )txt",
791        R"txt(
792 SimpleDeclaration
793 |-NestedNameSpecifier
794 | |-'::' ListDelimiter
795 | |-SimpleTemplateNameSpecifier ListElement
796 | | |-'ST'
797 | | |-'<'
798 | | |-'int'
799 | | `-'>'
800 | `-'::' ListDelimiter
801 |-'S'
802 `-DeclaratorList Declarators
803   `-SimpleDeclarator ListElement
804     `-'s2'
805 )txt"}));
806 }
807 
808 TEST_P(BuildSyntaxTreeTest, QualifiedId_DecltypeSpecifier) {
809   if (!GetParam().isCXX11OrLater()) {
810     return;
811   }
812   EXPECT_TRUE(treeDumpEqualOnAnnotations(
813       R"cpp(
814 struct S {
815   static void f(){}
816 };
817 void test(S s) {
818   [[decltype(s)::f()]];
819 }
820 )cpp",
821       {R"txt(
822 CallExpression Expression
823 |-IdExpression Callee
824 | |-NestedNameSpecifier Qualifier
825 | | |-DecltypeNameSpecifier ListElement
826 | | | |-'decltype'
827 | | | |-'('
828 | | | |-IdExpression
829 | | | | `-UnqualifiedId UnqualifiedId
830 | | | |   `-'s'
831 | | | `-')'
832 | | `-'::' ListDelimiter
833 | `-UnqualifiedId UnqualifiedId
834 |   `-'f'
835 |-'(' OpenParen
836 `-')' CloseParen
837 )txt"}));
838 }
839 
840 TEST_P(BuildSyntaxTreeTest, QualifiedId_OptionalTemplateKw) {
841   if (!GetParam().isCXX()) {
842     return;
843   }
844   EXPECT_TRUE(treeDumpEqualOnAnnotations(
845       R"cpp(
846 struct S {
847   template<typename U>
848   static U f();
849 };
850 void test() {
851   [[S::f<int>()]];
852   [[S::template f<int>()]];
853 }
854 )cpp",
855       {R"txt(
856 CallExpression Expression
857 |-IdExpression Callee
858 | |-NestedNameSpecifier Qualifier
859 | | |-IdentifierNameSpecifier ListElement
860 | | | `-'S'
861 | | `-'::' ListDelimiter
862 | `-UnqualifiedId UnqualifiedId
863 |   |-'f'
864 |   |-'<'
865 |   |-'int'
866 |   `-'>'
867 |-'(' OpenParen
868 `-')' CloseParen
869 )txt",
870        R"txt(
871 CallExpression Expression
872 |-IdExpression Callee
873 | |-NestedNameSpecifier Qualifier
874 | | |-IdentifierNameSpecifier ListElement
875 | | | `-'S'
876 | | `-'::' ListDelimiter
877 | |-'template' TemplateKeyword
878 | `-UnqualifiedId UnqualifiedId
879 |   |-'f'
880 |   |-'<'
881 |   |-'int'
882 |   `-'>'
883 |-'(' OpenParen
884 `-')' CloseParen
885 )txt"}));
886 }
887 
888 TEST_P(BuildSyntaxTreeTest, QualifiedId_Complex) {
889   if (!GetParam().isCXX()) {
890     return;
891   }
892   EXPECT_TRUE(treeDumpEqualOnAnnotations(
893       R"cpp(
894 namespace n {
895   template<typename T>
896   struct ST {
897     template<typename U>
898     static U f();
899   };
900 }
901 void test() {
902   [[::n::template ST<int>::template f<int>()]];
903 }
904 )cpp",
905       {R"txt(
906 CallExpression Expression
907 |-IdExpression Callee
908 | |-NestedNameSpecifier Qualifier
909 | | |-'::' ListDelimiter
910 | | |-IdentifierNameSpecifier ListElement
911 | | | `-'n'
912 | | |-'::' ListDelimiter
913 | | |-SimpleTemplateNameSpecifier ListElement
914 | | | |-'template'
915 | | | |-'ST'
916 | | | |-'<'
917 | | | |-'int'
918 | | | `-'>'
919 | | `-'::' ListDelimiter
920 | |-'template' TemplateKeyword
921 | `-UnqualifiedId UnqualifiedId
922 |   |-'f'
923 |   |-'<'
924 |   |-'int'
925 |   `-'>'
926 |-'(' OpenParen
927 `-')' CloseParen
928 )txt"}));
929 }
930 
931 TEST_P(BuildSyntaxTreeTest, QualifiedId_DependentType) {
932   if (!GetParam().isCXX()) {
933     return;
934   }
935   if (GetParam().hasDelayedTemplateParsing()) {
936     // FIXME: Make this test work on Windows by generating the expected syntax
937     // tree when `-fdelayed-template-parsing` is active.
938     return;
939   }
940   EXPECT_TRUE(treeDumpEqualOnAnnotations(
941       R"cpp(
942 template <typename T>
943 void test() {
944   [[T::template U<int>::f()]];
945   [[T::U::f()]];
946   [[T::template f<0>()]];
947 }
948 )cpp",
949       {R"txt(
950 CallExpression Expression
951 |-IdExpression Callee
952 | |-NestedNameSpecifier Qualifier
953 | | |-IdentifierNameSpecifier ListElement
954 | | | `-'T'
955 | | |-'::' ListDelimiter
956 | | |-SimpleTemplateNameSpecifier ListElement
957 | | | |-'template'
958 | | | |-'U'
959 | | | |-'<'
960 | | | |-'int'
961 | | | `-'>'
962 | | `-'::' ListDelimiter
963 | `-UnqualifiedId UnqualifiedId
964 |   `-'f'
965 |-'(' OpenParen
966 `-')' CloseParen
967 )txt",
968        R"txt(
969 CallExpression Expression
970 |-IdExpression Callee
971 | |-NestedNameSpecifier Qualifier
972 | | |-IdentifierNameSpecifier ListElement
973 | | | `-'T'
974 | | |-'::' ListDelimiter
975 | | |-IdentifierNameSpecifier ListElement
976 | | | `-'U'
977 | | `-'::' ListDelimiter
978 | `-UnqualifiedId UnqualifiedId
979 |   `-'f'
980 |-'(' OpenParen
981 `-')' CloseParen
982 )txt",
983        R"txt(
984 CallExpression Expression
985 |-IdExpression Callee
986 | |-NestedNameSpecifier Qualifier
987 | | |-IdentifierNameSpecifier ListElement
988 | | | `-'T'
989 | | `-'::' ListDelimiter
990 | |-'template' TemplateKeyword
991 | `-UnqualifiedId UnqualifiedId
992 |   |-'f'
993 |   |-'<'
994 |   |-IntegerLiteralExpression
995 |   | `-'0' LiteralToken
996 |   `-'>'
997 |-'(' OpenParen
998 `-')' CloseParen
999 )txt"}));
1000 }
1001 
1002 TEST_P(BuildSyntaxTreeTest, This_Simple) {
1003   if (!GetParam().isCXX()) {
1004     return;
1005   }
1006   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1007       R"cpp(
1008 struct S {
1009   S* test(){
1010     return [[this]];
1011   }
1012 };
1013 )cpp",
1014       {R"txt(
1015 ThisExpression ReturnValue
1016 `-'this' IntroducerKeyword
1017 )txt"}));
1018 }
1019 
1020 TEST_P(BuildSyntaxTreeTest, This_ExplicitMemberAccess) {
1021   if (!GetParam().isCXX()) {
1022     return;
1023   }
1024   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1025       R"cpp(
1026 struct S {
1027   int a;
1028   void test(){
1029     [[this->a]];
1030   }
1031 };
1032 )cpp",
1033       {R"txt(
1034 MemberExpression Expression
1035 |-ThisExpression Object
1036 | `-'this' IntroducerKeyword
1037 |-'->' AccessToken
1038 `-IdExpression Member
1039   `-UnqualifiedId UnqualifiedId
1040     `-'a'
1041 )txt"}));
1042 }
1043 
1044 TEST_P(BuildSyntaxTreeTest, This_ImplicitMemberAccess) {
1045   if (!GetParam().isCXX()) {
1046     return;
1047   }
1048   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1049       R"cpp(
1050 struct S {
1051   int a;
1052   void test(){
1053     [[a]];
1054   }
1055 };
1056 )cpp",
1057       {R"txt(
1058 IdExpression Expression
1059 `-UnqualifiedId UnqualifiedId
1060   `-'a'
1061 )txt"}));
1062 }
1063 
1064 TEST_P(BuildSyntaxTreeTest, ParenExpr) {
1065   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1066       R"cpp(
1067 void test() {
1068   [[(1)]];
1069   [[((1))]];
1070   [[(1 + (2))]];
1071 }
1072 )cpp",
1073       {R"txt(
1074 ParenExpression Expression
1075 |-'(' OpenParen
1076 |-IntegerLiteralExpression SubExpression
1077 | `-'1' LiteralToken
1078 `-')' CloseParen
1079 )txt",
1080        R"txt(
1081 ParenExpression Expression
1082 |-'(' OpenParen
1083 |-ParenExpression SubExpression
1084 | |-'(' OpenParen
1085 | |-IntegerLiteralExpression SubExpression
1086 | | `-'1' LiteralToken
1087 | `-')' CloseParen
1088 `-')' CloseParen
1089 )txt",
1090        R"txt(
1091 ParenExpression Expression
1092 |-'(' OpenParen
1093 |-BinaryOperatorExpression SubExpression
1094 | |-IntegerLiteralExpression LeftHandSide
1095 | | `-'1' LiteralToken
1096 | |-'+' OperatorToken
1097 | `-ParenExpression RightHandSide
1098 |   |-'(' OpenParen
1099 |   |-IntegerLiteralExpression SubExpression
1100 |   | `-'2' LiteralToken
1101 |   `-')' CloseParen
1102 `-')' CloseParen
1103 )txt"}));
1104 }
1105 
1106 TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Char) {
1107   if (!GetParam().isCXX11OrLater()) {
1108     return;
1109   }
1110   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1111       R"cpp(
1112 unsigned operator "" _c(char);
1113 void test() {
1114   [['2'_c]];
1115 }
1116     )cpp",
1117       {R"txt(
1118 CharUserDefinedLiteralExpression Expression
1119 `-''2'_c' LiteralToken
1120 )txt"}));
1121 }
1122 
1123 TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_String) {
1124   if (!GetParam().isCXX11OrLater()) {
1125     return;
1126   }
1127   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1128       R"cpp(
1129 typedef decltype(sizeof(void *)) size_t;
1130 
1131 unsigned operator "" _s(const char*, size_t);
1132 
1133 void test() {
1134   [["12"_s]];
1135 }
1136     )cpp",
1137       {R"txt(
1138 StringUserDefinedLiteralExpression Expression
1139 `-'"12"_s' LiteralToken
1140 )txt"}));
1141 }
1142 
1143 TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Integer) {
1144   if (!GetParam().isCXX11OrLater()) {
1145     return;
1146   }
1147   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1148       R"cpp(
1149 unsigned operator "" _i(unsigned long long);
1150 unsigned operator "" _r(const char*);
1151 template <char...>
1152 unsigned operator "" _t();
1153 
1154 void test() {
1155   [[12_i]];
1156   [[12_r]];
1157   [[12_t]];
1158 }
1159     )cpp",
1160       {R"txt(
1161 IntegerUserDefinedLiteralExpression Expression
1162 `-'12_i' LiteralToken
1163 )txt",
1164        R"txt(
1165 IntegerUserDefinedLiteralExpression Expression
1166 `-'12_r' LiteralToken
1167 )txt",
1168        R"txt(
1169 IntegerUserDefinedLiteralExpression Expression
1170 `-'12_t' LiteralToken
1171 )txt"}));
1172 }
1173 
1174 TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Float) {
1175   if (!GetParam().isCXX11OrLater()) {
1176     return;
1177   }
1178   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1179       R"cpp(
1180 unsigned operator "" _f(long double);
1181 unsigned operator "" _r(const char*);
1182 template <char...>
1183 unsigned operator "" _t();
1184 
1185 void test() {
1186   [[1.2_f]];
1187   [[1.2_r]];
1188   [[1.2_t]];
1189 }
1190     )cpp",
1191       {R"txt(
1192 FloatUserDefinedLiteralExpression Expression
1193 `-'1.2_f' LiteralToken
1194 )txt",
1195        R"txt(
1196 FloatUserDefinedLiteralExpression Expression
1197 `-'1.2_r' LiteralToken
1198 )txt",
1199        R"txt(
1200 FloatUserDefinedLiteralExpression Expression
1201 `-'1.2_t' LiteralToken
1202 )txt"}));
1203 }
1204 
1205 TEST_P(BuildSyntaxTreeTest, IntegerLiteral_LongLong) {
1206   if (!GetParam().isCXX11OrLater()) {
1207     return;
1208   }
1209   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1210       R"cpp(
1211 void test() {
1212   [[12ll]];
1213   [[12ull]];
1214 }
1215 )cpp",
1216       {R"txt(
1217 IntegerLiteralExpression Expression
1218 `-'12ll' LiteralToken
1219 )txt",
1220        R"txt(
1221 IntegerLiteralExpression Expression
1222 `-'12ull' LiteralToken
1223 )txt"}));
1224 }
1225 
1226 TEST_P(BuildSyntaxTreeTest, IntegerLiteral_Binary) {
1227   if (!GetParam().isCXX14OrLater()) {
1228     return;
1229   }
1230   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1231       R"cpp(
1232 void test() {
1233   [[0b1100]];
1234 }
1235 )cpp",
1236       {R"txt(
1237 IntegerLiteralExpression Expression
1238 `-'0b1100' LiteralToken
1239 )txt"}));
1240 }
1241 
1242 TEST_P(BuildSyntaxTreeTest, IntegerLiteral_WithDigitSeparators) {
1243   if (!GetParam().isCXX14OrLater()) {
1244     return;
1245   }
1246   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1247       R"cpp(
1248 void test() {
1249   [[1'2'0ull]];
1250 }
1251 )cpp",
1252       {R"txt(
1253 IntegerLiteralExpression Expression
1254 `-'1'2'0ull' LiteralToken
1255 )txt"}));
1256 }
1257 
1258 TEST_P(BuildSyntaxTreeTest, CharacterLiteral) {
1259   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1260       R"cpp(
1261 void test() {
1262   [['a']];
1263   [['\n']];
1264   [['\x20']];
1265   [['\0']];
1266   [[L'a']];
1267   [[L'α']];
1268 }
1269 )cpp",
1270       {R"txt(
1271 CharacterLiteralExpression Expression
1272 `-''a'' LiteralToken
1273 )txt",
1274        R"txt(
1275 CharacterLiteralExpression Expression
1276 `-''\n'' LiteralToken
1277 )txt",
1278        R"txt(
1279 CharacterLiteralExpression Expression
1280 `-''\x20'' LiteralToken
1281 )txt",
1282        R"txt(
1283 CharacterLiteralExpression Expression
1284 `-''\0'' LiteralToken
1285 )txt",
1286        R"txt(
1287 CharacterLiteralExpression Expression
1288 `-'L'a'' LiteralToken
1289 )txt",
1290        R"txt(
1291 CharacterLiteralExpression Expression
1292 `-'L'α'' LiteralToken
1293 )txt"}));
1294 }
1295 
1296 TEST_P(BuildSyntaxTreeTest, CharacterLiteral_Utf) {
1297   if (!GetParam().isCXX11OrLater()) {
1298     return;
1299   }
1300   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1301       R"cpp(
1302 void test() {
1303   [[u'a']];
1304   [[u'構']];
1305   [[U'a']];
1306   [[U'��']];
1307 }
1308 )cpp",
1309       {R"txt(
1310 CharacterLiteralExpression Expression
1311 `-'u'a'' LiteralToken
1312 )txt",
1313        R"txt(
1314 CharacterLiteralExpression Expression
1315 `-'u'構'' LiteralToken
1316 )txt",
1317        R"txt(
1318 CharacterLiteralExpression Expression
1319 `-'U'a'' LiteralToken
1320 )txt",
1321        R"txt(
1322 CharacterLiteralExpression Expression
1323 `-'U'��'' LiteralToken
1324 )txt"}));
1325 }
1326 
1327 TEST_P(BuildSyntaxTreeTest, CharacterLiteral_Utf8) {
1328   if (!GetParam().isCXX17OrLater()) {
1329     return;
1330   }
1331   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1332       R"cpp(
1333 void test() {
1334   [[u8'a']];
1335   [[u8'\x7f']];
1336 }
1337 )cpp",
1338       {R"txt(
1339 CharacterLiteralExpression Expression
1340 `-'u8'a'' LiteralToken
1341 )txt",
1342        R"txt(
1343 CharacterLiteralExpression Expression
1344 `-'u8'\x7f'' LiteralToken
1345 )txt"}));
1346 }
1347 
1348 TEST_P(BuildSyntaxTreeTest, FloatingLiteral) {
1349   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1350       R"cpp(
1351 void test() {
1352   [[1e-2]];
1353   [[2.]];
1354   [[.2]];
1355   [[2.f]];
1356 }
1357 )cpp",
1358       {R"txt(
1359 FloatingLiteralExpression Expression
1360 `-'1e-2' LiteralToken
1361 )txt",
1362        R"txt(
1363 FloatingLiteralExpression Expression
1364 `-'2.' LiteralToken
1365 )txt",
1366        R"txt(
1367 FloatingLiteralExpression Expression
1368 `-'.2' LiteralToken
1369 )txt",
1370        R"txt(
1371 FloatingLiteralExpression Expression
1372 `-'2.f' LiteralToken
1373 )txt"}));
1374 }
1375 
1376 TEST_P(BuildSyntaxTreeTest, FloatingLiteral_Hexadecimal) {
1377   if (!GetParam().isCXX17OrLater()) {
1378     return;
1379   }
1380   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1381       R"cpp(
1382 void test() {
1383   [[0xfp1]];
1384   [[0xf.p1]];
1385   [[0x.fp1]];
1386   [[0xf.fp1f]];
1387 }
1388 )cpp",
1389       {R"txt(
1390 FloatingLiteralExpression Expression
1391 `-'0xfp1' LiteralToken
1392 )txt",
1393        R"txt(
1394 FloatingLiteralExpression Expression
1395 `-'0xf.p1' LiteralToken
1396 )txt",
1397        R"txt(
1398 FloatingLiteralExpression Expression
1399 `-'0x.fp1' LiteralToken
1400 )txt",
1401        R"txt(
1402 FloatingLiteralExpression Expression
1403 `-'0xf.fp1f' LiteralToken
1404 )txt"}));
1405 }
1406 
1407 TEST_P(BuildSyntaxTreeTest, StringLiteral) {
1408   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1409       R"cpp(
1410 void test() {
1411   [["a\n\0\x20"]];
1412   [[L"αβ"]];
1413 }
1414 )cpp",
1415       {R"txt(
1416 StringLiteralExpression Expression
1417 `-'"a\n\0\x20"' LiteralToken
1418 )txt",
1419        R"txt(
1420 StringLiteralExpression Expression
1421 `-'L"αβ"' LiteralToken
1422 )txt"}));
1423 }
1424 
1425 TEST_P(BuildSyntaxTreeTest, StringLiteral_Utf) {
1426   if (!GetParam().isCXX11OrLater()) {
1427     return;
1428   }
1429   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1430       R"cpp(
1431 void test() {
1432   [[u8"a\x1f\x05"]];
1433   [[u"C++抽象構文木"]];
1434   [[U"����\n"]];
1435 }
1436 )cpp",
1437       {R"txt(
1438 StringLiteralExpression Expression
1439 `-'u8"a\x1f\x05"' LiteralToken
1440 )txt",
1441        R"txt(
1442 StringLiteralExpression Expression
1443 `-'u"C++抽象構文木"' LiteralToken
1444 )txt",
1445        R"txt(
1446 StringLiteralExpression Expression
1447 `-'U"����\n"' LiteralToken
1448 )txt"}));
1449 }
1450 
1451 TEST_P(BuildSyntaxTreeTest, StringLiteral_Raw) {
1452   if (!GetParam().isCXX11OrLater()) {
1453     return;
1454   }
1455   // This test uses regular string literals instead of raw string literals to
1456   // hold source code and expected output because of a bug in MSVC up to MSVC
1457   // 2019 16.2:
1458   // https://developercommunity.visualstudio.com/content/problem/67300/stringifying-raw-string-literal.html
1459   EXPECT_TRUE(treeDumpEqual( //
1460       "void test() {\n"
1461       "  R\"SyntaxTree(\n"
1462       "  Hello \"Syntax\" \\\"\n"
1463       "  )SyntaxTree\";\n"
1464       "}\n",
1465       "TranslationUnit Detached\n"
1466       "`-SimpleDeclaration\n"
1467       "  |-'void'\n"
1468       "  |-DeclaratorList Declarators\n"
1469       "  | `-SimpleDeclarator ListElement\n"
1470       "  |   |-'test'\n"
1471       "  |   `-ParametersAndQualifiers\n"
1472       "  |     |-'(' OpenParen\n"
1473       "  |     `-')' CloseParen\n"
1474       "  `-CompoundStatement\n"
1475       "    |-'{' OpenParen\n"
1476       "    |-ExpressionStatement Statement\n"
1477       "    | |-StringLiteralExpression Expression\n"
1478       "    | | `-'R\"SyntaxTree(\n"
1479       "  Hello \"Syntax\" \\\"\n"
1480       "  )SyntaxTree\"' LiteralToken\n"
1481       "    | `-';'\n"
1482       "    `-'}' CloseParen\n"));
1483 }
1484 
1485 TEST_P(BuildSyntaxTreeTest, BoolLiteral) {
1486   if (GetParam().isC()) {
1487     return;
1488   }
1489   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1490       R"cpp(
1491 void test() {
1492   [[true]];
1493   [[false]];
1494 }
1495 )cpp",
1496       {R"txt(
1497 BoolLiteralExpression Expression
1498 `-'true' LiteralToken
1499 )txt",
1500        R"txt(
1501 BoolLiteralExpression Expression
1502 `-'false' LiteralToken
1503 )txt"}));
1504 }
1505 
1506 TEST_P(BuildSyntaxTreeTest, CxxNullPtrLiteral) {
1507   if (!GetParam().isCXX11OrLater()) {
1508     return;
1509   }
1510   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1511       R"cpp(
1512 void test() {
1513   [[nullptr]];
1514 }
1515 )cpp",
1516       {R"txt(
1517 CxxNullPtrExpression Expression
1518 `-'nullptr' LiteralToken
1519 )txt"}));
1520 }
1521 
1522 TEST_P(BuildSyntaxTreeTest, PostfixUnaryOperator) {
1523   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1524       R"cpp(
1525 void test(int a) {
1526   [[a++]];
1527   [[a--]];
1528 }
1529 )cpp",
1530       {R"txt(
1531 PostfixUnaryOperatorExpression Expression
1532 |-IdExpression Operand
1533 | `-UnqualifiedId UnqualifiedId
1534 |   `-'a'
1535 `-'++' OperatorToken
1536 )txt",
1537        R"txt(
1538 PostfixUnaryOperatorExpression Expression
1539 |-IdExpression Operand
1540 | `-UnqualifiedId UnqualifiedId
1541 |   `-'a'
1542 `-'--' OperatorToken
1543 )txt"}));
1544 }
1545 
1546 TEST_P(BuildSyntaxTreeTest, PrefixUnaryOperator) {
1547   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1548       R"cpp(
1549 void test(int a, int *ap) {
1550   [[--a]]; [[++a]];
1551   [[~a]];
1552   [[-a]];
1553   [[+a]];
1554   [[&a]];
1555   [[*ap]];
1556   [[!a]];
1557   [[__real a]]; [[__imag a]];
1558 }
1559 )cpp",
1560       {R"txt(
1561 PrefixUnaryOperatorExpression Expression
1562 |-'--' OperatorToken
1563 `-IdExpression Operand
1564   `-UnqualifiedId UnqualifiedId
1565     `-'a'
1566 )txt",
1567        R"txt(
1568 PrefixUnaryOperatorExpression Expression
1569 |-'++' OperatorToken
1570 `-IdExpression Operand
1571   `-UnqualifiedId UnqualifiedId
1572     `-'a'
1573 )txt",
1574        R"txt(
1575 PrefixUnaryOperatorExpression Expression
1576 |-'~' OperatorToken
1577 `-IdExpression Operand
1578   `-UnqualifiedId UnqualifiedId
1579     `-'a'
1580 )txt",
1581        R"txt(
1582 PrefixUnaryOperatorExpression Expression
1583 |-'-' OperatorToken
1584 `-IdExpression Operand
1585   `-UnqualifiedId UnqualifiedId
1586     `-'a'
1587 )txt",
1588        R"txt(
1589 PrefixUnaryOperatorExpression Expression
1590 |-'+' OperatorToken
1591 `-IdExpression Operand
1592   `-UnqualifiedId UnqualifiedId
1593     `-'a'
1594 )txt",
1595        R"txt(
1596 PrefixUnaryOperatorExpression Expression
1597 |-'&' OperatorToken
1598 `-IdExpression Operand
1599   `-UnqualifiedId UnqualifiedId
1600     `-'a'
1601 )txt",
1602        R"txt(
1603 PrefixUnaryOperatorExpression Expression
1604 |-'*' OperatorToken
1605 `-IdExpression Operand
1606   `-UnqualifiedId UnqualifiedId
1607     `-'ap'
1608 )txt",
1609        R"txt(
1610 PrefixUnaryOperatorExpression Expression
1611 |-'!' OperatorToken
1612 `-IdExpression Operand
1613   `-UnqualifiedId UnqualifiedId
1614     `-'a'
1615 )txt",
1616        R"txt(
1617 PrefixUnaryOperatorExpression Expression
1618 |-'__real' OperatorToken
1619 `-IdExpression Operand
1620   `-UnqualifiedId UnqualifiedId
1621     `-'a'
1622 )txt",
1623        R"txt(
1624 PrefixUnaryOperatorExpression Expression
1625 |-'__imag' OperatorToken
1626 `-IdExpression Operand
1627   `-UnqualifiedId UnqualifiedId
1628     `-'a'
1629 )txt"}));
1630 }
1631 
1632 TEST_P(BuildSyntaxTreeTest, PrefixUnaryOperatorCxx) {
1633   if (!GetParam().isCXX()) {
1634     return;
1635   }
1636   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1637       R"cpp(
1638 void test(int a, bool b) {
1639   [[compl a]];
1640   [[not b]];
1641 }
1642 )cpp",
1643       {R"txt(
1644 PrefixUnaryOperatorExpression Expression
1645 |-'compl' OperatorToken
1646 `-IdExpression Operand
1647   `-UnqualifiedId UnqualifiedId
1648     `-'a'
1649 )txt",
1650        R"txt(
1651 PrefixUnaryOperatorExpression Expression
1652 |-'not' OperatorToken
1653 `-IdExpression Operand
1654   `-UnqualifiedId UnqualifiedId
1655     `-'b'
1656 )txt"}));
1657 }
1658 
1659 TEST_P(BuildSyntaxTreeTest, BinaryOperator) {
1660   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1661       R"cpp(
1662 void test(int a) {
1663   [[1 - 2]];
1664   [[1 == 2]];
1665   [[a = 1]];
1666   [[a <<= 1]];
1667   [[1 || 0]];
1668   [[1 & 2]];
1669   [[a != 3]];
1670 }
1671 )cpp",
1672       {R"txt(
1673 BinaryOperatorExpression Expression
1674 |-IntegerLiteralExpression LeftHandSide
1675 | `-'1' LiteralToken
1676 |-'-' OperatorToken
1677 `-IntegerLiteralExpression RightHandSide
1678   `-'2' LiteralToken
1679 )txt",
1680        R"txt(
1681 BinaryOperatorExpression Expression
1682 |-IntegerLiteralExpression LeftHandSide
1683 | `-'1' LiteralToken
1684 |-'==' OperatorToken
1685 `-IntegerLiteralExpression RightHandSide
1686   `-'2' LiteralToken
1687 )txt",
1688        R"txt(
1689 BinaryOperatorExpression Expression
1690 |-IdExpression LeftHandSide
1691 | `-UnqualifiedId UnqualifiedId
1692 |   `-'a'
1693 |-'=' OperatorToken
1694 `-IntegerLiteralExpression RightHandSide
1695   `-'1' LiteralToken
1696 )txt",
1697        R"txt(
1698 BinaryOperatorExpression Expression
1699 |-IdExpression LeftHandSide
1700 | `-UnqualifiedId UnqualifiedId
1701 |   `-'a'
1702 |-'<<=' OperatorToken
1703 `-IntegerLiteralExpression RightHandSide
1704   `-'1' LiteralToken
1705 )txt",
1706        R"txt(
1707 BinaryOperatorExpression Expression
1708 |-IntegerLiteralExpression LeftHandSide
1709 | `-'1' LiteralToken
1710 |-'||' OperatorToken
1711 `-IntegerLiteralExpression RightHandSide
1712   `-'0' LiteralToken
1713 )txt",
1714        R"txt(
1715 BinaryOperatorExpression Expression
1716 |-IntegerLiteralExpression LeftHandSide
1717 | `-'1' LiteralToken
1718 |-'&' OperatorToken
1719 `-IntegerLiteralExpression RightHandSide
1720   `-'2' LiteralToken
1721 )txt",
1722        R"txt(
1723 BinaryOperatorExpression Expression
1724 |-IdExpression LeftHandSide
1725 | `-UnqualifiedId UnqualifiedId
1726 |   `-'a'
1727 |-'!=' OperatorToken
1728 `-IntegerLiteralExpression RightHandSide
1729   `-'3' LiteralToken
1730 )txt"}));
1731 }
1732 
1733 TEST_P(BuildSyntaxTreeTest, BinaryOperatorCxx) {
1734   if (!GetParam().isCXX()) {
1735     return;
1736   }
1737   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1738       R"cpp(
1739 void test(int a) {
1740   [[true || false]];
1741   [[true or false]];
1742   [[1 bitand 2]];
1743   [[a xor_eq 3]];
1744 }
1745 )cpp",
1746       {R"txt(
1747 BinaryOperatorExpression Expression
1748 |-BoolLiteralExpression LeftHandSide
1749 | `-'true' LiteralToken
1750 |-'||' OperatorToken
1751 `-BoolLiteralExpression RightHandSide
1752   `-'false' LiteralToken
1753 )txt",
1754        R"txt(
1755 BinaryOperatorExpression Expression
1756 |-BoolLiteralExpression LeftHandSide
1757 | `-'true' LiteralToken
1758 |-'or' OperatorToken
1759 `-BoolLiteralExpression RightHandSide
1760   `-'false' LiteralToken
1761 )txt",
1762        R"txt(
1763 BinaryOperatorExpression Expression
1764 |-IntegerLiteralExpression LeftHandSide
1765 | `-'1' LiteralToken
1766 |-'bitand' OperatorToken
1767 `-IntegerLiteralExpression RightHandSide
1768   `-'2' LiteralToken
1769 )txt",
1770        R"txt(
1771 BinaryOperatorExpression Expression
1772 |-IdExpression LeftHandSide
1773 | `-UnqualifiedId UnqualifiedId
1774 |   `-'a'
1775 |-'xor_eq' OperatorToken
1776 `-IntegerLiteralExpression RightHandSide
1777   `-'3' LiteralToken
1778 )txt"}));
1779 }
1780 
1781 TEST_P(BuildSyntaxTreeTest, BinaryOperator_NestedWithParenthesis) {
1782   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1783       R"cpp(
1784 void test() {
1785   [[(1 + 2) * (4 / 2)]];
1786 }
1787 )cpp",
1788       {R"txt(
1789 BinaryOperatorExpression Expression
1790 |-ParenExpression LeftHandSide
1791 | |-'(' OpenParen
1792 | |-BinaryOperatorExpression SubExpression
1793 | | |-IntegerLiteralExpression LeftHandSide
1794 | | | `-'1' LiteralToken
1795 | | |-'+' OperatorToken
1796 | | `-IntegerLiteralExpression RightHandSide
1797 | |   `-'2' LiteralToken
1798 | `-')' CloseParen
1799 |-'*' OperatorToken
1800 `-ParenExpression RightHandSide
1801   |-'(' OpenParen
1802   |-BinaryOperatorExpression SubExpression
1803   | |-IntegerLiteralExpression LeftHandSide
1804   | | `-'4' LiteralToken
1805   | |-'/' OperatorToken
1806   | `-IntegerLiteralExpression RightHandSide
1807   |   `-'2' LiteralToken
1808   `-')' CloseParen
1809 )txt"}));
1810 }
1811 
1812 TEST_P(BuildSyntaxTreeTest, BinaryOperator_Associativity) {
1813   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1814       R"cpp(
1815 void test(int a, int b) {
1816   [[a + b + 42]];
1817   [[a = b = 42]];
1818 }
1819 )cpp",
1820       {R"txt(
1821 BinaryOperatorExpression Expression
1822 |-BinaryOperatorExpression LeftHandSide
1823 | |-IdExpression LeftHandSide
1824 | | `-UnqualifiedId UnqualifiedId
1825 | |   `-'a'
1826 | |-'+' OperatorToken
1827 | `-IdExpression RightHandSide
1828 |   `-UnqualifiedId UnqualifiedId
1829 |     `-'b'
1830 |-'+' OperatorToken
1831 `-IntegerLiteralExpression RightHandSide
1832   `-'42' LiteralToken
1833 )txt",
1834        R"txt(
1835 BinaryOperatorExpression Expression
1836 |-IdExpression LeftHandSide
1837 | `-UnqualifiedId UnqualifiedId
1838 |   `-'a'
1839 |-'=' OperatorToken
1840 `-BinaryOperatorExpression RightHandSide
1841   |-IdExpression LeftHandSide
1842   | `-UnqualifiedId UnqualifiedId
1843   |   `-'b'
1844   |-'=' OperatorToken
1845   `-IntegerLiteralExpression RightHandSide
1846     `-'42' LiteralToken
1847 )txt"}));
1848 }
1849 
1850 TEST_P(BuildSyntaxTreeTest, BinaryOperator_Precedence) {
1851   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1852       R"cpp(
1853 void test() {
1854   [[1 + 2 * 3 + 4]];
1855   [[1 % 2 + 3 * 4]];
1856 }
1857 )cpp",
1858       {R"txt(
1859 BinaryOperatorExpression Expression
1860 |-BinaryOperatorExpression LeftHandSide
1861 | |-IntegerLiteralExpression LeftHandSide
1862 | | `-'1' LiteralToken
1863 | |-'+' OperatorToken
1864 | `-BinaryOperatorExpression RightHandSide
1865 |   |-IntegerLiteralExpression LeftHandSide
1866 |   | `-'2' LiteralToken
1867 |   |-'*' OperatorToken
1868 |   `-IntegerLiteralExpression RightHandSide
1869 |     `-'3' LiteralToken
1870 |-'+' OperatorToken
1871 `-IntegerLiteralExpression RightHandSide
1872   `-'4' LiteralToken
1873 )txt",
1874        R"txt(
1875 BinaryOperatorExpression Expression
1876 |-BinaryOperatorExpression LeftHandSide
1877 | |-IntegerLiteralExpression LeftHandSide
1878 | | `-'1' LiteralToken
1879 | |-'%' OperatorToken
1880 | `-IntegerLiteralExpression RightHandSide
1881 |   `-'2' LiteralToken
1882 |-'+' OperatorToken
1883 `-BinaryOperatorExpression RightHandSide
1884   |-IntegerLiteralExpression LeftHandSide
1885   | `-'3' LiteralToken
1886   |-'*' OperatorToken
1887   `-IntegerLiteralExpression RightHandSide
1888     `-'4' LiteralToken
1889 )txt"}));
1890 }
1891 
1892 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Assignment) {
1893   if (!GetParam().isCXX()) {
1894     return;
1895   }
1896   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1897       R"cpp(
1898 struct X {
1899   X& operator=(const X&);
1900 };
1901 void test(X x, X y) {
1902   [[x = y]];
1903 }
1904 )cpp",
1905       {R"txt(
1906 BinaryOperatorExpression Expression
1907 |-IdExpression LeftHandSide
1908 | `-UnqualifiedId UnqualifiedId
1909 |   `-'x'
1910 |-'=' OperatorToken
1911 `-IdExpression RightHandSide
1912   `-UnqualifiedId UnqualifiedId
1913     `-'y'
1914 )txt"}));
1915 }
1916 
1917 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Plus) {
1918   if (!GetParam().isCXX()) {
1919     return;
1920   }
1921   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1922       R"cpp(
1923 struct X {
1924   friend X operator+(X, const X&);
1925 };
1926 void test(X x, X y) {
1927   [[x + y]];
1928 }
1929 )cpp",
1930       {R"txt(
1931 BinaryOperatorExpression Expression
1932 |-IdExpression LeftHandSide
1933 | `-UnqualifiedId UnqualifiedId
1934 |   `-'x'
1935 |-'+' OperatorToken
1936 `-IdExpression RightHandSide
1937   `-UnqualifiedId UnqualifiedId
1938     `-'y'
1939 )txt"}));
1940 }
1941 
1942 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Less) {
1943   if (!GetParam().isCXX()) {
1944     return;
1945   }
1946   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1947       R"cpp(
1948 struct X {
1949   friend bool operator<(const X&, const X&);
1950 };
1951 void test(X x, X y) {
1952   [[x < y]];
1953 }
1954 )cpp",
1955       {R"txt(
1956 BinaryOperatorExpression Expression
1957 |-IdExpression LeftHandSide
1958 | `-UnqualifiedId UnqualifiedId
1959 |   `-'x'
1960 |-'<' OperatorToken
1961 `-IdExpression RightHandSide
1962   `-UnqualifiedId UnqualifiedId
1963     `-'y'
1964 )txt"}));
1965 }
1966 
1967 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_LeftShift) {
1968   if (!GetParam().isCXX()) {
1969     return;
1970   }
1971   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1972       R"cpp(
1973 struct X {
1974   friend X operator<<(X&, const X&);
1975 };
1976 void test(X x, X y) {
1977   [[x << y]];
1978 }
1979 )cpp",
1980       {R"txt(
1981 BinaryOperatorExpression Expression
1982 |-IdExpression LeftHandSide
1983 | `-UnqualifiedId UnqualifiedId
1984 |   `-'x'
1985 |-'<<' OperatorToken
1986 `-IdExpression RightHandSide
1987   `-UnqualifiedId UnqualifiedId
1988     `-'y'
1989 )txt"}));
1990 }
1991 
1992 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Comma) {
1993   if (!GetParam().isCXX()) {
1994     return;
1995   }
1996   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1997       R"cpp(
1998 struct X {
1999   X operator,(X&);
2000 };
2001 void test(X x, X y) {
2002   [[x, y]];
2003 }
2004 )cpp",
2005       {R"txt(
2006 BinaryOperatorExpression Expression
2007 |-IdExpression LeftHandSide
2008 | `-UnqualifiedId UnqualifiedId
2009 |   `-'x'
2010 |-',' OperatorToken
2011 `-IdExpression RightHandSide
2012   `-UnqualifiedId UnqualifiedId
2013     `-'y'
2014 )txt"}));
2015 }
2016 
2017 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PointerToMember) {
2018   if (!GetParam().isCXX()) {
2019     return;
2020   }
2021   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2022       R"cpp(
2023 struct X {
2024   X operator->*(int);
2025 };
2026 void test(X* xp, int X::* pmi) {
2027   [[xp->*pmi]];
2028 }
2029 )cpp",
2030       {R"txt(
2031 BinaryOperatorExpression Expression
2032 |-IdExpression LeftHandSide
2033 | `-UnqualifiedId UnqualifiedId
2034 |   `-'xp'
2035 |-'->*' OperatorToken
2036 `-IdExpression RightHandSide
2037   `-UnqualifiedId UnqualifiedId
2038     `-'pmi'
2039 )txt"}));
2040 }
2041 
2042 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Negation) {
2043   if (!GetParam().isCXX()) {
2044     return;
2045   }
2046   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2047       R"cpp(
2048 struct X {
2049   bool operator!();
2050 };
2051 void test(X x) {
2052   [[!x]];
2053 }
2054 )cpp",
2055       {R"txt(
2056 PrefixUnaryOperatorExpression Expression
2057 |-'!' OperatorToken
2058 `-IdExpression Operand
2059   `-UnqualifiedId UnqualifiedId
2060     `-'x'
2061 )txt"}));
2062 }
2063 
2064 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_AddressOf) {
2065   if (!GetParam().isCXX()) {
2066     return;
2067   }
2068   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2069       R"cpp(
2070 struct X {
2071   X* operator&();
2072 };
2073 void test(X x) {
2074   [[&x]];
2075 }
2076 )cpp",
2077       {R"txt(
2078 PrefixUnaryOperatorExpression Expression
2079 |-'&' OperatorToken
2080 `-IdExpression Operand
2081   `-UnqualifiedId UnqualifiedId
2082     `-'x'
2083 )txt"}));
2084 }
2085 
2086 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PrefixIncrement) {
2087   if (!GetParam().isCXX()) {
2088     return;
2089   }
2090   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2091       R"cpp(
2092 struct X {
2093   X operator++();
2094 };
2095 void test(X x) {
2096   [[++x]];
2097 }
2098 )cpp",
2099       {R"txt(
2100 PrefixUnaryOperatorExpression Expression
2101 |-'++' OperatorToken
2102 `-IdExpression Operand
2103   `-UnqualifiedId UnqualifiedId
2104     `-'x'
2105 )txt"}));
2106 }
2107 
2108 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PostfixIncrement) {
2109   if (!GetParam().isCXX()) {
2110     return;
2111   }
2112   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2113       R"cpp(
2114 struct X {
2115   X operator++(int);
2116 };
2117 void test(X x) {
2118   [[x++]];
2119 }
2120 )cpp",
2121       {R"txt(
2122 PostfixUnaryOperatorExpression Expression
2123 |-IdExpression Operand
2124 | `-UnqualifiedId UnqualifiedId
2125 |   `-'x'
2126 `-'++' OperatorToken
2127 )txt"}));
2128 }
2129 
2130 TEST_P(BuildSyntaxTreeTest, MemberExpression_SimpleWithDot) {
2131   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2132       R"cpp(
2133 struct S {
2134   int a;
2135 };
2136 void test(struct S s) {
2137   [[s.a]];
2138 }
2139 )cpp",
2140       {R"txt(
2141 MemberExpression Expression
2142 |-IdExpression Object
2143 | `-UnqualifiedId UnqualifiedId
2144 |   `-'s'
2145 |-'.' AccessToken
2146 `-IdExpression Member
2147   `-UnqualifiedId UnqualifiedId
2148     `-'a'
2149 )txt"}));
2150 }
2151 
2152 TEST_P(BuildSyntaxTreeTest, MemberExpression_StaticDataMember) {
2153   if (!GetParam().isCXX()) {
2154     return;
2155   }
2156   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2157       R"cpp(
2158 struct S {
2159   static int a;
2160 };
2161 void test(S s) {
2162   [[s.a]];
2163 }
2164 )cpp",
2165       {R"txt(
2166 MemberExpression Expression
2167 |-IdExpression Object
2168 | `-UnqualifiedId UnqualifiedId
2169 |   `-'s'
2170 |-'.' AccessToken
2171 `-IdExpression Member
2172   `-UnqualifiedId UnqualifiedId
2173     `-'a'
2174 )txt"}));
2175 }
2176 
2177 TEST_P(BuildSyntaxTreeTest, MemberExpression_SimpleWithArrow) {
2178   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2179       R"cpp(
2180 struct S {
2181   int a;
2182 };
2183 void test(struct S* sp) {
2184   [[sp->a]];
2185 }
2186 )cpp",
2187       {R"txt(
2188 MemberExpression Expression
2189 |-IdExpression Object
2190 | `-UnqualifiedId UnqualifiedId
2191 |   `-'sp'
2192 |-'->' AccessToken
2193 `-IdExpression Member
2194   `-UnqualifiedId UnqualifiedId
2195     `-'a'
2196 )txt"}));
2197 }
2198 
2199 TEST_P(BuildSyntaxTreeTest, MemberExpression_Chaining) {
2200   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2201       R"cpp(
2202 struct S {
2203   struct S* next;
2204 };
2205 void test(struct S s){
2206   [[s.next->next]];
2207 }
2208 )cpp",
2209       {R"txt(
2210 MemberExpression Expression
2211 |-MemberExpression Object
2212 | |-IdExpression Object
2213 | | `-UnqualifiedId UnqualifiedId
2214 | |   `-'s'
2215 | |-'.' AccessToken
2216 | `-IdExpression Member
2217 |   `-UnqualifiedId UnqualifiedId
2218 |     `-'next'
2219 |-'->' AccessToken
2220 `-IdExpression Member
2221   `-UnqualifiedId UnqualifiedId
2222     `-'next'
2223 )txt"}));
2224 }
2225 
2226 TEST_P(BuildSyntaxTreeTest, MemberExpression_OperatorFunction) {
2227   if (!GetParam().isCXX()) {
2228     return;
2229   }
2230   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2231       R"cpp(
2232 struct S {
2233   bool operator!();
2234 };
2235 void test(S s) {
2236   [[s.operator!()]];
2237 }
2238 )cpp",
2239       {R"txt(
2240 CallExpression Expression
2241 |-MemberExpression Callee
2242 | |-IdExpression Object
2243 | | `-UnqualifiedId UnqualifiedId
2244 | |   `-'s'
2245 | |-'.' AccessToken
2246 | `-IdExpression Member
2247 |   `-UnqualifiedId UnqualifiedId
2248 |     |-'operator'
2249 |     `-'!'
2250 |-'(' OpenParen
2251 `-')' CloseParen
2252 )txt"}));
2253 }
2254 
2255 TEST_P(BuildSyntaxTreeTest, MemberExpression_VariableTemplate) {
2256   if (!GetParam().isCXX14OrLater()) {
2257     return;
2258   }
2259   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2260       R"cpp(
2261 struct S {
2262   template<typename T>
2263   static constexpr T x = 42;
2264 };
2265 void test(S s) [[{
2266   s.x<int>;
2267 }]]
2268 )cpp",
2269       {R"txt(
2270 CompoundStatement
2271 |-'{' OpenParen
2272 |-ExpressionStatement Statement
2273 | |-MemberExpression Expression
2274 | | |-IdExpression Object
2275 | | | `-UnqualifiedId UnqualifiedId
2276 | | |   `-'s'
2277 | | |-'.' AccessToken
2278 | | `-IdExpression Member
2279 | |   `-UnqualifiedId UnqualifiedId
2280 | |     |-'x'
2281 | |     |-'<'
2282 | |     |-'int'
2283 | |     `-'>'
2284 | `-';'
2285 `-'}' CloseParen
2286 )txt"}));
2287 }
2288 
2289 TEST_P(BuildSyntaxTreeTest, MemberExpression_FunctionTemplate) {
2290   if (!GetParam().isCXX()) {
2291     return;
2292   }
2293   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2294       R"cpp(
2295 struct S {
2296   template<typename T>
2297   T f();
2298 };
2299 void test(S* sp){
2300   [[sp->f<int>()]];
2301 }
2302 )cpp",
2303       {R"txt(
2304 CallExpression Expression
2305 |-MemberExpression Callee
2306 | |-IdExpression Object
2307 | | `-UnqualifiedId UnqualifiedId
2308 | |   `-'sp'
2309 | |-'->' AccessToken
2310 | `-IdExpression Member
2311 |   `-UnqualifiedId UnqualifiedId
2312 |     |-'f'
2313 |     |-'<'
2314 |     |-'int'
2315 |     `-'>'
2316 |-'(' OpenParen
2317 `-')' CloseParen
2318 )txt"}));
2319 }
2320 
2321 TEST_P(BuildSyntaxTreeTest,
2322        MemberExpression_FunctionTemplateWithTemplateKeyword) {
2323   if (!GetParam().isCXX()) {
2324     return;
2325   }
2326   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2327       R"cpp(
2328 struct S {
2329   template<typename T>
2330   T f();
2331 };
2332 void test(S s){
2333   [[s.template f<int>()]];
2334 }
2335 )cpp",
2336       {R"txt(
2337 CallExpression Expression
2338 |-MemberExpression Callee
2339 | |-IdExpression Object
2340 | | `-UnqualifiedId UnqualifiedId
2341 | |   `-'s'
2342 | |-'.' AccessToken
2343 | |-'template'
2344 | `-IdExpression Member
2345 |   `-UnqualifiedId UnqualifiedId
2346 |     |-'f'
2347 |     |-'<'
2348 |     |-'int'
2349 |     `-'>'
2350 |-'(' OpenParen
2351 `-')' CloseParen
2352 )txt"}));
2353 }
2354 
2355 TEST_P(BuildSyntaxTreeTest, MemberExpression_WithQualifier) {
2356   if (!GetParam().isCXX()) {
2357     return;
2358   }
2359   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2360       R"cpp(
2361 struct Base {
2362   void f();
2363 };
2364 struct S : public Base {};
2365 void test(S s){
2366   [[s.Base::f()]];
2367   [[s.::S::~S()]];
2368 }
2369 )cpp",
2370       {R"txt(
2371 CallExpression Expression
2372 |-MemberExpression Callee
2373 | |-IdExpression Object
2374 | | `-UnqualifiedId UnqualifiedId
2375 | |   `-'s'
2376 | |-'.' AccessToken
2377 | `-IdExpression Member
2378 |   |-NestedNameSpecifier Qualifier
2379 |   | |-IdentifierNameSpecifier ListElement
2380 |   | | `-'Base'
2381 |   | `-'::' ListDelimiter
2382 |   `-UnqualifiedId UnqualifiedId
2383 |     `-'f'
2384 |-'(' OpenParen
2385 `-')' CloseParen
2386       )txt",
2387        R"txt(
2388 CallExpression Expression
2389 |-MemberExpression Callee
2390 | |-IdExpression Object
2391 | | `-UnqualifiedId UnqualifiedId
2392 | |   `-'s'
2393 | |-'.' AccessToken
2394 | `-IdExpression Member
2395 |   |-NestedNameSpecifier Qualifier
2396 |   | |-'::' ListDelimiter
2397 |   | |-IdentifierNameSpecifier ListElement
2398 |   | | `-'S'
2399 |   | `-'::' ListDelimiter
2400 |   `-UnqualifiedId UnqualifiedId
2401 |     |-'~'
2402 |     `-'S'
2403 |-'(' OpenParen
2404 `-')' CloseParen
2405 )txt"}));
2406 }
2407 
2408 TEST_P(BuildSyntaxTreeTest, MemberExpression_Complex) {
2409   if (!GetParam().isCXX()) {
2410     return;
2411   }
2412   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2413       R"cpp(
2414 template<typename T>
2415 struct U {
2416   template<typename U>
2417   U f();
2418 };
2419 struct S {
2420   U<int> getU();
2421 };
2422 void test(S* sp) {
2423   // FIXME: The first 'template' keyword is a child of `NestedNameSpecifier`,
2424   // but it should be a child of `MemberExpression` according to the grammar.
2425   // However one might argue that the 'template' keyword fits better inside
2426   // `NestedNameSpecifier` because if we change `U<int>` to `UI` we would like
2427   // equally to change the `NameSpecifier` `template U<int>` to just `UI`.
2428   [[sp->getU().template U<int>::template f<int>()]];
2429 }
2430 )cpp",
2431       {R"txt(
2432 CallExpression Expression
2433 |-MemberExpression Callee
2434 | |-CallExpression Object
2435 | | |-MemberExpression Callee
2436 | | | |-IdExpression Object
2437 | | | | `-UnqualifiedId UnqualifiedId
2438 | | | |   `-'sp'
2439 | | | |-'->' AccessToken
2440 | | | `-IdExpression Member
2441 | | |   `-UnqualifiedId UnqualifiedId
2442 | | |     `-'getU'
2443 | | |-'(' OpenParen
2444 | | `-')' CloseParen
2445 | |-'.' AccessToken
2446 | `-IdExpression Member
2447 |   |-NestedNameSpecifier Qualifier
2448 |   | |-SimpleTemplateNameSpecifier ListElement
2449 |   | | |-'template'
2450 |   | | |-'U'
2451 |   | | |-'<'
2452 |   | | |-'int'
2453 |   | | `-'>'
2454 |   | `-'::' ListDelimiter
2455 |   |-'template' TemplateKeyword
2456 |   `-UnqualifiedId UnqualifiedId
2457 |     |-'f'
2458 |     |-'<'
2459 |     |-'int'
2460 |     `-'>'
2461 |-'(' OpenParen
2462 `-')' CloseParen
2463 )txt"}));
2464 }
2465 
2466 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_Member) {
2467   if (!GetParam().isCXX()) {
2468     return;
2469   }
2470   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2471       R"cpp(
2472 struct S{
2473   void f();
2474 };
2475 void test(S s) {
2476   [[s.f()]];
2477 }
2478 )cpp",
2479       {R"txt(
2480 CallExpression Expression
2481 |-MemberExpression Callee
2482 | |-IdExpression Object
2483 | | `-UnqualifiedId UnqualifiedId
2484 | |   `-'s'
2485 | |-'.' AccessToken
2486 | `-IdExpression Member
2487 |   `-UnqualifiedId UnqualifiedId
2488 |     `-'f'
2489 |-'(' OpenParen
2490 `-')' CloseParen
2491 )txt"}));
2492 }
2493 
2494 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_OperatorParens) {
2495   if (!GetParam().isCXX()) {
2496     return;
2497   }
2498   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2499       R"cpp(
2500 struct S {
2501   void operator()();
2502 };
2503 void test(S s) {
2504   [[s()]];
2505 }
2506 )cpp",
2507       {R"txt(
2508 CallExpression Expression
2509 |-IdExpression Callee
2510 | `-UnqualifiedId UnqualifiedId
2511 |   `-'s'
2512 |-'(' OpenParen
2513 `-')' CloseParen
2514 )txt"}));
2515 }
2516 
2517 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_OperatorParensChaining) {
2518   if (!GetParam().isCXX()) {
2519     return;
2520   }
2521   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2522       R"cpp(
2523 struct S {
2524   S operator()();
2525 };
2526 void test(S s) {
2527   [[s()()]];
2528 }
2529 )cpp",
2530       {R"txt(
2531 CallExpression Expression
2532 |-CallExpression Callee
2533 | |-IdExpression Callee
2534 | | `-UnqualifiedId UnqualifiedId
2535 | |   `-'s'
2536 | |-'(' OpenParen
2537 | `-')' CloseParen
2538 |-'(' OpenParen
2539 `-')' CloseParen
2540 )txt"}));
2541 }
2542 
2543 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_MemberWithThis) {
2544   if (!GetParam().isCXX()) {
2545     return;
2546   }
2547   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2548       R"cpp(
2549 struct Base {
2550   void f();
2551 };
2552 struct S: public Base {
2553   void f();
2554   void test() {
2555     [[this->f()]];
2556     [[f()]];
2557     [[this->Base::f()]];
2558   }
2559 };
2560 )cpp",
2561       {R"txt(
2562 CallExpression Expression
2563 |-MemberExpression Callee
2564 | |-ThisExpression Object
2565 | | `-'this' IntroducerKeyword
2566 | |-'->' AccessToken
2567 | `-IdExpression Member
2568 |   `-UnqualifiedId UnqualifiedId
2569 |     `-'f'
2570 |-'(' OpenParen
2571 `-')' CloseParen
2572       )txt",
2573        R"txt(
2574 CallExpression Expression
2575 |-IdExpression Callee
2576 | `-UnqualifiedId UnqualifiedId
2577 |   `-'f'
2578 |-'(' OpenParen
2579 `-')' CloseParen
2580       )txt",
2581        R"txt(
2582 CallExpression Expression
2583 |-MemberExpression Callee
2584 | |-ThisExpression Object
2585 | | `-'this' IntroducerKeyword
2586 | |-'->' AccessToken
2587 | `-IdExpression Member
2588 |   |-NestedNameSpecifier Qualifier
2589 |   | |-IdentifierNameSpecifier ListElement
2590 |   | | `-'Base'
2591 |   | `-'::' ListDelimiter
2592 |   `-UnqualifiedId UnqualifiedId
2593 |     `-'f'
2594 |-'(' OpenParen
2595 `-')' CloseParen
2596 )txt"}));
2597 }
2598 
2599 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_FunctionPointer) {
2600   if (!GetParam().isCXX()) {
2601     return;
2602   }
2603   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2604       R"cpp(
2605 void (*pf)();
2606 void test() {
2607   [[pf()]];
2608   [[(*pf)()]];
2609 }
2610 )cpp",
2611       {R"txt(
2612 CallExpression Expression
2613 |-IdExpression Callee
2614 | `-UnqualifiedId UnqualifiedId
2615 |   `-'pf'
2616 |-'(' OpenParen
2617 `-')' CloseParen
2618 )txt",
2619        R"txt(
2620 CallExpression Expression
2621 |-ParenExpression Callee
2622 | |-'(' OpenParen
2623 | |-PrefixUnaryOperatorExpression SubExpression
2624 | | |-'*' OperatorToken
2625 | | `-IdExpression Operand
2626 | |   `-UnqualifiedId UnqualifiedId
2627 | |     `-'pf'
2628 | `-')' CloseParen
2629 |-'(' OpenParen
2630 `-')' CloseParen
2631 )txt"}));
2632 }
2633 
2634 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_MemberFunctionPointer) {
2635   if (!GetParam().isCXX()) {
2636     return;
2637   }
2638   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2639       R"cpp(
2640 struct S {
2641   void f();
2642 };
2643 void test(S s) {
2644   void (S::*pmf)();
2645   pmf = &S::f;
2646   [[(s.*pmf)()]];
2647 }
2648 )cpp",
2649       {R"txt(
2650 CallExpression Expression
2651 |-ParenExpression Callee
2652 | |-'(' OpenParen
2653 | |-BinaryOperatorExpression SubExpression
2654 | | |-IdExpression LeftHandSide
2655 | | | `-UnqualifiedId UnqualifiedId
2656 | | |   `-'s'
2657 | | |-'.*' OperatorToken
2658 | | `-IdExpression RightHandSide
2659 | |   `-UnqualifiedId UnqualifiedId
2660 | |     `-'pmf'
2661 | `-')' CloseParen
2662 |-'(' OpenParen
2663 `-')' CloseParen
2664 )txt"}));
2665 }
2666 
2667 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Zero) {
2668   if (!GetParam().isCXX()) {
2669     return;
2670   }
2671   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2672       R"cpp(
2673 void f();
2674 void test() {
2675   [[f();]]
2676 }
2677 )cpp",
2678       {R"txt(
2679 ExpressionStatement Statement
2680 |-CallExpression Expression
2681 | |-IdExpression Callee
2682 | | `-UnqualifiedId UnqualifiedId
2683 | |   `-'f'
2684 | |-'(' OpenParen
2685 | `-')' CloseParen
2686 `-';'
2687 )txt"}));
2688 }
2689 
2690 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_One) {
2691   if (!GetParam().isCXX()) {
2692     return;
2693   }
2694   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2695       R"cpp(
2696 void f(int);
2697 void test() {
2698   [[f(1);]]
2699 }
2700 )cpp",
2701       {R"txt(
2702 ExpressionStatement Statement
2703 |-CallExpression Expression
2704 | |-IdExpression Callee
2705 | | `-UnqualifiedId UnqualifiedId
2706 | |   `-'f'
2707 | |-'(' OpenParen
2708 | |-CallArguments Arguments
2709 | | `-IntegerLiteralExpression ListElement
2710 | |   `-'1' LiteralToken
2711 | `-')' CloseParen
2712 `-';'
2713 )txt"}));
2714 }
2715 
2716 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Multiple) {
2717   if (!GetParam().isCXX()) {
2718     return;
2719   }
2720   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2721       R"cpp(
2722 void f(int, char, float);
2723 void test() {
2724   [[f(1, '2', 3.);]]
2725 }
2726 )cpp",
2727       {R"txt(
2728 ExpressionStatement Statement
2729 |-CallExpression Expression
2730 | |-IdExpression Callee
2731 | | `-UnqualifiedId UnqualifiedId
2732 | |   `-'f'
2733 | |-'(' OpenParen
2734 | |-CallArguments Arguments
2735 | | |-IntegerLiteralExpression ListElement
2736 | | | `-'1' LiteralToken
2737 | | |-',' ListDelimiter
2738 | | |-CharacterLiteralExpression ListElement
2739 | | | `-''2'' LiteralToken
2740 | | |-',' ListDelimiter
2741 | | `-FloatingLiteralExpression ListElement
2742 | |   `-'3.' LiteralToken
2743 | `-')' CloseParen
2744 `-';'
2745 )txt"}));
2746 }
2747 
2748 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Assignment) {
2749   if (!GetParam().isCXX()) {
2750     return;
2751   }
2752   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2753       R"cpp(
2754 void f(int);
2755 void test(int a) {
2756   [[f(a = 1);]]
2757 }
2758 )cpp",
2759       {R"txt(
2760 ExpressionStatement Statement
2761 |-CallExpression Expression
2762 | |-IdExpression Callee
2763 | | `-UnqualifiedId UnqualifiedId
2764 | |   `-'f'
2765 | |-'(' OpenParen
2766 | |-CallArguments Arguments
2767 | | `-BinaryOperatorExpression ListElement
2768 | |   |-IdExpression LeftHandSide
2769 | |   | `-UnqualifiedId UnqualifiedId
2770 | |   |   `-'a'
2771 | |   |-'=' OperatorToken
2772 | |   `-IntegerLiteralExpression RightHandSide
2773 | |     `-'1' LiteralToken
2774 | `-')' CloseParen
2775 `-';'
2776 )txt"}));
2777 }
2778 
2779 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_BracedInitList_Empty) {
2780   if (!GetParam().isCXX11OrLater()) {
2781     return;
2782   }
2783   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2784       R"cpp(
2785 void f(int[]);
2786 void test() {
2787   [[f({});]]
2788 }
2789 )cpp",
2790       {R"txt(
2791 ExpressionStatement Statement
2792 |-CallExpression Expression
2793 | |-IdExpression Callee
2794 | | `-UnqualifiedId UnqualifiedId
2795 | |   `-'f'
2796 | |-'(' OpenParen
2797 | |-CallArguments Arguments
2798 | | `-UnknownExpression ListElement
2799 | |   `-UnknownExpression
2800 | |     |-'{'
2801 | |     `-'}'
2802 | `-')' CloseParen
2803 `-';'
2804 )txt"}));
2805 }
2806 
2807 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_BracedInitList_Simple) {
2808   if (!GetParam().isCXX11OrLater()) {
2809     return;
2810   }
2811   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2812       R"cpp(
2813 struct TT {};
2814 struct T{
2815   int a;
2816   TT b;
2817 };
2818 void f(T);
2819 void test() {
2820   [[f({1, {}});]]
2821 }
2822 )cpp",
2823       {R"txt(
2824 ExpressionStatement Statement
2825 |-CallExpression Expression
2826 | |-IdExpression Callee
2827 | | `-UnqualifiedId UnqualifiedId
2828 | |   `-'f'
2829 | |-'(' OpenParen
2830 | |-CallArguments Arguments
2831 | | `-UnknownExpression ListElement
2832 | |   `-UnknownExpression
2833 | |     |-'{'
2834 | |     |-IntegerLiteralExpression
2835 | |     | `-'1' LiteralToken
2836 | |     |-','
2837 | |     |-UnknownExpression
2838 | |     | `-UnknownExpression
2839 | |     |   |-'{'
2840 | |     |   `-'}'
2841 | |     `-'}'
2842 | `-')' CloseParen
2843 `-';'
2844 )txt"}));
2845 }
2846 
2847 TEST_P(BuildSyntaxTreeTest,
2848        CallExpression_Arguments_BracedInitList_Designated) {
2849   if (!GetParam().isCXX11OrLater()) {
2850     return;
2851   }
2852   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2853       R"cpp(
2854 struct TT {};
2855 struct T{
2856   int a;
2857   TT b;
2858 };
2859 void f(T);
2860 void test() {
2861   [[f({.a = 1, .b {}});]]
2862 }
2863 )cpp",
2864       {R"txt(
2865 ExpressionStatement Statement
2866 |-CallExpression Expression
2867 | |-IdExpression Callee
2868 | | `-UnqualifiedId UnqualifiedId
2869 | |   `-'f'
2870 | |-'(' OpenParen
2871 | |-CallArguments Arguments
2872 | | `-UnknownExpression ListElement
2873 | |   `-UnknownExpression
2874 | |     |-'{'
2875 | |     |-UnknownExpression
2876 | |     | |-'.'
2877 | |     | |-'a'
2878 | |     | |-'='
2879 | |     | `-IntegerLiteralExpression
2880 | |     |   `-'1' LiteralToken
2881 | |     |-','
2882 | |     |-UnknownExpression
2883 | |     | |-'.'
2884 | |     | |-'b'
2885 | |     | `-UnknownExpression
2886 | |     |   `-UnknownExpression
2887 | |     |     |-'{'
2888 | |     |     `-'}'
2889 | |     `-'}'
2890 | `-')' CloseParen
2891 `-';'
2892 )txt"}));
2893 }
2894 
2895 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_ParameterPack) {
2896   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
2897     return;
2898   }
2899   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2900       R"cpp(
2901 template<typename T, typename... Args>
2902 void test(T t, Args... args) {
2903   [[test(args...)]];
2904 }
2905 )cpp",
2906       {R"txt(
2907 CallExpression Expression
2908 |-UnknownExpression Callee
2909 | `-'test'
2910 |-'(' OpenParen
2911 |-CallArguments Arguments
2912 | `-UnknownExpression ListElement
2913 |   |-IdExpression
2914 |   | `-UnqualifiedId UnqualifiedId
2915 |   |   `-'args'
2916 |   `-'...'
2917 `-')' CloseParen
2918 )txt"}));
2919 }
2920 
2921 TEST_P(BuildSyntaxTreeTest, CallExpression_DefaultArguments) {
2922   if (!GetParam().isCXX11OrLater()) {
2923     return;
2924   }
2925   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2926       R"cpp(
2927 void f(int i = 1, char c = '2');
2928 void test() {
2929   [[f()]];
2930   [[f(1)]];
2931   [[f(1, '2')]];
2932 }
2933 )cpp",
2934       {R"txt(
2935 CallExpression Expression
2936 |-IdExpression Callee
2937 | `-UnqualifiedId UnqualifiedId
2938 |   `-'f'
2939 |-'(' OpenParen
2940 `-')' CloseParen
2941       )txt",
2942        R"txt(
2943 CallExpression Expression
2944 |-IdExpression Callee
2945 | `-UnqualifiedId UnqualifiedId
2946 |   `-'f'
2947 |-'(' OpenParen
2948 |-CallArguments Arguments
2949 | `-IntegerLiteralExpression ListElement
2950 |   `-'1' LiteralToken
2951 `-')' CloseParen
2952       )txt",
2953        R"txt(
2954 CallExpression Expression
2955 |-IdExpression Callee
2956 | `-UnqualifiedId UnqualifiedId
2957 |   `-'f'
2958 |-'(' OpenParen
2959 |-CallArguments Arguments
2960 | |-IntegerLiteralExpression ListElement
2961 | | `-'1' LiteralToken
2962 | |-',' ListDelimiter
2963 | `-CharacterLiteralExpression ListElement
2964 |   `-''2'' LiteralToken
2965 `-')' CloseParen
2966 )txt"}));
2967 }
2968 
2969 TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsGrouping) {
2970   EXPECT_TRUE(treeDumpEqual(
2971       R"cpp(
2972 int *a, b;
2973 int *c, d;
2974 )cpp",
2975       R"txt(
2976 TranslationUnit Detached
2977 |-SimpleDeclaration
2978 | |-'int'
2979 | |-DeclaratorList Declarators
2980 | | |-SimpleDeclarator ListElement
2981 | | | |-'*'
2982 | | | `-'a'
2983 | | |-',' ListDelimiter
2984 | | `-SimpleDeclarator ListElement
2985 | |   `-'b'
2986 | `-';'
2987 `-SimpleDeclaration
2988   |-'int'
2989   |-DeclaratorList Declarators
2990   | |-SimpleDeclarator ListElement
2991   | | |-'*'
2992   | | `-'c'
2993   | |-',' ListDelimiter
2994   | `-SimpleDeclarator ListElement
2995   |   `-'d'
2996   `-';'
2997 )txt"));
2998 }
2999 
3000 TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
3001   EXPECT_TRUE(treeDumpEqual(
3002       R"cpp(
3003 typedef int *a, b;
3004 )cpp",
3005       R"txt(
3006 TranslationUnit Detached
3007 `-SimpleDeclaration
3008   |-'typedef'
3009   |-'int'
3010   |-DeclaratorList Declarators
3011   | |-SimpleDeclarator ListElement
3012   | | |-'*'
3013   | | `-'a'
3014   | |-',' ListDelimiter
3015   | `-SimpleDeclarator ListElement
3016   |   `-'b'
3017   `-';'
3018 )txt"));
3019 }
3020 
3021 TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
3022   EXPECT_TRUE(treeDumpEqual(
3023       R"cpp(
3024 void foo() {
3025   int *a, b;
3026   typedef int *ta, tb;
3027 }
3028 )cpp",
3029       R"txt(
3030 TranslationUnit Detached
3031 `-SimpleDeclaration
3032   |-'void'
3033   |-DeclaratorList Declarators
3034   | `-SimpleDeclarator ListElement
3035   |   |-'foo'
3036   |   `-ParametersAndQualifiers
3037   |     |-'(' OpenParen
3038   |     `-')' CloseParen
3039   `-CompoundStatement
3040     |-'{' OpenParen
3041     |-DeclarationStatement Statement
3042     | |-SimpleDeclaration
3043     | | |-'int'
3044     | | `-DeclaratorList Declarators
3045     | |   |-SimpleDeclarator ListElement
3046     | |   | |-'*'
3047     | |   | `-'a'
3048     | |   |-',' ListDelimiter
3049     | |   `-SimpleDeclarator ListElement
3050     | |     `-'b'
3051     | `-';'
3052     |-DeclarationStatement Statement
3053     | |-SimpleDeclaration
3054     | | |-'typedef'
3055     | | |-'int'
3056     | | `-DeclaratorList Declarators
3057     | |   |-SimpleDeclarator ListElement
3058     | |   | |-'*'
3059     | |   | `-'ta'
3060     | |   |-',' ListDelimiter
3061     | |   `-SimpleDeclarator ListElement
3062     | |     `-'tb'
3063     | `-';'
3064     `-'}' CloseParen
3065 )txt"));
3066 }
3067 
3068 TEST_P(BuildSyntaxTreeTest, SizeTTypedef) {
3069   if (!GetParam().isCXX11OrLater()) {
3070     return;
3071   }
3072   EXPECT_TRUE(treeDumpEqual(
3073       R"cpp(
3074 typedef decltype(sizeof(void *)) size_t;
3075     )cpp",
3076       R"txt(
3077 TranslationUnit Detached
3078 `-SimpleDeclaration
3079   |-'typedef'
3080   |-'decltype'
3081   |-'('
3082   |-UnknownExpression
3083   | |-'sizeof'
3084   | |-'('
3085   | |-'void'
3086   | |-'*'
3087   | `-')'
3088   |-')'
3089   |-DeclaratorList Declarators
3090   | `-SimpleDeclarator ListElement
3091   |   `-'size_t'
3092   `-';'
3093 )txt"));
3094 }
3095 
3096 TEST_P(BuildSyntaxTreeTest, Namespace_Nested) {
3097   if (!GetParam().isCXX()) {
3098     return;
3099   }
3100   EXPECT_TRUE(treeDumpEqual(
3101       R"cpp(
3102 namespace a { namespace b {} }
3103 )cpp",
3104       R"txt(
3105 TranslationUnit Detached
3106 `-NamespaceDefinition
3107   |-'namespace'
3108   |-'a'
3109   |-'{'
3110   |-NamespaceDefinition
3111   | |-'namespace'
3112   | |-'b'
3113   | |-'{'
3114   | `-'}'
3115   `-'}'
3116 )txt"));
3117 }
3118 
3119 TEST_P(BuildSyntaxTreeTest, Namespace_NestedDefinition) {
3120   if (!GetParam().isCXX17OrLater()) {
3121     return;
3122   }
3123   EXPECT_TRUE(treeDumpEqual(
3124       R"cpp(
3125 namespace a::b {}
3126 )cpp",
3127       R"txt(
3128 TranslationUnit Detached
3129 `-NamespaceDefinition
3130   |-'namespace'
3131   |-'a'
3132   |-'::'
3133   |-'b'
3134   |-'{'
3135   `-'}'
3136 )txt"));
3137 }
3138 
3139 TEST_P(BuildSyntaxTreeTest, Namespace_Unnamed) {
3140   if (!GetParam().isCXX()) {
3141     return;
3142   }
3143   EXPECT_TRUE(treeDumpEqual(
3144       R"cpp(
3145 namespace {}
3146 )cpp",
3147       R"txt(
3148 TranslationUnit Detached
3149 `-NamespaceDefinition
3150   |-'namespace'
3151   |-'{'
3152   `-'}'
3153 )txt"));
3154 }
3155 
3156 TEST_P(BuildSyntaxTreeTest, Namespace_Alias) {
3157   if (!GetParam().isCXX()) {
3158     return;
3159   }
3160   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3161       R"cpp(
3162 namespace a {}
3163 [[namespace foo = a;]]
3164 )cpp",
3165       {R"txt(
3166 NamespaceAliasDefinition
3167 |-'namespace'
3168 |-'foo'
3169 |-'='
3170 |-'a'
3171 `-';'
3172 )txt"}));
3173 }
3174 
3175 TEST_P(BuildSyntaxTreeTest, UsingDirective) {
3176   if (!GetParam().isCXX()) {
3177     return;
3178   }
3179   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3180       R"cpp(
3181 namespace ns {}
3182 [[using namespace ::ns;]]
3183 )cpp",
3184       {R"txt(
3185 UsingNamespaceDirective
3186 |-'using'
3187 |-'namespace'
3188 |-NestedNameSpecifier
3189 | `-'::' ListDelimiter
3190 |-'ns'
3191 `-';'
3192 )txt"}));
3193 }
3194 
3195 TEST_P(BuildSyntaxTreeTest, UsingDeclaration_Namespace) {
3196   if (!GetParam().isCXX()) {
3197     return;
3198   }
3199   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3200       R"cpp(
3201 namespace ns { int a; }
3202 [[using ns::a;]]
3203 )cpp",
3204       {R"txt(
3205 UsingDeclaration
3206 |-'using'
3207 |-NestedNameSpecifier
3208 | |-IdentifierNameSpecifier ListElement
3209 | | `-'ns'
3210 | `-'::' ListDelimiter
3211 |-'a'
3212 `-';'
3213 )txt"}));
3214 }
3215 
3216 TEST_P(BuildSyntaxTreeTest, UsingDeclaration_ClassMember) {
3217   if (!GetParam().isCXX()) {
3218     return;
3219   }
3220   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3221       R"cpp(
3222 template <class T> struct X {
3223   [[using T::foo;]]
3224   [[using typename T::bar;]]
3225 };
3226 )cpp",
3227       {R"txt(
3228 UsingDeclaration
3229 |-'using'
3230 |-NestedNameSpecifier
3231 | |-IdentifierNameSpecifier ListElement
3232 | | `-'T'
3233 | `-'::' ListDelimiter
3234 |-'foo'
3235 `-';'
3236 )txt",
3237        R"txt(
3238 UsingDeclaration
3239 |-'using'
3240 |-'typename'
3241 |-NestedNameSpecifier
3242 | |-IdentifierNameSpecifier ListElement
3243 | | `-'T'
3244 | `-'::' ListDelimiter
3245 |-'bar'
3246 `-';'
3247 )txt"}));
3248 }
3249 
3250 TEST_P(BuildSyntaxTreeTest, UsingTypeAlias) {
3251   if (!GetParam().isCXX11OrLater()) {
3252     return;
3253   }
3254   EXPECT_TRUE(treeDumpEqual(
3255       R"cpp(
3256 using type = int;
3257 )cpp",
3258       R"txt(
3259 TranslationUnit Detached
3260 `-TypeAliasDeclaration
3261   |-'using'
3262   |-'type'
3263   |-'='
3264   |-'int'
3265   `-';'
3266 )txt"));
3267 }
3268 
3269 TEST_P(BuildSyntaxTreeTest, FreeStandingClass_ForwardDeclaration) {
3270   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3271       R"cpp(
3272 [[struct X;]]
3273 [[struct Y *y1;]]
3274 )cpp",
3275       {R"txt(
3276 SimpleDeclaration
3277 |-'struct'
3278 |-'X'
3279 `-';'
3280 )txt",
3281        R"txt(
3282 SimpleDeclaration
3283 |-'struct'
3284 |-'Y'
3285 |-DeclaratorList Declarators
3286 | `-SimpleDeclarator ListElement
3287 |   |-'*'
3288 |   `-'y1'
3289 `-';'
3290 )txt"}));
3291 }
3292 
3293 TEST_P(BuildSyntaxTreeTest, FreeStandingClasses_Definition) {
3294   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3295       R"cpp(
3296 [[struct X {};]]
3297 [[struct Y {} *y2;]]
3298 [[struct {} *a1;]]
3299 )cpp",
3300       {R"txt(
3301 SimpleDeclaration
3302 |-'struct'
3303 |-'X'
3304 |-'{'
3305 |-'}'
3306 `-';'
3307 )txt",
3308        R"txt(
3309 SimpleDeclaration
3310 |-'struct'
3311 |-'Y'
3312 |-'{'
3313 |-'}'
3314 |-DeclaratorList Declarators
3315 | `-SimpleDeclarator ListElement
3316 |   |-'*'
3317 |   `-'y2'
3318 `-';'
3319 )txt",
3320        R"txt(
3321 SimpleDeclaration
3322 |-'struct'
3323 |-'{'
3324 |-'}'
3325 |-DeclaratorList Declarators
3326 | `-SimpleDeclarator ListElement
3327 |   |-'*'
3328 |   `-'a1'
3329 `-';'
3330 )txt"}));
3331 }
3332 
3333 TEST_P(BuildSyntaxTreeTest, StaticMemberFunction) {
3334   if (!GetParam().isCXX11OrLater()) {
3335     return;
3336   }
3337   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3338       R"cpp(
3339 struct S {
3340   [[static void f(){}]]
3341 };
3342 )cpp",
3343       {R"txt(
3344 SimpleDeclaration
3345 |-'static'
3346 |-'void'
3347 |-DeclaratorList Declarators
3348 | `-SimpleDeclarator ListElement
3349 |   |-'f'
3350 |   `-ParametersAndQualifiers
3351 |     |-'(' OpenParen
3352 |     `-')' CloseParen
3353 `-CompoundStatement
3354   |-'{' OpenParen
3355   `-'}' CloseParen
3356 )txt"}));
3357 }
3358 
3359 TEST_P(BuildSyntaxTreeTest, OutOfLineMemberFunctionDefinition) {
3360   if (!GetParam().isCXX11OrLater()) {
3361     return;
3362   }
3363   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3364       R"cpp(
3365 struct S {
3366   void f();
3367 };
3368 [[void S::f(){}]]
3369 )cpp",
3370       {R"txt(
3371 SimpleDeclaration
3372 |-'void'
3373 |-DeclaratorList Declarators
3374 | `-SimpleDeclarator ListElement
3375 |   |-NestedNameSpecifier
3376 |   | |-IdentifierNameSpecifier ListElement
3377 |   | | `-'S'
3378 |   | `-'::' ListDelimiter
3379 |   |-'f'
3380 |   `-ParametersAndQualifiers
3381 |     |-'(' OpenParen
3382 |     `-')' CloseParen
3383 `-CompoundStatement
3384   |-'{' OpenParen
3385   `-'}' CloseParen
3386 )txt"}));
3387 }
3388 
3389 TEST_P(BuildSyntaxTreeTest, ConversionMemberFunction) {
3390   if (!GetParam().isCXX()) {
3391     return;
3392   }
3393   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3394       R"cpp(
3395 struct X {
3396   [[operator int();]]
3397 };
3398 )cpp",
3399       {R"txt(
3400 SimpleDeclaration
3401 |-DeclaratorList Declarators
3402 | `-SimpleDeclarator ListElement
3403 |   |-'operator'
3404 |   |-'int'
3405 |   `-ParametersAndQualifiers
3406 |     |-'(' OpenParen
3407 |     `-')' CloseParen
3408 `-';'
3409 )txt"}));
3410 }
3411 
3412 TEST_P(BuildSyntaxTreeTest, LiteralOperatorDeclaration) {
3413   if (!GetParam().isCXX11OrLater()) {
3414     return;
3415   }
3416   EXPECT_TRUE(treeDumpEqual(
3417       R"cpp(
3418 unsigned operator "" _c(char);
3419     )cpp",
3420       R"txt(
3421 TranslationUnit Detached
3422 `-SimpleDeclaration
3423   |-'unsigned'
3424   |-DeclaratorList Declarators
3425   | `-SimpleDeclarator ListElement
3426   |   |-'operator'
3427   |   |-'""'
3428   |   |-'_c'
3429   |   `-ParametersAndQualifiers
3430   |     |-'(' OpenParen
3431   |     |-ParameterDeclarationList Parameters
3432   |     | `-SimpleDeclaration ListElement
3433   |     |   `-'char'
3434   |     `-')' CloseParen
3435   `-';'
3436 )txt"));
3437 }
3438 
3439 TEST_P(BuildSyntaxTreeTest, NumericLiteralOperatorTemplateDeclaration) {
3440   if (!GetParam().isCXX11OrLater()) {
3441     return;
3442   }
3443   EXPECT_TRUE(treeDumpEqual(
3444       R"cpp(
3445 template <char...>
3446 unsigned operator "" _t();
3447     )cpp",
3448       R"txt(
3449 TranslationUnit Detached
3450 `-TemplateDeclaration Declaration
3451   |-'template' IntroducerKeyword
3452   |-'<'
3453   |-SimpleDeclaration
3454   | `-'char'
3455   |-'...'
3456   |-'>'
3457   `-SimpleDeclaration
3458     |-'unsigned'
3459     |-DeclaratorList Declarators
3460     | `-SimpleDeclarator ListElement
3461     |   |-'operator'
3462     |   |-'""'
3463     |   |-'_t'
3464     |   `-ParametersAndQualifiers
3465     |     |-'(' OpenParen
3466     |     `-')' CloseParen
3467     `-';'
3468 )txt"));
3469 }
3470 
3471 TEST_P(BuildSyntaxTreeTest, OverloadedOperatorDeclaration) {
3472   if (!GetParam().isCXX()) {
3473     return;
3474   }
3475   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3476       R"cpp(
3477 struct X {
3478   [[X& operator=(const X&);]]
3479 };
3480 )cpp",
3481       {R"txt(
3482 SimpleDeclaration
3483 |-'X'
3484 |-DeclaratorList Declarators
3485 | `-SimpleDeclarator ListElement
3486 |   |-'&'
3487 |   |-'operator'
3488 |   |-'='
3489 |   `-ParametersAndQualifiers
3490 |     |-'(' OpenParen
3491 |     |-ParameterDeclarationList Parameters
3492 |     | `-SimpleDeclaration ListElement
3493 |     |   |-'const'
3494 |     |   |-'X'
3495 |     |   `-DeclaratorList Declarators
3496 |     |     `-SimpleDeclarator ListElement
3497 |     |       `-'&'
3498 |     `-')' CloseParen
3499 `-';'
3500 )txt"}));
3501 }
3502 
3503 TEST_P(BuildSyntaxTreeTest, OverloadedOperatorFriendDeclaration) {
3504   if (!GetParam().isCXX()) {
3505     return;
3506   }
3507   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3508       R"cpp(
3509 struct X {
3510   [[friend X operator+(X, const X&);]]
3511 };
3512 )cpp",
3513       {R"txt(
3514 UnknownDeclaration
3515 `-SimpleDeclaration
3516   |-'friend'
3517   |-'X'
3518   |-DeclaratorList Declarators
3519   | `-SimpleDeclarator ListElement
3520   |   |-'operator'
3521   |   |-'+'
3522   |   `-ParametersAndQualifiers
3523   |     |-'(' OpenParen
3524   |     |-ParameterDeclarationList Parameters
3525   |     | |-SimpleDeclaration ListElement
3526   |     | | `-'X'
3527   |     | |-',' ListDelimiter
3528   |     | `-SimpleDeclaration ListElement
3529   |     |   |-'const'
3530   |     |   |-'X'
3531   |     |   `-DeclaratorList Declarators
3532   |     |     `-SimpleDeclarator ListElement
3533   |     |       `-'&'
3534   |     `-')' CloseParen
3535   `-';'
3536 )txt"}));
3537 }
3538 
3539 TEST_P(BuildSyntaxTreeTest, ClassTemplateDeclaration) {
3540   if (!GetParam().isCXX()) {
3541     return;
3542   }
3543   EXPECT_TRUE(treeDumpEqual(
3544       R"cpp(
3545 template<typename T>
3546 struct ST {};
3547 )cpp",
3548       R"txt(
3549 TranslationUnit Detached
3550 `-TemplateDeclaration Declaration
3551   |-'template' IntroducerKeyword
3552   |-'<'
3553   |-UnknownDeclaration
3554   | |-'typename'
3555   | `-'T'
3556   |-'>'
3557   `-SimpleDeclaration
3558     |-'struct'
3559     |-'ST'
3560     |-'{'
3561     |-'}'
3562     `-';'
3563 )txt"));
3564 }
3565 
3566 TEST_P(BuildSyntaxTreeTest, FunctionTemplateDeclaration) {
3567   if (!GetParam().isCXX()) {
3568     return;
3569   }
3570   EXPECT_TRUE(treeDumpEqual(
3571       R"cpp(
3572 template<typename T>
3573 T f();
3574 )cpp",
3575       R"txt(
3576 TranslationUnit Detached
3577 `-TemplateDeclaration Declaration
3578   |-'template' IntroducerKeyword
3579   |-'<'
3580   |-UnknownDeclaration
3581   | |-'typename'
3582   | `-'T'
3583   |-'>'
3584   `-SimpleDeclaration
3585     |-'T'
3586     |-DeclaratorList Declarators
3587     | `-SimpleDeclarator ListElement
3588     |   |-'f'
3589     |   `-ParametersAndQualifiers
3590     |     |-'(' OpenParen
3591     |     `-')' CloseParen
3592     `-';'
3593 )txt"));
3594 }
3595 
3596 TEST_P(BuildSyntaxTreeTest, VariableTemplateDeclaration) {
3597   if (!GetParam().isCXX14OrLater()) {
3598     return;
3599   }
3600   EXPECT_TRUE(treeDumpEqual(
3601       R"cpp(
3602 template <class T> T var = 10;
3603 )cpp",
3604       R"txt(
3605 TranslationUnit Detached
3606 `-TemplateDeclaration Declaration
3607   |-'template' IntroducerKeyword
3608   |-'<'
3609   |-UnknownDeclaration
3610   | |-'class'
3611   | `-'T'
3612   |-'>'
3613   `-SimpleDeclaration
3614     |-'T'
3615     |-DeclaratorList Declarators
3616     | `-SimpleDeclarator ListElement
3617     |   |-'var'
3618     |   |-'='
3619     |   `-IntegerLiteralExpression
3620     |     `-'10' LiteralToken
3621     `-';'
3622 )txt"));
3623 }
3624 
3625 TEST_P(BuildSyntaxTreeTest, StaticMemberFunctionTemplate) {
3626   if (!GetParam().isCXX()) {
3627     return;
3628   }
3629   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3630       R"cpp(
3631 struct S {
3632   [[template<typename U>
3633   static U f();]]
3634 };
3635 )cpp",
3636       {R"txt(
3637 TemplateDeclaration Declaration
3638 |-'template' IntroducerKeyword
3639 |-'<'
3640 |-UnknownDeclaration
3641 | |-'typename'
3642 | `-'U'
3643 |-'>'
3644 `-SimpleDeclaration
3645   |-'static'
3646   |-'U'
3647   |-DeclaratorList Declarators
3648   | `-SimpleDeclarator ListElement
3649   |   |-'f'
3650   |   `-ParametersAndQualifiers
3651   |     |-'(' OpenParen
3652   |     `-')' CloseParen
3653   `-';'
3654 )txt"}));
3655 }
3656 
3657 TEST_P(BuildSyntaxTreeTest, NestedTemplates) {
3658   if (!GetParam().isCXX()) {
3659     return;
3660   }
3661   EXPECT_TRUE(treeDumpEqual(
3662       R"cpp(
3663 template <class T>
3664 struct X {
3665   template <class U>
3666   U foo();
3667 };
3668 )cpp",
3669       R"txt(
3670 TranslationUnit Detached
3671 `-TemplateDeclaration Declaration
3672   |-'template' IntroducerKeyword
3673   |-'<'
3674   |-UnknownDeclaration
3675   | |-'class'
3676   | `-'T'
3677   |-'>'
3678   `-SimpleDeclaration
3679     |-'struct'
3680     |-'X'
3681     |-'{'
3682     |-TemplateDeclaration Declaration
3683     | |-'template' IntroducerKeyword
3684     | |-'<'
3685     | |-UnknownDeclaration
3686     | | |-'class'
3687     | | `-'U'
3688     | |-'>'
3689     | `-SimpleDeclaration
3690     |   |-'U'
3691     |   |-DeclaratorList Declarators
3692     |   | `-SimpleDeclarator ListElement
3693     |   |   |-'foo'
3694     |   |   `-ParametersAndQualifiers
3695     |   |     |-'(' OpenParen
3696     |   |     `-')' CloseParen
3697     |   `-';'
3698     |-'}'
3699     `-';'
3700 )txt"));
3701 }
3702 
3703 TEST_P(BuildSyntaxTreeTest, NestedTemplatesInNamespace) {
3704   if (!GetParam().isCXX()) {
3705     return;
3706   }
3707   EXPECT_TRUE(treeDumpEqual(
3708       R"cpp(
3709 namespace n {
3710   template<typename T>
3711   struct ST {
3712     template<typename U>
3713     static U f();
3714   };
3715 }
3716 )cpp",
3717       R"txt(
3718 TranslationUnit Detached
3719 `-NamespaceDefinition
3720   |-'namespace'
3721   |-'n'
3722   |-'{'
3723   |-TemplateDeclaration Declaration
3724   | |-'template' IntroducerKeyword
3725   | |-'<'
3726   | |-UnknownDeclaration
3727   | | |-'typename'
3728   | | `-'T'
3729   | |-'>'
3730   | `-SimpleDeclaration
3731   |   |-'struct'
3732   |   |-'ST'
3733   |   |-'{'
3734   |   |-TemplateDeclaration Declaration
3735   |   | |-'template' IntroducerKeyword
3736   |   | |-'<'
3737   |   | |-UnknownDeclaration
3738   |   | | |-'typename'
3739   |   | | `-'U'
3740   |   | |-'>'
3741   |   | `-SimpleDeclaration
3742   |   |   |-'static'
3743   |   |   |-'U'
3744   |   |   |-DeclaratorList Declarators
3745   |   |   | `-SimpleDeclarator ListElement
3746   |   |   |   |-'f'
3747   |   |   |   `-ParametersAndQualifiers
3748   |   |   |     |-'(' OpenParen
3749   |   |   |     `-')' CloseParen
3750   |   |   `-';'
3751   |   |-'}'
3752   |   `-';'
3753   `-'}'
3754 )txt"));
3755 }
3756 
3757 TEST_P(BuildSyntaxTreeTest, ClassTemplate_MemberClassDefinition) {
3758   if (!GetParam().isCXX()) {
3759     return;
3760   }
3761   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3762       R"cpp(
3763 template <class T> struct X { struct Y; };
3764 [[template <class T> struct X<T>::Y {};]]
3765 )cpp",
3766       {R"txt(
3767 TemplateDeclaration Declaration
3768 |-'template' IntroducerKeyword
3769 |-'<'
3770 |-UnknownDeclaration
3771 | |-'class'
3772 | `-'T'
3773 |-'>'
3774 `-SimpleDeclaration
3775   |-'struct'
3776   |-NestedNameSpecifier
3777   | |-SimpleTemplateNameSpecifier ListElement
3778   | | |-'X'
3779   | | |-'<'
3780   | | |-'T'
3781   | | `-'>'
3782   | `-'::' ListDelimiter
3783   |-'Y'
3784   |-'{'
3785   |-'}'
3786   `-';'
3787 )txt"}));
3788 }
3789 
3790 TEST_P(BuildSyntaxTreeTest, ExplicitClassTemplateInstantiation_Definition) {
3791   if (!GetParam().isCXX()) {
3792     return;
3793   }
3794   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3795       R"cpp(
3796 template <class T> struct X {};
3797 [[template struct X<double>;]]
3798 )cpp",
3799       {R"txt(
3800 ExplicitTemplateInstantiation
3801 |-'template' IntroducerKeyword
3802 `-SimpleDeclaration Declaration
3803   |-'struct'
3804   |-'X'
3805   |-'<'
3806   |-'double'
3807   |-'>'
3808   `-';'
3809 )txt"}));
3810 }
3811 
3812 TEST_P(BuildSyntaxTreeTest, ExplicitClassTemplateInstantiation_Declaration) {
3813   if (!GetParam().isCXX()) {
3814     return;
3815   }
3816   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3817       R"cpp(
3818 template <class T> struct X {};
3819 [[extern template struct X<float>;]]
3820 )cpp",
3821       {R"txt(
3822 ExplicitTemplateInstantiation
3823 |-'extern' ExternKeyword
3824 |-'template' IntroducerKeyword
3825 `-SimpleDeclaration Declaration
3826   |-'struct'
3827   |-'X'
3828   |-'<'
3829   |-'float'
3830   |-'>'
3831   `-';'
3832 )txt"}));
3833 }
3834 
3835 TEST_P(BuildSyntaxTreeTest, ClassTemplateSpecialization_Partial) {
3836   if (!GetParam().isCXX()) {
3837     return;
3838   }
3839   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3840       R"cpp(
3841 template <class T> struct X {};
3842 [[template <class T> struct X<T*> {};]]
3843 )cpp",
3844       {R"txt(
3845 TemplateDeclaration Declaration
3846 |-'template' IntroducerKeyword
3847 |-'<'
3848 |-UnknownDeclaration
3849 | |-'class'
3850 | `-'T'
3851 |-'>'
3852 `-SimpleDeclaration
3853   |-'struct'
3854   |-'X'
3855   |-'<'
3856   |-'T'
3857   |-'*'
3858   |-'>'
3859   |-'{'
3860   |-'}'
3861   `-';'
3862 )txt"}));
3863 }
3864 
3865 TEST_P(BuildSyntaxTreeTest, ClassTemplateSpecialization_Full) {
3866   if (!GetParam().isCXX()) {
3867     return;
3868   }
3869   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3870       R"cpp(
3871 template <class T> struct X {};
3872 [[template <> struct X<int> {};]]
3873 )cpp",
3874       {R"txt(
3875 TemplateDeclaration Declaration
3876 |-'template' IntroducerKeyword
3877 |-'<'
3878 |-'>'
3879 `-SimpleDeclaration
3880   |-'struct'
3881   |-'X'
3882   |-'<'
3883   |-'int'
3884   |-'>'
3885   |-'{'
3886   |-'}'
3887   `-';'
3888 )txt"}));
3889 }
3890 
3891 TEST_P(BuildSyntaxTreeTest, EmptyDeclaration) {
3892   EXPECT_TRUE(treeDumpEqual(
3893       R"cpp(
3894 ;
3895 )cpp",
3896       R"txt(
3897 TranslationUnit Detached
3898 `-EmptyDeclaration
3899   `-';'
3900 )txt"));
3901 }
3902 
3903 TEST_P(BuildSyntaxTreeTest, StaticAssert) {
3904   if (!GetParam().isCXX11OrLater()) {
3905     return;
3906   }
3907   EXPECT_TRUE(treeDumpEqual(
3908       R"cpp(
3909 static_assert(true, "message");
3910 )cpp",
3911       R"txt(
3912 TranslationUnit Detached
3913 `-StaticAssertDeclaration
3914   |-'static_assert'
3915   |-'('
3916   |-BoolLiteralExpression Condition
3917   | `-'true' LiteralToken
3918   |-','
3919   |-StringLiteralExpression Message
3920   | `-'"message"' LiteralToken
3921   |-')'
3922   `-';'
3923 )txt"));
3924 }
3925 
3926 TEST_P(BuildSyntaxTreeTest, StaticAssert_WithoutMessage) {
3927   if (!GetParam().isCXX17OrLater()) {
3928     return;
3929   }
3930   EXPECT_TRUE(treeDumpEqual(
3931       R"cpp(
3932 static_assert(true);
3933 )cpp",
3934       R"txt(
3935 TranslationUnit Detached
3936 `-StaticAssertDeclaration
3937   |-'static_assert'
3938   |-'('
3939   |-BoolLiteralExpression Condition
3940   | `-'true' LiteralToken
3941   |-')'
3942   `-';'
3943 )txt"));
3944 }
3945 
3946 TEST_P(BuildSyntaxTreeTest, ExternC) {
3947   if (!GetParam().isCXX()) {
3948     return;
3949   }
3950   EXPECT_TRUE(treeDumpEqual(
3951       R"cpp(
3952 extern "C" int a;
3953 extern "C" { int b; int c; }
3954 )cpp",
3955       R"txt(
3956 TranslationUnit Detached
3957 |-LinkageSpecificationDeclaration
3958 | |-'extern'
3959 | |-'"C"'
3960 | `-SimpleDeclaration
3961 |   |-'int'
3962 |   |-DeclaratorList Declarators
3963 |   | `-SimpleDeclarator ListElement
3964 |   |   `-'a'
3965 |   `-';'
3966 `-LinkageSpecificationDeclaration
3967   |-'extern'
3968   |-'"C"'
3969   |-'{'
3970   |-SimpleDeclaration
3971   | |-'int'
3972   | |-DeclaratorList Declarators
3973   | | `-SimpleDeclarator ListElement
3974   | |   `-'b'
3975   | `-';'
3976   |-SimpleDeclaration
3977   | |-'int'
3978   | |-DeclaratorList Declarators
3979   | | `-SimpleDeclarator ListElement
3980   | |   `-'c'
3981   | `-';'
3982   `-'}'
3983 )txt"));
3984 }
3985 
3986 TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_Leaf) {
3987   // All nodes can be mutated.
3988   EXPECT_TRUE(treeDumpEqual(
3989       R"cpp(
3990 #define OPEN {
3991 #define CLOSE }
3992 
3993 void test() {
3994   OPEN
3995     1;
3996   CLOSE
3997 
3998   OPEN
3999     2;
4000   }
4001 }
4002 )cpp",
4003       R"txt(
4004 TranslationUnit Detached
4005 `-SimpleDeclaration
4006   |-'void'
4007   |-DeclaratorList Declarators
4008   | `-SimpleDeclarator ListElement
4009   |   |-'test'
4010   |   `-ParametersAndQualifiers
4011   |     |-'(' OpenParen
4012   |     `-')' CloseParen
4013   `-CompoundStatement
4014     |-'{' OpenParen
4015     |-CompoundStatement Statement
4016     | |-'{' OpenParen
4017     | |-ExpressionStatement Statement
4018     | | |-IntegerLiteralExpression Expression
4019     | | | `-'1' LiteralToken
4020     | | `-';'
4021     | `-'}' CloseParen
4022     |-CompoundStatement Statement
4023     | |-'{' OpenParen
4024     | |-ExpressionStatement Statement
4025     | | |-IntegerLiteralExpression Expression
4026     | | | `-'2' LiteralToken
4027     | | `-';'
4028     | `-'}' CloseParen
4029     `-'}' CloseParen
4030 )txt"));
4031 }
4032 
4033 TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MatchTree) {
4034   // Some nodes are unmodifiable, they are marked with 'unmodifiable'.
4035   EXPECT_TRUE(treeDumpEqual(
4036       R"cpp(
4037 #define BRACES {}
4038 
4039 void test() BRACES
4040 )cpp",
4041       R"txt(
4042 TranslationUnit Detached
4043 `-SimpleDeclaration
4044   |-'void'
4045   |-DeclaratorList Declarators
4046   | `-SimpleDeclarator ListElement
4047   |   |-'test'
4048   |   `-ParametersAndQualifiers
4049   |     |-'(' OpenParen
4050   |     `-')' CloseParen
4051   `-CompoundStatement
4052     |-'{' OpenParen unmodifiable
4053     `-'}' CloseParen unmodifiable
4054 )txt"));
4055 }
4056 
4057 TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MismatchTree) {
4058   EXPECT_TRUE(treeDumpEqual(
4059       R"cpp(
4060 #define HALF_IF if (1+
4061 #define HALF_IF_2 1) {}
4062 void test() {
4063   HALF_IF HALF_IF_2 else {}
4064 })cpp",
4065       R"txt(
4066 TranslationUnit Detached
4067 `-SimpleDeclaration
4068   |-'void'
4069   |-DeclaratorList Declarators
4070   | `-SimpleDeclarator ListElement
4071   |   |-'test'
4072   |   `-ParametersAndQualifiers
4073   |     |-'(' OpenParen
4074   |     `-')' CloseParen
4075   `-CompoundStatement
4076     |-'{' OpenParen
4077     |-IfStatement Statement
4078     | |-'if' IntroducerKeyword unmodifiable
4079     | |-'(' unmodifiable
4080     | |-ExpressionStatement Condition unmodifiable
4081     | | `-BinaryOperatorExpression Expression unmodifiable
4082     | |   |-IntegerLiteralExpression LeftHandSide unmodifiable
4083     | |   | `-'1' LiteralToken unmodifiable
4084     | |   |-'+' OperatorToken unmodifiable
4085     | |   `-IntegerLiteralExpression RightHandSide unmodifiable
4086     | |     `-'1' LiteralToken unmodifiable
4087     | |-')' unmodifiable
4088     | |-CompoundStatement ThenStatement unmodifiable
4089     | | |-'{' OpenParen unmodifiable
4090     | | `-'}' CloseParen unmodifiable
4091     | |-'else' ElseKeyword
4092     | `-CompoundStatement ElseStatement
4093     |   |-'{' OpenParen
4094     |   `-'}' CloseParen
4095     `-'}' CloseParen
4096 )txt"));
4097 }
4098 
4099 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_ModifiableArguments) {
4100   // FIXME: Note that the substitutions for `X` and `Y` are marked modifiable.
4101   // However we cannot change `X` freely. Indeed if we change its substitution
4102   // in the condition we should also change it the then-branch.
4103   EXPECT_TRUE(treeDumpEqual(
4104       R"cpp(
4105 #define MIN(X,Y) X < Y ? X : Y
4106 
4107 void test() {
4108   MIN(1,2);
4109 }
4110 )cpp",
4111       R"txt(
4112 TranslationUnit Detached
4113 `-SimpleDeclaration
4114   |-'void'
4115   |-DeclaratorList Declarators
4116   | `-SimpleDeclarator ListElement
4117   |   |-'test'
4118   |   `-ParametersAndQualifiers
4119   |     |-'(' OpenParen
4120   |     `-')' CloseParen
4121   `-CompoundStatement
4122     |-'{' OpenParen
4123     |-ExpressionStatement Statement
4124     | |-UnknownExpression Expression
4125     | | |-BinaryOperatorExpression unmodifiable
4126     | | | |-IntegerLiteralExpression LeftHandSide
4127     | | | | `-'1' LiteralToken
4128     | | | |-'<' OperatorToken unmodifiable
4129     | | | `-IntegerLiteralExpression RightHandSide
4130     | | |   `-'2' LiteralToken
4131     | | |-'?' unmodifiable
4132     | | |-IntegerLiteralExpression
4133     | | | `-'1' LiteralToken
4134     | | |-':' unmodifiable
4135     | | `-IntegerLiteralExpression
4136     | |   `-'2' LiteralToken
4137     | `-';'
4138     `-'}' CloseParen
4139 )txt"));
4140 }
4141 
4142 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_MismatchTree) {
4143   EXPECT_TRUE(treeDumpEqual(
4144       R"cpp(
4145 #define HALF_IF(X) if (X &&
4146 #define HALF_IF_2(Y) Y) {}
4147 void test() {
4148   HALF_IF(1) HALF_IF_2(0) else {}
4149 })cpp",
4150       R"txt(
4151 TranslationUnit Detached
4152 `-SimpleDeclaration
4153   |-'void'
4154   |-DeclaratorList Declarators
4155   | `-SimpleDeclarator ListElement
4156   |   |-'test'
4157   |   `-ParametersAndQualifiers
4158   |     |-'(' OpenParen
4159   |     `-')' CloseParen
4160   `-CompoundStatement
4161     |-'{' OpenParen
4162     |-IfStatement Statement
4163     | |-'if' IntroducerKeyword unmodifiable
4164     | |-'(' unmodifiable
4165     | |-ExpressionStatement Condition unmodifiable
4166     | | `-BinaryOperatorExpression Expression unmodifiable
4167     | |   |-IntegerLiteralExpression LeftHandSide
4168     | |   | `-'1' LiteralToken
4169     | |   |-'&&' OperatorToken unmodifiable
4170     | |   `-IntegerLiteralExpression RightHandSide
4171     | |     `-'0' LiteralToken
4172     | |-')' unmodifiable
4173     | |-CompoundStatement ThenStatement unmodifiable
4174     | | |-'{' OpenParen unmodifiable
4175     | | `-'}' CloseParen unmodifiable
4176     | |-'else' ElseKeyword
4177     | `-CompoundStatement ElseStatement
4178     |   |-'{' OpenParen
4179     |   `-'}' CloseParen
4180     `-'}' CloseParen
4181 )txt"));
4182 }
4183 
4184 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_Variadic) {
4185   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4186       R"cpp(
4187 #define CALL(F_NAME, ...) F_NAME(__VA_ARGS__)
4188 
4189 void f(int);
4190 void g(int, int);
4191 void test() [[{
4192   CALL(f, 0);
4193   CALL(g, 0, 1);
4194 }]]
4195 )cpp",
4196       {R"txt(
4197 CompoundStatement
4198 |-'{' OpenParen
4199 |-ExpressionStatement Statement
4200 | |-CallExpression Expression
4201 | | |-IdExpression Callee
4202 | | | `-UnqualifiedId UnqualifiedId
4203 | | |   `-'f'
4204 | | |-'(' OpenParen unmodifiable
4205 | | |-CallArguments Arguments
4206 | | | `-IntegerLiteralExpression ListElement
4207 | | |   `-'0' LiteralToken
4208 | | `-')' CloseParen unmodifiable
4209 | `-';'
4210 |-ExpressionStatement Statement
4211 | |-CallExpression Expression
4212 | | |-IdExpression Callee
4213 | | | `-UnqualifiedId UnqualifiedId
4214 | | |   `-'g'
4215 | | |-'(' OpenParen unmodifiable
4216 | | |-CallArguments Arguments
4217 | | | |-IntegerLiteralExpression ListElement
4218 | | | | `-'0' LiteralToken
4219 | | | |-',' ListDelimiter
4220 | | | `-IntegerLiteralExpression ListElement
4221 | | |   `-'1' LiteralToken
4222 | | `-')' CloseParen unmodifiable
4223 | `-';'
4224 `-'}' CloseParen
4225 )txt"}));
4226 }
4227 
4228 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Equal) {
4229   if (!GetParam().isCXX()) {
4230     return;
4231   }
4232   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4233       R"cpp(
4234 struct S { S(int);};
4235 void test() {
4236   [[S s = 1]];
4237 }
4238 )cpp",
4239       {R"txt(
4240 SimpleDeclaration
4241 |-'S'
4242 `-DeclaratorList Declarators
4243   `-SimpleDeclarator ListElement
4244     |-'s'
4245     |-'='
4246     `-IntegerLiteralExpression
4247       `-'1' LiteralToken
4248 )txt"}));
4249 }
4250 
4251 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Brace) {
4252   if (!GetParam().isCXX11OrLater()) {
4253     return;
4254   }
4255   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4256       R"cpp(
4257 struct S {
4258   S();
4259   S(int);
4260   S(int, float);
4261 };
4262 void test(){
4263   // FIXME: 's...' is a declarator and '{...}' is initializer
4264   [[S s0{}]];
4265   [[S s1{1}]];
4266   [[S s2{1, 2.}]];
4267 }
4268 )cpp",
4269       {R"txt(
4270 SimpleDeclaration
4271 |-'S'
4272 `-DeclaratorList Declarators
4273   `-SimpleDeclarator ListElement
4274     `-UnknownExpression
4275       |-'s0'
4276       |-'{'
4277       `-'}'
4278   )txt",
4279        R"txt(
4280 SimpleDeclaration
4281 |-'S'
4282 `-DeclaratorList Declarators
4283   `-SimpleDeclarator ListElement
4284     `-UnknownExpression
4285       |-'s1'
4286       |-'{'
4287       |-IntegerLiteralExpression
4288       | `-'1' LiteralToken
4289       `-'}'
4290   )txt",
4291        R"txt(
4292 SimpleDeclaration
4293 |-'S'
4294 `-DeclaratorList Declarators
4295   `-SimpleDeclarator ListElement
4296     `-UnknownExpression
4297       |-'s2'
4298       |-'{'
4299       |-IntegerLiteralExpression
4300       | `-'1' LiteralToken
4301       |-','
4302       |-FloatingLiteralExpression
4303       | `-'2.' LiteralToken
4304       `-'}'
4305 )txt"}));
4306 }
4307 
4308 TEST_P(BuildSyntaxTreeTest, InitDeclarator_EqualBrace) {
4309   if (!GetParam().isCXX11OrLater()) {
4310     return;
4311   }
4312   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4313       R"cpp(
4314 struct S {
4315   S();
4316   S(int);
4317   S(int, float);
4318 };
4319 void test() {
4320   // FIXME: '= {...}' is initializer
4321   [[S s0 = {}]];
4322   [[S s1 = {1}]];
4323   [[S s2 = {1, 2.}]];
4324 }
4325 )cpp",
4326       {R"txt(
4327 SimpleDeclaration
4328 |-'S'
4329 `-DeclaratorList Declarators
4330   `-SimpleDeclarator ListElement
4331     |-'s0'
4332     |-'='
4333     `-UnknownExpression
4334       |-'{'
4335       `-'}'
4336   )txt",
4337        R"txt(
4338 SimpleDeclaration
4339 |-'S'
4340 `-DeclaratorList Declarators
4341   `-SimpleDeclarator ListElement
4342     |-'s1'
4343     |-'='
4344     `-UnknownExpression
4345       |-'{'
4346       |-IntegerLiteralExpression
4347       | `-'1' LiteralToken
4348       `-'}'
4349   )txt",
4350        R"txt(
4351 SimpleDeclaration
4352 |-'S'
4353 `-DeclaratorList Declarators
4354   `-SimpleDeclarator ListElement
4355     |-'s2'
4356     |-'='
4357     `-UnknownExpression
4358       |-'{'
4359       |-IntegerLiteralExpression
4360       | `-'1' LiteralToken
4361       |-','
4362       |-FloatingLiteralExpression
4363       | `-'2.' LiteralToken
4364       `-'}'
4365 )txt"}));
4366 }
4367 
4368 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Paren) {
4369   if (!GetParam().isCXX()) {
4370     return;
4371   }
4372   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4373       R"cpp(
4374 struct S {
4375   S(int);
4376   S(int, float);
4377 };
4378 // FIXME: 's...' is a declarator and '(...)' is initializer
4379 [[S s1(1);]]
4380 [[S s2(1, 2.);]]
4381 )cpp",
4382       {R"txt(
4383 SimpleDeclaration
4384 |-'S'
4385 |-DeclaratorList Declarators
4386 | `-SimpleDeclarator ListElement
4387 |   `-UnknownExpression
4388 |     |-'s1'
4389 |     |-'('
4390 |     |-IntegerLiteralExpression
4391 |     | `-'1' LiteralToken
4392 |     `-')'
4393 `-';'
4394   )txt",
4395        R"txt(
4396 SimpleDeclaration
4397 |-'S'
4398 |-DeclaratorList Declarators
4399 | `-SimpleDeclarator ListElement
4400 |   `-UnknownExpression
4401 |     |-'s2'
4402 |     |-'('
4403 |     |-IntegerLiteralExpression
4404 |     | `-'1' LiteralToken
4405 |     |-','
4406 |     |-FloatingLiteralExpression
4407 |     | `-'2.' LiteralToken
4408 |     `-')'
4409 `-';'
4410 )txt"}));
4411 }
4412 
4413 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Paren_DefaultArguments) {
4414   if (!GetParam().isCXX()) {
4415     return;
4416   }
4417   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4418       R"cpp(
4419 struct S {
4420   S(int i = 1, float = 2.);
4421 };
4422 [[S s0;]]
4423 // FIXME: 's...' is a declarator and '(...)' is initializer
4424 [[S s1(1);]]
4425 [[S s2(1, 2.);]]
4426 )cpp",
4427       {R"txt(
4428 SimpleDeclaration
4429 |-'S'
4430 |-DeclaratorList Declarators
4431 | `-SimpleDeclarator ListElement
4432 |   `-'s0'
4433 `-';'
4434   )txt",
4435        R"txt(
4436 SimpleDeclaration
4437 |-'S'
4438 |-DeclaratorList Declarators
4439 | `-SimpleDeclarator ListElement
4440 |   `-UnknownExpression
4441 |     |-'s1'
4442 |     |-'('
4443 |     |-IntegerLiteralExpression
4444 |     | `-'1' LiteralToken
4445 |     `-')'
4446 `-';'
4447   )txt",
4448        R"txt(
4449 SimpleDeclaration
4450 |-'S'
4451 |-DeclaratorList Declarators
4452 | `-SimpleDeclarator ListElement
4453 |   `-UnknownExpression
4454 |     |-'s2'
4455 |     |-'('
4456 |     |-IntegerLiteralExpression
4457 |     | `-'1' LiteralToken
4458 |     |-','
4459 |     |-FloatingLiteralExpression
4460 |     | `-'2.' LiteralToken
4461 |     `-')'
4462 `-';'
4463 )txt"}));
4464 }
4465 
4466 TEST_P(BuildSyntaxTreeTest, ImplicitConversion_Argument) {
4467   if (!GetParam().isCXX()) {
4468     return;
4469   }
4470   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4471       R"cpp(
4472 struct X {
4473   X(int);
4474 };
4475 void TakeX(const X&);
4476 void test() {
4477   [[TakeX(1)]];
4478 }
4479 )cpp",
4480       {R"txt(
4481 CallExpression Expression
4482 |-IdExpression Callee
4483 | `-UnqualifiedId UnqualifiedId
4484 |   `-'TakeX'
4485 |-'(' OpenParen
4486 |-CallArguments Arguments
4487 | `-IntegerLiteralExpression ListElement
4488 |   `-'1' LiteralToken
4489 `-')' CloseParen
4490 )txt"}));
4491 }
4492 
4493 TEST_P(BuildSyntaxTreeTest, ImplicitConversion_Return) {
4494   if (!GetParam().isCXX()) {
4495     return;
4496   }
4497   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4498       R"cpp(
4499 struct X {
4500   X(int);
4501 };
4502 X CreateX(){
4503   [[return 1;]]
4504 }
4505 )cpp",
4506       {R"txt(
4507 ReturnStatement Statement
4508 |-'return' IntroducerKeyword
4509 |-IntegerLiteralExpression ReturnValue
4510 | `-'1' LiteralToken
4511 `-';'
4512 )txt"}));
4513 }
4514 
4515 TEST_P(BuildSyntaxTreeTest, ConstructorCall_ZeroArguments) {
4516   if (!GetParam().isCXX()) {
4517     return;
4518   }
4519   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4520       R"cpp(
4521 struct X {
4522   X();
4523 };
4524 X test() {
4525   [[return X();]]
4526 }
4527 )cpp",
4528       {R"txt(
4529 ReturnStatement Statement
4530 |-'return' IntroducerKeyword
4531 |-UnknownExpression ReturnValue
4532 | |-'X'
4533 | |-'('
4534 | `-')'
4535 `-';'
4536 )txt"}));
4537 }
4538 
4539 TEST_P(BuildSyntaxTreeTest, ConstructorCall_OneArgument) {
4540   if (!GetParam().isCXX()) {
4541     return;
4542   }
4543   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4544       R"cpp(
4545 struct X {
4546   X(int);
4547 };
4548 X test() {
4549   [[return X(1);]]
4550 }
4551 )cpp",
4552       {R"txt(
4553 ReturnStatement Statement
4554 |-'return' IntroducerKeyword
4555 |-UnknownExpression ReturnValue
4556 | |-'X'
4557 | |-'('
4558 | |-IntegerLiteralExpression
4559 | | `-'1' LiteralToken
4560 | `-')'
4561 `-';'
4562 )txt"}));
4563 }
4564 
4565 TEST_P(BuildSyntaxTreeTest, ConstructorCall_MultipleArguments) {
4566   if (!GetParam().isCXX()) {
4567     return;
4568   }
4569   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4570       R"cpp(
4571 struct X {
4572   X(int, char);
4573 };
4574 X test() {
4575   [[return X(1, '2');]]
4576 }
4577 )cpp",
4578       {R"txt(
4579 ReturnStatement Statement
4580 |-'return' IntroducerKeyword
4581 |-UnknownExpression ReturnValue
4582 | |-'X'
4583 | |-'('
4584 | |-IntegerLiteralExpression
4585 | | `-'1' LiteralToken
4586 | |-','
4587 | |-CharacterLiteralExpression
4588 | | `-''2'' LiteralToken
4589 | `-')'
4590 `-';'
4591 )txt"}));
4592 }
4593 
4594 TEST_P(BuildSyntaxTreeTest, ConstructorCall_DefaultArguments) {
4595   if (!GetParam().isCXX()) {
4596     return;
4597   }
4598   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4599       R"cpp(
4600 struct X {
4601   X(int i = 1, char c = '2');
4602 };
4603 X test() {
4604   auto x0 = [[X()]];
4605   auto x1 = [[X(1)]];
4606   auto x2 = [[X(1, '2')]];
4607 }
4608 )cpp",
4609       {R"txt(
4610 UnknownExpression
4611 |-'X'
4612 |-'('
4613 `-')'
4614 )txt",
4615        R"txt(
4616 UnknownExpression
4617 |-'X'
4618 |-'('
4619 |-IntegerLiteralExpression
4620 | `-'1' LiteralToken
4621 `-')'
4622 )txt",
4623        R"txt(
4624 UnknownExpression
4625 |-'X'
4626 |-'('
4627 |-IntegerLiteralExpression
4628 | `-'1' LiteralToken
4629 |-','
4630 |-CharacterLiteralExpression
4631 | `-''2'' LiteralToken
4632 `-')'
4633 )txt"}));
4634 }
4635 
4636 TEST_P(BuildSyntaxTreeTest, TypeConversion_FunctionalNotation) {
4637   if (!GetParam().isCXX()) {
4638     return;
4639   }
4640   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4641       R"cpp(
4642 float test() {
4643   [[return float(1);]]
4644 }
4645 )cpp",
4646       {R"txt(
4647 ReturnStatement Statement
4648 |-'return' IntroducerKeyword
4649 |-UnknownExpression ReturnValue
4650 | |-'float'
4651 | |-'('
4652 | |-IntegerLiteralExpression
4653 | | `-'1' LiteralToken
4654 | `-')'
4655 `-';'
4656 )txt"}));
4657 }
4658 
4659 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Simple) {
4660   EXPECT_TRUE(treeDumpEqual(
4661       R"cpp(
4662 int a[10];
4663 )cpp",
4664       R"txt(
4665 TranslationUnit Detached
4666 `-SimpleDeclaration
4667   |-'int'
4668   |-DeclaratorList Declarators
4669   | `-SimpleDeclarator ListElement
4670   |   |-'a'
4671   |   `-ArraySubscript
4672   |     |-'[' OpenParen
4673   |     |-IntegerLiteralExpression Size
4674   |     | `-'10' LiteralToken
4675   |     `-']' CloseParen
4676   `-';'
4677 )txt"));
4678 }
4679 
4680 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Multidimensional) {
4681   EXPECT_TRUE(treeDumpEqual(
4682       R"cpp(
4683 int b[1][2][3];
4684 )cpp",
4685       R"txt(
4686 TranslationUnit Detached
4687 `-SimpleDeclaration
4688   |-'int'
4689   |-DeclaratorList Declarators
4690   | `-SimpleDeclarator ListElement
4691   |   |-'b'
4692   |   |-ArraySubscript
4693   |   | |-'[' OpenParen
4694   |   | |-IntegerLiteralExpression Size
4695   |   | | `-'1' LiteralToken
4696   |   | `-']' CloseParen
4697   |   |-ArraySubscript
4698   |   | |-'[' OpenParen
4699   |   | |-IntegerLiteralExpression Size
4700   |   | | `-'2' LiteralToken
4701   |   | `-']' CloseParen
4702   |   `-ArraySubscript
4703   |     |-'[' OpenParen
4704   |     |-IntegerLiteralExpression Size
4705   |     | `-'3' LiteralToken
4706   |     `-']' CloseParen
4707   `-';'
4708 )txt"));
4709 }
4710 
4711 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_UnknownBound) {
4712   EXPECT_TRUE(treeDumpEqual(
4713       R"cpp(
4714 int c[] = {1,2,3};
4715 )cpp",
4716       R"txt(
4717 TranslationUnit Detached
4718 `-SimpleDeclaration
4719   |-'int'
4720   |-DeclaratorList Declarators
4721   | `-SimpleDeclarator ListElement
4722   |   |-'c'
4723   |   |-ArraySubscript
4724   |   | |-'[' OpenParen
4725   |   | `-']' CloseParen
4726   |   |-'='
4727   |   `-UnknownExpression
4728   |     `-UnknownExpression
4729   |       |-'{'
4730   |       |-IntegerLiteralExpression
4731   |       | `-'1' LiteralToken
4732   |       |-','
4733   |       |-IntegerLiteralExpression
4734   |       | `-'2' LiteralToken
4735   |       |-','
4736   |       |-IntegerLiteralExpression
4737   |       | `-'3' LiteralToken
4738   |       `-'}'
4739   `-';'
4740 )txt"));
4741 }
4742 
4743 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Static) {
4744   if (!GetParam().isC99OrLater()) {
4745     return;
4746   }
4747   EXPECT_TRUE(treeDumpEqual(
4748       R"cpp(
4749 void f(int xs[static 10]);
4750 )cpp",
4751       R"txt(
4752 TranslationUnit Detached
4753 `-SimpleDeclaration
4754   |-'void'
4755   |-DeclaratorList Declarators
4756   | `-SimpleDeclarator ListElement
4757   |   |-'f'
4758   |   `-ParametersAndQualifiers
4759   |     |-'(' OpenParen
4760   |     |-ParameterDeclarationList Parameters
4761   |     | `-SimpleDeclaration ListElement
4762   |     |   |-'int'
4763   |     |   `-DeclaratorList Declarators
4764   |     |     `-SimpleDeclarator ListElement
4765   |     |       |-'xs'
4766   |     |       `-ArraySubscript
4767   |     |         |-'[' OpenParen
4768   |     |         |-'static'
4769   |     |         |-IntegerLiteralExpression Size
4770   |     |         | `-'10' LiteralToken
4771   |     |         `-']' CloseParen
4772   |     `-')' CloseParen
4773   `-';'
4774 )txt"));
4775 }
4776 
4777 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) {
4778   EXPECT_TRUE(treeDumpEqual(
4779       R"cpp(
4780 int func();
4781 )cpp",
4782       R"txt(
4783 TranslationUnit Detached
4784 `-SimpleDeclaration
4785   |-'int'
4786   |-DeclaratorList Declarators
4787   | `-SimpleDeclarator ListElement
4788   |   |-'func'
4789   |   `-ParametersAndQualifiers
4790   |     |-'(' OpenParen
4791   |     `-')' CloseParen
4792   `-';'
4793 )txt"));
4794 }
4795 
4796 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) {
4797   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4798       R"cpp(
4799      int func1([[int a]]);
4800      int func2([[int *ap]]);
4801      int func3([[int a, float b]]);
4802      int func4([[undef a]]); // error-ok: no crash on invalid type
4803    )cpp",
4804       {R"txt(
4805 ParameterDeclarationList Parameters
4806 `-SimpleDeclaration ListElement
4807   |-'int'
4808   `-DeclaratorList Declarators
4809     `-SimpleDeclarator ListElement
4810       `-'a'
4811 )txt",
4812        R"txt(
4813 ParameterDeclarationList Parameters
4814 `-SimpleDeclaration ListElement
4815   |-'int'
4816   `-DeclaratorList Declarators
4817     `-SimpleDeclarator ListElement
4818       |-'*'
4819       `-'ap'
4820 )txt",
4821        R"txt(
4822 ParameterDeclarationList Parameters
4823 |-SimpleDeclaration ListElement
4824 | |-'int'
4825 | `-DeclaratorList Declarators
4826 |   `-SimpleDeclarator ListElement
4827 |     `-'a'
4828 |-',' ListDelimiter
4829 `-SimpleDeclaration ListElement
4830   |-'float'
4831   `-DeclaratorList Declarators
4832     `-SimpleDeclarator ListElement
4833       `-'b'
4834 )txt",
4835        R"txt(
4836 ParameterDeclarationList Parameters
4837 `-SimpleDeclaration ListElement
4838   |-'undef'
4839   `-DeclaratorList Declarators
4840     `-SimpleDeclarator ListElement
4841       `-'a'
4842 )txt"}));
4843 }
4844 
4845 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
4846   EXPECT_TRUE(treeDumpEqual(
4847       R"cpp(
4848 int func1(int);
4849 int func2(int *);
4850 int func3(int, float);
4851 )cpp",
4852       R"txt(
4853 TranslationUnit Detached
4854 |-SimpleDeclaration
4855 | |-'int'
4856 | |-DeclaratorList Declarators
4857 | | `-SimpleDeclarator ListElement
4858 | |   |-'func1'
4859 | |   `-ParametersAndQualifiers
4860 | |     |-'(' OpenParen
4861 | |     |-ParameterDeclarationList Parameters
4862 | |     | `-SimpleDeclaration ListElement
4863 | |     |   `-'int'
4864 | |     `-')' CloseParen
4865 | `-';'
4866 |-SimpleDeclaration
4867 | |-'int'
4868 | |-DeclaratorList Declarators
4869 | | `-SimpleDeclarator ListElement
4870 | |   |-'func2'
4871 | |   `-ParametersAndQualifiers
4872 | |     |-'(' OpenParen
4873 | |     |-ParameterDeclarationList Parameters
4874 | |     | `-SimpleDeclaration ListElement
4875 | |     |   |-'int'
4876 | |     |   `-DeclaratorList Declarators
4877 | |     |     `-SimpleDeclarator ListElement
4878 | |     |       `-'*'
4879 | |     `-')' CloseParen
4880 | `-';'
4881 `-SimpleDeclaration
4882   |-'int'
4883   |-DeclaratorList Declarators
4884   | `-SimpleDeclarator ListElement
4885   |   |-'func3'
4886   |   `-ParametersAndQualifiers
4887   |     |-'(' OpenParen
4888   |     |-ParameterDeclarationList Parameters
4889   |     | |-SimpleDeclaration ListElement
4890   |     | | `-'int'
4891   |     | |-',' ListDelimiter
4892   |     | `-SimpleDeclaration ListElement
4893   |     |   `-'float'
4894   |     `-')' CloseParen
4895   `-';'
4896 )txt"));
4897 }
4898 
4899 TEST_P(BuildSyntaxTreeTest,
4900        ParametersAndQualifiers_InFreeFunctions_Default_One) {
4901   if (!GetParam().isCXX()) {
4902     return;
4903   }
4904   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4905       R"cpp(
4906 int func1([[int a = 1]]);
4907 )cpp",
4908       {R"txt(
4909 ParameterDeclarationList Parameters
4910 `-SimpleDeclaration ListElement
4911   |-'int'
4912   `-DeclaratorList Declarators
4913     `-SimpleDeclarator ListElement
4914       |-'a'
4915       |-'='
4916       `-IntegerLiteralExpression
4917         `-'1' LiteralToken
4918 )txt"}));
4919 }
4920 
4921 TEST_P(BuildSyntaxTreeTest,
4922        ParametersAndQualifiers_InFreeFunctions_Default_Multiple) {
4923   if (!GetParam().isCXX()) {
4924     return;
4925   }
4926   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4927       R"cpp(
4928 int func2([[int *ap, int a = 1, char c = '2']]);
4929 )cpp",
4930       {R"txt(
4931 ParameterDeclarationList Parameters
4932 |-SimpleDeclaration ListElement
4933 | |-'int'
4934 | `-DeclaratorList Declarators
4935 |   `-SimpleDeclarator ListElement
4936 |     |-'*'
4937 |     `-'ap'
4938 |-',' ListDelimiter
4939 |-SimpleDeclaration ListElement
4940 | |-'int'
4941 | `-DeclaratorList Declarators
4942 |   `-SimpleDeclarator ListElement
4943 |     |-'a'
4944 |     |-'='
4945 |     `-IntegerLiteralExpression
4946 |       `-'1' LiteralToken
4947 |-',' ListDelimiter
4948 `-SimpleDeclaration ListElement
4949   |-'char'
4950   `-DeclaratorList Declarators
4951     `-SimpleDeclarator ListElement
4952       |-'c'
4953       |-'='
4954       `-CharacterLiteralExpression
4955         `-''2'' LiteralToken
4956 )txt"}));
4957 }
4958 
4959 TEST_P(BuildSyntaxTreeTest,
4960        ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) {
4961   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4962     return;
4963   }
4964   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4965       R"cpp(
4966 template<typename T, typename... Args>
4967 [[void test(T , Args... );]]
4968 )cpp",
4969       {R"txt(
4970 SimpleDeclaration
4971 |-'void'
4972 |-DeclaratorList Declarators
4973 | `-SimpleDeclarator ListElement
4974 |   |-'test'
4975 |   `-ParametersAndQualifiers
4976 |     |-'(' OpenParen
4977 |     |-ParameterDeclarationList Parameters
4978 |     | |-SimpleDeclaration ListElement
4979 |     | | `-'T'
4980 |     | |-',' ListDelimiter
4981 |     | `-SimpleDeclaration ListElement
4982 |     |   |-'Args'
4983 |     |   `-'...'
4984 |     `-')' CloseParen
4985 `-';'
4986 )txt"}));
4987 }
4988 
4989 TEST_P(BuildSyntaxTreeTest,
4990        ParametersAndQualifiers_InVariadicFunctionTemplate_NamedParameterPack) {
4991   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4992     return;
4993   }
4994   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4995       R"cpp(
4996 template<typename T, typename... Args>
4997 [[void test(T t, Args... args);]]
4998 )cpp",
4999       {R"txt(
5000 SimpleDeclaration
5001 |-'void'
5002 |-DeclaratorList Declarators
5003 | `-SimpleDeclarator ListElement
5004 |   |-'test'
5005 |   `-ParametersAndQualifiers
5006 |     |-'(' OpenParen
5007 |     |-ParameterDeclarationList Parameters
5008 |     | |-SimpleDeclaration ListElement
5009 |     | | |-'T'
5010 |     | | `-DeclaratorList Declarators
5011 |     | |   `-SimpleDeclarator ListElement
5012 |     | |     `-'t'
5013 |     | |-',' ListDelimiter
5014 |     | `-SimpleDeclaration ListElement
5015 |     |   |-'Args'
5016 |     |   |-'...'
5017 |     |   `-DeclaratorList Declarators
5018 |     |     `-SimpleDeclarator ListElement
5019 |     |       `-'args'
5020 |     `-')' CloseParen
5021 `-';'
5022 )txt"}));
5023 }
5024 
5025 TEST_P(BuildSyntaxTreeTest,
5026        ParametersAndQualifiers_InFreeFunctions_VariadicArguments) {
5027   if (!GetParam().isCXX11OrLater()) {
5028     return;
5029   }
5030   EXPECT_TRUE(treeDumpEqual(
5031       R"cpp(
5032 void test(int , char ...);
5033 )cpp",
5034       R"txt(
5035 TranslationUnit Detached
5036 `-SimpleDeclaration
5037   |-'void'
5038   |-DeclaratorList Declarators
5039   | `-SimpleDeclarator ListElement
5040   |   |-'test'
5041   |   `-ParametersAndQualifiers
5042   |     |-'(' OpenParen
5043   |     |-ParameterDeclarationList Parameters
5044   |     | |-SimpleDeclaration ListElement
5045   |     | | `-'int'
5046   |     | |-',' ListDelimiter
5047   |     | `-SimpleDeclaration ListElement
5048   |     |   `-'char'
5049   |     |-'...'
5050   |     `-')' CloseParen
5051   `-';'
5052 )txt"));
5053 }
5054 
5055 TEST_P(BuildSyntaxTreeTest,
5056        ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
5057   if (!GetParam().isCXX()) {
5058     return;
5059   }
5060   EXPECT_TRUE(treeDumpEqual(
5061       R"cpp(
5062 int func(const int a, volatile int b, const volatile int c);
5063 )cpp",
5064       R"txt(
5065 TranslationUnit Detached
5066 `-SimpleDeclaration
5067   |-'int'
5068   |-DeclaratorList Declarators
5069   | `-SimpleDeclarator ListElement
5070   |   |-'func'
5071   |   `-ParametersAndQualifiers
5072   |     |-'(' OpenParen
5073   |     |-ParameterDeclarationList Parameters
5074   |     | |-SimpleDeclaration ListElement
5075   |     | | |-'const'
5076   |     | | |-'int'
5077   |     | | `-DeclaratorList Declarators
5078   |     | |   `-SimpleDeclarator ListElement
5079   |     | |     `-'a'
5080   |     | |-',' ListDelimiter
5081   |     | |-SimpleDeclaration ListElement
5082   |     | | |-'volatile'
5083   |     | | |-'int'
5084   |     | | `-DeclaratorList Declarators
5085   |     | |   `-SimpleDeclarator ListElement
5086   |     | |     `-'b'
5087   |     | |-',' ListDelimiter
5088   |     | `-SimpleDeclaration ListElement
5089   |     |   |-'const'
5090   |     |   |-'volatile'
5091   |     |   |-'int'
5092   |     |   `-DeclaratorList Declarators
5093   |     |     `-SimpleDeclarator ListElement
5094   |     |       `-'c'
5095   |     `-')' CloseParen
5096   `-';'
5097 )txt"));
5098 }
5099 
5100 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
5101   if (!GetParam().isCXX()) {
5102     return;
5103   }
5104   EXPECT_TRUE(treeDumpEqual(
5105       R"cpp(
5106 int func(int& a);
5107 )cpp",
5108       R"txt(
5109 TranslationUnit Detached
5110 `-SimpleDeclaration
5111   |-'int'
5112   |-DeclaratorList Declarators
5113   | `-SimpleDeclarator ListElement
5114   |   |-'func'
5115   |   `-ParametersAndQualifiers
5116   |     |-'(' OpenParen
5117   |     |-ParameterDeclarationList Parameters
5118   |     | `-SimpleDeclaration ListElement
5119   |     |   |-'int'
5120   |     |   `-DeclaratorList Declarators
5121   |     |     `-SimpleDeclarator ListElement
5122   |     |       |-'&'
5123   |     |       `-'a'
5124   |     `-')' CloseParen
5125   `-';'
5126 )txt"));
5127 }
5128 
5129 TEST_P(BuildSyntaxTreeTest,
5130        ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
5131   if (!GetParam().isCXX11OrLater()) {
5132     return;
5133   }
5134   EXPECT_TRUE(treeDumpEqual(
5135       R"cpp(
5136 int func(int&& a);
5137 )cpp",
5138       R"txt(
5139 TranslationUnit Detached
5140 `-SimpleDeclaration
5141   |-'int'
5142   |-DeclaratorList Declarators
5143   | `-SimpleDeclarator ListElement
5144   |   |-'func'
5145   |   `-ParametersAndQualifiers
5146   |     |-'(' OpenParen
5147   |     |-ParameterDeclarationList Parameters
5148   |     | `-SimpleDeclaration ListElement
5149   |     |   |-'int'
5150   |     |   `-DeclaratorList Declarators
5151   |     |     `-SimpleDeclarator ListElement
5152   |     |       |-'&&'
5153   |     |       `-'a'
5154   |     `-')' CloseParen
5155   `-';'
5156 )txt"));
5157 }
5158 
5159 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
5160   if (!GetParam().isCXX()) {
5161     return;
5162   }
5163   EXPECT_TRUE(treeDumpEqual(
5164       R"cpp(
5165 struct Test {
5166   int a();
5167 };
5168 )cpp",
5169       R"txt(
5170 TranslationUnit Detached
5171 `-SimpleDeclaration
5172   |-'struct'
5173   |-'Test'
5174   |-'{'
5175   |-SimpleDeclaration
5176   | |-'int'
5177   | |-DeclaratorList Declarators
5178   | | `-SimpleDeclarator ListElement
5179   | |   |-'a'
5180   | |   `-ParametersAndQualifiers
5181   | |     |-'(' OpenParen
5182   | |     `-')' CloseParen
5183   | `-';'
5184   |-'}'
5185   `-';'
5186 )txt"));
5187 }
5188 
5189 TEST_P(BuildSyntaxTreeTest,
5190        ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
5191   if (!GetParam().isCXX()) {
5192     return;
5193   }
5194   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5195       R"cpp(
5196 struct Test {
5197   [[int b() const;]]
5198   [[int c() volatile;]]
5199   [[int d() const volatile;]]
5200 };
5201 )cpp",
5202       {R"txt(
5203 SimpleDeclaration
5204 |-'int'
5205 |-DeclaratorList Declarators
5206 | `-SimpleDeclarator ListElement
5207 |   |-'b'
5208 |   `-ParametersAndQualifiers
5209 |     |-'(' OpenParen
5210 |     |-')' CloseParen
5211 |     `-'const'
5212 `-';'
5213 )txt",
5214        R"txt(
5215 SimpleDeclaration
5216 |-'int'
5217 |-DeclaratorList Declarators
5218 | `-SimpleDeclarator ListElement
5219 |   |-'c'
5220 |   `-ParametersAndQualifiers
5221 |     |-'(' OpenParen
5222 |     |-')' CloseParen
5223 |     `-'volatile'
5224 `-';'
5225 )txt",
5226        R"txt(
5227 SimpleDeclaration
5228 |-'int'
5229 |-DeclaratorList Declarators
5230 | `-SimpleDeclarator ListElement
5231 |   |-'d'
5232 |   `-ParametersAndQualifiers
5233 |     |-'(' OpenParen
5234 |     |-')' CloseParen
5235 |     |-'const'
5236 |     `-'volatile'
5237 `-';'
5238 )txt"}));
5239 }
5240 
5241 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
5242   if (!GetParam().isCXX11OrLater()) {
5243     return;
5244   }
5245   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5246       R"cpp(
5247 struct Test {
5248   [[int e() &;]]
5249 };
5250 )cpp",
5251       {R"txt(
5252 SimpleDeclaration
5253 |-'int'
5254 |-DeclaratorList Declarators
5255 | `-SimpleDeclarator ListElement
5256 |   |-'e'
5257 |   `-ParametersAndQualifiers
5258 |     |-'(' OpenParen
5259 |     |-')' CloseParen
5260 |     `-'&'
5261 `-';'
5262 )txt"}));
5263 }
5264 
5265 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
5266   if (!GetParam().isCXX11OrLater()) {
5267     return;
5268   }
5269   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5270       R"cpp(
5271 struct Test {
5272   [[int f() &&;]]
5273 };
5274 )cpp",
5275       {R"txt(
5276 SimpleDeclaration
5277 |-'int'
5278 |-DeclaratorList Declarators
5279 | `-SimpleDeclarator ListElement
5280 |   |-'f'
5281 |   `-ParametersAndQualifiers
5282 |     |-'(' OpenParen
5283 |     |-')' CloseParen
5284 |     `-'&&'
5285 `-';'
5286 )txt"}));
5287 }
5288 
5289 TEST_P(BuildSyntaxTreeTest, TrailingReturn) {
5290   if (!GetParam().isCXX11OrLater()) {
5291     return;
5292   }
5293   EXPECT_TRUE(treeDumpEqual(
5294       R"cpp(
5295 auto foo() -> int;
5296 )cpp",
5297       R"txt(
5298 TranslationUnit Detached
5299 `-SimpleDeclaration
5300   |-'auto'
5301   |-DeclaratorList Declarators
5302   | `-SimpleDeclarator ListElement
5303   |   |-'foo'
5304   |   `-ParametersAndQualifiers
5305   |     |-'(' OpenParen
5306   |     |-')' CloseParen
5307   |     `-TrailingReturnType TrailingReturn
5308   |       |-'->' ArrowToken
5309   |       `-'int'
5310   `-';'
5311 )txt"));
5312 }
5313 
5314 TEST_P(BuildSyntaxTreeTest, DynamicExceptionSpecification) {
5315   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
5316     return;
5317   }
5318   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5319       R"cpp(
5320 struct MyException1 {};
5321 struct MyException2 {};
5322 [[int a() throw();]]
5323 [[int b() throw(...);]]
5324 [[int c() throw(MyException1);]]
5325 [[int d() throw(MyException1, MyException2);]]
5326 )cpp",
5327       {R"txt(
5328 SimpleDeclaration
5329 |-'int'
5330 |-DeclaratorList Declarators
5331 | `-SimpleDeclarator ListElement
5332 |   |-'a'
5333 |   `-ParametersAndQualifiers
5334 |     |-'(' OpenParen
5335 |     |-')' CloseParen
5336 |     |-'throw'
5337 |     |-'('
5338 |     `-')'
5339 `-';'
5340 )txt",
5341        R"txt(
5342 SimpleDeclaration
5343 |-'int'
5344 |-DeclaratorList Declarators
5345 | `-SimpleDeclarator ListElement
5346 |   |-'b'
5347 |   `-ParametersAndQualifiers
5348 |     |-'(' OpenParen
5349 |     |-')' CloseParen
5350 |     |-'throw'
5351 |     |-'('
5352 |     |-'...'
5353 |     `-')'
5354 `-';'
5355 )txt",
5356        R"txt(
5357 SimpleDeclaration
5358 |-'int'
5359 |-DeclaratorList Declarators
5360 | `-SimpleDeclarator ListElement
5361 |   |-'c'
5362 |   `-ParametersAndQualifiers
5363 |     |-'(' OpenParen
5364 |     |-')' CloseParen
5365 |     |-'throw'
5366 |     |-'('
5367 |     |-'MyException1'
5368 |     `-')'
5369 `-';'
5370 )txt",
5371        R"txt(
5372 SimpleDeclaration
5373 |-'int'
5374 |-DeclaratorList Declarators
5375 | `-SimpleDeclarator ListElement
5376 |   |-'d'
5377 |   `-ParametersAndQualifiers
5378 |     |-'(' OpenParen
5379 |     |-')' CloseParen
5380 |     |-'throw'
5381 |     |-'('
5382 |     |-'MyException1'
5383 |     |-','
5384 |     |-'MyException2'
5385 |     `-')'
5386 `-';'
5387 )txt"}));
5388 }
5389 
5390 TEST_P(BuildSyntaxTreeTest, NoexceptExceptionSpecification) {
5391   if (!GetParam().isCXX11OrLater()) {
5392     return;
5393   }
5394   EXPECT_TRUE(treeDumpEqual(
5395       R"cpp(
5396 int a() noexcept;
5397 int b() noexcept(true);
5398 )cpp",
5399       R"txt(
5400 TranslationUnit Detached
5401 |-SimpleDeclaration
5402 | |-'int'
5403 | |-DeclaratorList Declarators
5404 | | `-SimpleDeclarator ListElement
5405 | |   |-'a'
5406 | |   `-ParametersAndQualifiers
5407 | |     |-'(' OpenParen
5408 | |     |-')' CloseParen
5409 | |     `-'noexcept'
5410 | `-';'
5411 `-SimpleDeclaration
5412   |-'int'
5413   |-DeclaratorList Declarators
5414   | `-SimpleDeclarator ListElement
5415   |   |-'b'
5416   |   `-ParametersAndQualifiers
5417   |     |-'(' OpenParen
5418   |     |-')' CloseParen
5419   |     |-'noexcept'
5420   |     |-'('
5421   |     |-BoolLiteralExpression
5422   |     | `-'true' LiteralToken
5423   |     `-')'
5424   `-';'
5425 )txt"));
5426 }
5427 
5428 TEST_P(BuildSyntaxTreeTest, DeclaratorsInParentheses) {
5429   EXPECT_TRUE(treeDumpEqual(
5430       R"cpp(
5431 int (a);
5432 int *(b);
5433 int (*c)(int);
5434 int *(d)(int);
5435 )cpp",
5436       R"txt(
5437 TranslationUnit Detached
5438 |-SimpleDeclaration
5439 | |-'int'
5440 | |-DeclaratorList Declarators
5441 | | `-SimpleDeclarator ListElement
5442 | |   `-ParenDeclarator
5443 | |     |-'(' OpenParen
5444 | |     |-'a'
5445 | |     `-')' CloseParen
5446 | `-';'
5447 |-SimpleDeclaration
5448 | |-'int'
5449 | |-DeclaratorList Declarators
5450 | | `-SimpleDeclarator ListElement
5451 | |   |-'*'
5452 | |   `-ParenDeclarator
5453 | |     |-'(' OpenParen
5454 | |     |-'b'
5455 | |     `-')' CloseParen
5456 | `-';'
5457 |-SimpleDeclaration
5458 | |-'int'
5459 | |-DeclaratorList Declarators
5460 | | `-SimpleDeclarator ListElement
5461 | |   |-ParenDeclarator
5462 | |   | |-'(' OpenParen
5463 | |   | |-'*'
5464 | |   | |-'c'
5465 | |   | `-')' CloseParen
5466 | |   `-ParametersAndQualifiers
5467 | |     |-'(' OpenParen
5468 | |     |-ParameterDeclarationList Parameters
5469 | |     | `-SimpleDeclaration ListElement
5470 | |     |   `-'int'
5471 | |     `-')' CloseParen
5472 | `-';'
5473 `-SimpleDeclaration
5474   |-'int'
5475   |-DeclaratorList Declarators
5476   | `-SimpleDeclarator ListElement
5477   |   |-'*'
5478   |   |-ParenDeclarator
5479   |   | |-'(' OpenParen
5480   |   | |-'d'
5481   |   | `-')' CloseParen
5482   |   `-ParametersAndQualifiers
5483   |     |-'(' OpenParen
5484   |     |-ParameterDeclarationList Parameters
5485   |     | `-SimpleDeclaration ListElement
5486   |     |   `-'int'
5487   |     `-')' CloseParen
5488   `-';'
5489 )txt"));
5490 }
5491 
5492 TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
5493   EXPECT_TRUE(treeDumpEqual(
5494       R"cpp(
5495 const int west = -1;
5496 int const east = 1;
5497 )cpp",
5498       R"txt(
5499 TranslationUnit Detached
5500 |-SimpleDeclaration
5501 | |-'const'
5502 | |-'int'
5503 | |-DeclaratorList Declarators
5504 | | `-SimpleDeclarator ListElement
5505 | |   |-'west'
5506 | |   |-'='
5507 | |   `-PrefixUnaryOperatorExpression
5508 | |     |-'-' OperatorToken
5509 | |     `-IntegerLiteralExpression Operand
5510 | |       `-'1' LiteralToken
5511 | `-';'
5512 `-SimpleDeclaration
5513   |-'int'
5514   |-'const'
5515   |-DeclaratorList Declarators
5516   | `-SimpleDeclarator ListElement
5517   |   |-'east'
5518   |   |-'='
5519   |   `-IntegerLiteralExpression
5520   |     `-'1' LiteralToken
5521   `-';'
5522 )txt"));
5523 }
5524 
5525 TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
5526   EXPECT_TRUE(treeDumpEqual(
5527       R"cpp(
5528 const int const universal = 0;
5529 )cpp",
5530       R"txt(
5531 TranslationUnit Detached
5532 `-SimpleDeclaration
5533   |-'const'
5534   |-'int'
5535   |-'const'
5536   |-DeclaratorList Declarators
5537   | `-SimpleDeclarator ListElement
5538   |   |-'universal'
5539   |   |-'='
5540   |   `-IntegerLiteralExpression
5541   |     `-'0' LiteralToken
5542   `-';'
5543 )txt"));
5544 }
5545 
5546 TEST_P(BuildSyntaxTreeTest,
5547        Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
5548   EXPECT_TRUE(treeDumpEqual(
5549       R"cpp(
5550 const int const *const *volatile b;
5551 )cpp",
5552       R"txt(
5553 TranslationUnit Detached
5554 `-SimpleDeclaration
5555   |-'const'
5556   |-'int'
5557   |-'const'
5558   |-DeclaratorList Declarators
5559   | `-SimpleDeclarator ListElement
5560   |   |-'*'
5561   |   |-'const'
5562   |   |-'*'
5563   |   |-'volatile'
5564   |   `-'b'
5565   `-';'
5566 )txt"));
5567 }
5568 
5569 TEST_P(BuildSyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
5570   if (!GetParam().isCXX11OrLater()) {
5571     return;
5572   }
5573   EXPECT_TRUE(treeDumpEqual(
5574       R"cpp(
5575 auto foo() -> auto(*)(int) -> double*;
5576 )cpp",
5577       R"txt(
5578 TranslationUnit Detached
5579 `-SimpleDeclaration
5580   |-'auto'
5581   |-DeclaratorList Declarators
5582   | `-SimpleDeclarator ListElement
5583   |   |-'foo'
5584   |   `-ParametersAndQualifiers
5585   |     |-'(' OpenParen
5586   |     |-')' CloseParen
5587   |     `-TrailingReturnType TrailingReturn
5588   |       |-'->' ArrowToken
5589   |       |-'auto'
5590   |       `-SimpleDeclarator Declarator
5591   |         |-ParenDeclarator
5592   |         | |-'(' OpenParen
5593   |         | |-'*'
5594   |         | `-')' CloseParen
5595   |         `-ParametersAndQualifiers
5596   |           |-'(' OpenParen
5597   |           |-ParameterDeclarationList Parameters
5598   |           | `-SimpleDeclaration ListElement
5599   |           |   `-'int'
5600   |           |-')' CloseParen
5601   |           `-TrailingReturnType TrailingReturn
5602   |             |-'->' ArrowToken
5603   |             |-'double'
5604   |             `-SimpleDeclarator Declarator
5605   |               `-'*'
5606   `-';'
5607 )txt"));
5608 }
5609 
5610 TEST_P(BuildSyntaxTreeTest, MemberPointers) {
5611   if (!GetParam().isCXX()) {
5612     return;
5613   }
5614   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5615       R"cpp(
5616 struct X {};
5617 [[int X::* a;]]
5618 [[const int X::* b;]]
5619 )cpp",
5620       {R"txt(
5621 SimpleDeclaration
5622 |-'int'
5623 |-DeclaratorList Declarators
5624 | `-SimpleDeclarator ListElement
5625 |   |-MemberPointer
5626 |   | |-'X'
5627 |   | |-'::'
5628 |   | `-'*'
5629 |   `-'a'
5630 `-';'
5631 )txt",
5632        R"txt(
5633 SimpleDeclaration
5634 |-'const'
5635 |-'int'
5636 |-DeclaratorList Declarators
5637 | `-SimpleDeclarator ListElement
5638 |   |-MemberPointer
5639 |   | |-'X'
5640 |   | |-'::'
5641 |   | `-'*'
5642 |   `-'b'
5643 `-';'
5644 )txt"}));
5645 }
5646 
5647 TEST_P(BuildSyntaxTreeTest, MemberFunctionPointer) {
5648   if (!GetParam().isCXX()) {
5649     return;
5650   }
5651   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5652       R"cpp(
5653 struct X {
5654   struct Y {};
5655 };
5656 [[void (X::*xp)();]]
5657 [[void (X::**xpp)(const int*);]]
5658 // FIXME: Generate the right syntax tree for this type,
5659 // i.e. create a syntax node for the outer member pointer
5660 [[void (X::Y::*xyp)(const int*, char);]]
5661 )cpp",
5662       {R"txt(
5663 SimpleDeclaration
5664 |-'void'
5665 |-DeclaratorList Declarators
5666 | `-SimpleDeclarator ListElement
5667 |   |-ParenDeclarator
5668 |   | |-'(' OpenParen
5669 |   | |-MemberPointer
5670 |   | | |-'X'
5671 |   | | |-'::'
5672 |   | | `-'*'
5673 |   | |-'xp'
5674 |   | `-')' CloseParen
5675 |   `-ParametersAndQualifiers
5676 |     |-'(' OpenParen
5677 |     `-')' CloseParen
5678 `-';'
5679 )txt",
5680        R"txt(
5681 SimpleDeclaration
5682 |-'void'
5683 |-DeclaratorList Declarators
5684 | `-SimpleDeclarator ListElement
5685 |   |-ParenDeclarator
5686 |   | |-'(' OpenParen
5687 |   | |-MemberPointer
5688 |   | | |-'X'
5689 |   | | |-'::'
5690 |   | | `-'*'
5691 |   | |-'*'
5692 |   | |-'xpp'
5693 |   | `-')' CloseParen
5694 |   `-ParametersAndQualifiers
5695 |     |-'(' OpenParen
5696 |     |-ParameterDeclarationList Parameters
5697 |     | `-SimpleDeclaration ListElement
5698 |     |   |-'const'
5699 |     |   |-'int'
5700 |     |   `-DeclaratorList Declarators
5701 |     |     `-SimpleDeclarator ListElement
5702 |     |       `-'*'
5703 |     `-')' CloseParen
5704 `-';'
5705 )txt",
5706        R"txt(
5707 SimpleDeclaration
5708 |-'void'
5709 |-DeclaratorList Declarators
5710 | `-SimpleDeclarator ListElement
5711 |   |-ParenDeclarator
5712 |   | |-'(' OpenParen
5713 |   | |-'X'
5714 |   | |-'::'
5715 |   | |-MemberPointer
5716 |   | | |-'Y'
5717 |   | | |-'::'
5718 |   | | `-'*'
5719 |   | |-'xyp'
5720 |   | `-')' CloseParen
5721 |   `-ParametersAndQualifiers
5722 |     |-'(' OpenParen
5723 |     |-ParameterDeclarationList Parameters
5724 |     | |-SimpleDeclaration ListElement
5725 |     | | |-'const'
5726 |     | | |-'int'
5727 |     | | `-DeclaratorList Declarators
5728 |     | |   `-SimpleDeclarator ListElement
5729 |     | |     `-'*'
5730 |     | |-',' ListDelimiter
5731 |     | `-SimpleDeclaration ListElement
5732 |     |   `-'char'
5733 |     `-')' CloseParen
5734 `-';'
5735 )txt"}));
5736 }
5737 
5738 TEST_P(BuildSyntaxTreeTest, ComplexDeclarator) {
5739   EXPECT_TRUE(treeDumpEqual(
5740       R"cpp(
5741 void x(char a, short (*b)(int));
5742 )cpp",
5743       R"txt(
5744 TranslationUnit Detached
5745 `-SimpleDeclaration
5746   |-'void'
5747   |-DeclaratorList Declarators
5748   | `-SimpleDeclarator ListElement
5749   |   |-'x'
5750   |   `-ParametersAndQualifiers
5751   |     |-'(' OpenParen
5752   |     |-ParameterDeclarationList Parameters
5753   |     | |-SimpleDeclaration ListElement
5754   |     | | |-'char'
5755   |     | | `-DeclaratorList Declarators
5756   |     | |   `-SimpleDeclarator ListElement
5757   |     | |     `-'a'
5758   |     | |-',' ListDelimiter
5759   |     | `-SimpleDeclaration ListElement
5760   |     |   |-'short'
5761   |     |   `-DeclaratorList Declarators
5762   |     |     `-SimpleDeclarator ListElement
5763   |     |       |-ParenDeclarator
5764   |     |       | |-'(' OpenParen
5765   |     |       | |-'*'
5766   |     |       | |-'b'
5767   |     |       | `-')' CloseParen
5768   |     |       `-ParametersAndQualifiers
5769   |     |         |-'(' OpenParen
5770   |     |         |-ParameterDeclarationList Parameters
5771   |     |         | `-SimpleDeclaration ListElement
5772   |     |         |   `-'int'
5773   |     |         `-')' CloseParen
5774   |     `-')' CloseParen
5775   `-';'
5776 )txt"));
5777 }
5778 
5779 TEST_P(BuildSyntaxTreeTest, ComplexDeclarator2) {
5780   EXPECT_TRUE(treeDumpEqual(
5781       R"cpp(
5782 void x(char a, short (*b)(int), long (**c)(long long));
5783 )cpp",
5784       R"txt(
5785 TranslationUnit Detached
5786 `-SimpleDeclaration
5787   |-'void'
5788   |-DeclaratorList Declarators
5789   | `-SimpleDeclarator ListElement
5790   |   |-'x'
5791   |   `-ParametersAndQualifiers
5792   |     |-'(' OpenParen
5793   |     |-ParameterDeclarationList Parameters
5794   |     | |-SimpleDeclaration ListElement
5795   |     | | |-'char'
5796   |     | | `-DeclaratorList Declarators
5797   |     | |   `-SimpleDeclarator ListElement
5798   |     | |     `-'a'
5799   |     | |-',' ListDelimiter
5800   |     | |-SimpleDeclaration ListElement
5801   |     | | |-'short'
5802   |     | | `-DeclaratorList Declarators
5803   |     | |   `-SimpleDeclarator ListElement
5804   |     | |     |-ParenDeclarator
5805   |     | |     | |-'(' OpenParen
5806   |     | |     | |-'*'
5807   |     | |     | |-'b'
5808   |     | |     | `-')' CloseParen
5809   |     | |     `-ParametersAndQualifiers
5810   |     | |       |-'(' OpenParen
5811   |     | |       |-ParameterDeclarationList Parameters
5812   |     | |       | `-SimpleDeclaration ListElement
5813   |     | |       |   `-'int'
5814   |     | |       `-')' CloseParen
5815   |     | |-',' ListDelimiter
5816   |     | `-SimpleDeclaration ListElement
5817   |     |   |-'long'
5818   |     |   `-DeclaratorList Declarators
5819   |     |     `-SimpleDeclarator ListElement
5820   |     |       |-ParenDeclarator
5821   |     |       | |-'(' OpenParen
5822   |     |       | |-'*'
5823   |     |       | |-'*'
5824   |     |       | |-'c'
5825   |     |       | `-')' CloseParen
5826   |     |       `-ParametersAndQualifiers
5827   |     |         |-'(' OpenParen
5828   |     |         |-ParameterDeclarationList Parameters
5829   |     |         | `-SimpleDeclaration ListElement
5830   |     |         |   |-'long'
5831   |     |         |   `-'long'
5832   |     |         `-')' CloseParen
5833   |     `-')' CloseParen
5834   `-';'
5835 )txt"));
5836 }
5837 
5838 } // namespace
5839