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