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, MultipleDeclaratorsGrouping) {
2737   EXPECT_TRUE(treeDumpEqual(
2738       R"cpp(
2739 int *a, b;
2740 int *c, d;
2741 )cpp",
2742       R"txt(
2743 TranslationUnit Detached
2744 |-SimpleDeclaration
2745 | |-'int'
2746 | |-SimpleDeclarator Declarator
2747 | | |-'*'
2748 | | `-'a'
2749 | |-','
2750 | |-SimpleDeclarator Declarator
2751 | | `-'b'
2752 | `-';'
2753 `-SimpleDeclaration
2754   |-'int'
2755   |-SimpleDeclarator Declarator
2756   | |-'*'
2757   | `-'c'
2758   |-','
2759   |-SimpleDeclarator Declarator
2760   | `-'d'
2761   `-';'
2762 )txt"));
2763 }
2764 
2765 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
2766   EXPECT_TRUE(treeDumpEqual(
2767       R"cpp(
2768 typedef int *a, b;
2769 )cpp",
2770       R"txt(
2771 TranslationUnit Detached
2772 `-SimpleDeclaration
2773   |-'typedef'
2774   |-'int'
2775   |-SimpleDeclarator Declarator
2776   | |-'*'
2777   | `-'a'
2778   |-','
2779   |-SimpleDeclarator Declarator
2780   | `-'b'
2781   `-';'
2782 )txt"));
2783 }
2784 
2785 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
2786   EXPECT_TRUE(treeDumpEqual(
2787       R"cpp(
2788 void foo() {
2789   int *a, b;
2790   typedef int *ta, tb;
2791 }
2792 )cpp",
2793       R"txt(
2794 TranslationUnit Detached
2795 `-SimpleDeclaration
2796   |-'void'
2797   |-SimpleDeclarator Declarator
2798   | |-'foo'
2799   | `-ParametersAndQualifiers
2800   |   |-'(' OpenParen
2801   |   `-')' CloseParen
2802   `-CompoundStatement
2803     |-'{' OpenParen
2804     |-DeclarationStatement Statement
2805     | |-SimpleDeclaration
2806     | | |-'int'
2807     | | |-SimpleDeclarator Declarator
2808     | | | |-'*'
2809     | | | `-'a'
2810     | | |-','
2811     | | `-SimpleDeclarator Declarator
2812     | |   `-'b'
2813     | `-';'
2814     |-DeclarationStatement Statement
2815     | |-SimpleDeclaration
2816     | | |-'typedef'
2817     | | |-'int'
2818     | | |-SimpleDeclarator Declarator
2819     | | | |-'*'
2820     | | | `-'ta'
2821     | | |-','
2822     | | `-SimpleDeclarator Declarator
2823     | |   `-'tb'
2824     | `-';'
2825     `-'}' CloseParen
2826 )txt"));
2827 }
2828 
2829 TEST_P(SyntaxTreeTest, SizeTTypedef) {
2830   if (!GetParam().isCXX11OrLater()) {
2831     return;
2832   }
2833   EXPECT_TRUE(treeDumpEqual(
2834       R"cpp(
2835 typedef decltype(sizeof(void *)) size_t;
2836     )cpp",
2837       R"txt(
2838 TranslationUnit Detached
2839 `-SimpleDeclaration
2840   |-'typedef'
2841   |-'decltype'
2842   |-'('
2843   |-UnknownExpression
2844   | |-'sizeof'
2845   | |-'('
2846   | |-'void'
2847   | |-'*'
2848   | `-')'
2849   |-')'
2850   |-SimpleDeclarator Declarator
2851   | `-'size_t'
2852   `-';'
2853 )txt"));
2854 }
2855 
2856 TEST_P(SyntaxTreeTest, Namespace_Nested) {
2857   if (!GetParam().isCXX()) {
2858     return;
2859   }
2860   EXPECT_TRUE(treeDumpEqual(
2861       R"cpp(
2862 namespace a { namespace b {} }
2863 )cpp",
2864       R"txt(
2865 TranslationUnit Detached
2866 `-NamespaceDefinition
2867   |-'namespace'
2868   |-'a'
2869   |-'{'
2870   |-NamespaceDefinition
2871   | |-'namespace'
2872   | |-'b'
2873   | |-'{'
2874   | `-'}'
2875   `-'}'
2876 )txt"));
2877 }
2878 
2879 TEST_P(SyntaxTreeTest, Namespace_NestedDefinition) {
2880   if (!GetParam().isCXX17OrLater()) {
2881     return;
2882   }
2883   EXPECT_TRUE(treeDumpEqual(
2884       R"cpp(
2885 namespace a::b {}
2886 )cpp",
2887       R"txt(
2888 TranslationUnit Detached
2889 `-NamespaceDefinition
2890   |-'namespace'
2891   |-'a'
2892   |-'::'
2893   |-'b'
2894   |-'{'
2895   `-'}'
2896 )txt"));
2897 }
2898 
2899 TEST_P(SyntaxTreeTest, Namespace_Unnamed) {
2900   if (!GetParam().isCXX()) {
2901     return;
2902   }
2903   EXPECT_TRUE(treeDumpEqual(
2904       R"cpp(
2905 namespace {}
2906 )cpp",
2907       R"txt(
2908 TranslationUnit Detached
2909 `-NamespaceDefinition
2910   |-'namespace'
2911   |-'{'
2912   `-'}'
2913 )txt"));
2914 }
2915 
2916 TEST_P(SyntaxTreeTest, Namespace_Alias) {
2917   if (!GetParam().isCXX()) {
2918     return;
2919   }
2920   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2921       R"cpp(
2922 namespace a {}
2923 [[namespace foo = a;]]
2924 )cpp",
2925       {R"txt(
2926 NamespaceAliasDefinition
2927 |-'namespace'
2928 |-'foo'
2929 |-'='
2930 |-'a'
2931 `-';'
2932 )txt"}));
2933 }
2934 
2935 TEST_P(SyntaxTreeTest, UsingDirective) {
2936   if (!GetParam().isCXX()) {
2937     return;
2938   }
2939   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2940       R"cpp(
2941 namespace ns {}
2942 [[using namespace ::ns;]]
2943 )cpp",
2944       {R"txt(
2945 UsingNamespaceDirective
2946 |-'using'
2947 |-'namespace'
2948 |-NestedNameSpecifier
2949 | `-'::' ListDelimiter
2950 |-'ns'
2951 `-';'
2952 )txt"}));
2953 }
2954 
2955 TEST_P(SyntaxTreeTest, UsingDeclaration_Namespace) {
2956   if (!GetParam().isCXX()) {
2957     return;
2958   }
2959   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2960       R"cpp(
2961 namespace ns { int a; }
2962 [[using ns::a;]]
2963 )cpp",
2964       {R"txt(
2965 UsingDeclaration
2966 |-'using'
2967 |-NestedNameSpecifier
2968 | |-IdentifierNameSpecifier ListElement
2969 | | `-'ns'
2970 | `-'::' ListDelimiter
2971 |-'a'
2972 `-';'
2973 )txt"}));
2974 }
2975 
2976 TEST_P(SyntaxTreeTest, UsingDeclaration_ClassMember) {
2977   if (!GetParam().isCXX()) {
2978     return;
2979   }
2980   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2981       R"cpp(
2982 template <class T> struct X {
2983   [[using T::foo;]]
2984   [[using typename T::bar;]]
2985 };
2986 )cpp",
2987       {R"txt(
2988 UsingDeclaration
2989 |-'using'
2990 |-NestedNameSpecifier
2991 | |-IdentifierNameSpecifier ListElement
2992 | | `-'T'
2993 | `-'::' ListDelimiter
2994 |-'foo'
2995 `-';'
2996 )txt",
2997        R"txt(
2998 UsingDeclaration
2999 |-'using'
3000 |-'typename'
3001 |-NestedNameSpecifier
3002 | |-IdentifierNameSpecifier ListElement
3003 | | `-'T'
3004 | `-'::' ListDelimiter
3005 |-'bar'
3006 `-';'
3007 )txt"}));
3008 }
3009 
3010 TEST_P(SyntaxTreeTest, UsingTypeAlias) {
3011   if (!GetParam().isCXX11OrLater()) {
3012     return;
3013   }
3014   EXPECT_TRUE(treeDumpEqual(
3015       R"cpp(
3016 using type = int;
3017 )cpp",
3018       R"txt(
3019 TranslationUnit Detached
3020 `-TypeAliasDeclaration
3021   |-'using'
3022   |-'type'
3023   |-'='
3024   |-'int'
3025   `-';'
3026 )txt"));
3027 }
3028 
3029 TEST_P(SyntaxTreeTest, FreeStandingClass_ForwardDeclaration) {
3030   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3031       R"cpp(
3032 [[struct X;]]
3033 [[struct Y *y1;]]
3034 )cpp",
3035       {R"txt(
3036 SimpleDeclaration
3037 |-'struct'
3038 |-'X'
3039 `-';'
3040 )txt",
3041        R"txt(
3042 SimpleDeclaration
3043 |-'struct'
3044 |-'Y'
3045 |-SimpleDeclarator Declarator
3046 | |-'*'
3047 | `-'y1'
3048 `-';'
3049 )txt"}));
3050 }
3051 
3052 TEST_P(SyntaxTreeTest, FreeStandingClasses_Definition) {
3053   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3054       R"cpp(
3055 [[struct X {};]]
3056 [[struct Y {} *y2;]]
3057 [[struct {} *a1;]]
3058 )cpp",
3059       {R"txt(
3060 SimpleDeclaration
3061 |-'struct'
3062 |-'X'
3063 |-'{'
3064 |-'}'
3065 `-';'
3066 )txt",
3067        R"txt(
3068 SimpleDeclaration
3069 |-'struct'
3070 |-'Y'
3071 |-'{'
3072 |-'}'
3073 |-SimpleDeclarator Declarator
3074 | |-'*'
3075 | `-'y2'
3076 `-';'
3077 )txt",
3078        R"txt(
3079 SimpleDeclaration
3080 |-'struct'
3081 |-'{'
3082 |-'}'
3083 |-SimpleDeclarator Declarator
3084 | |-'*'
3085 | `-'a1'
3086 `-';'
3087 )txt"}));
3088 }
3089 
3090 TEST_P(SyntaxTreeTest, StaticMemberFunction) {
3091   if (!GetParam().isCXX11OrLater()) {
3092     return;
3093   }
3094   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3095       R"cpp(
3096 struct S {
3097   [[static void f(){}]]
3098 };
3099 )cpp",
3100       {R"txt(
3101 SimpleDeclaration
3102 |-'static'
3103 |-'void'
3104 |-SimpleDeclarator Declarator
3105 | |-'f'
3106 | `-ParametersAndQualifiers
3107 |   |-'(' OpenParen
3108 |   `-')' CloseParen
3109 `-CompoundStatement
3110   |-'{' OpenParen
3111   `-'}' CloseParen
3112 )txt"}));
3113 }
3114 
3115 TEST_P(SyntaxTreeTest, OutOfLineMemberFunctionDefinition) {
3116   if (!GetParam().isCXX11OrLater()) {
3117     return;
3118   }
3119   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3120       R"cpp(
3121 struct S {
3122   void f();
3123 };
3124 [[void S::f(){}]]
3125 )cpp",
3126       {R"txt(
3127 SimpleDeclaration
3128 |-'void'
3129 |-SimpleDeclarator Declarator
3130 | |-NestedNameSpecifier
3131 | | |-IdentifierNameSpecifier ListElement
3132 | | | `-'S'
3133 | | `-'::' ListDelimiter
3134 | |-'f'
3135 | `-ParametersAndQualifiers
3136 |   |-'(' OpenParen
3137 |   `-')' CloseParen
3138 `-CompoundStatement
3139   |-'{' OpenParen
3140   `-'}' CloseParen
3141 )txt"}));
3142 }
3143 
3144 TEST_P(SyntaxTreeTest, ConversionMemberFunction) {
3145   if (!GetParam().isCXX()) {
3146     return;
3147   }
3148   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3149       R"cpp(
3150 struct X {
3151   [[operator int();]]
3152 };
3153 )cpp",
3154       {R"txt(
3155 SimpleDeclaration
3156 |-SimpleDeclarator Declarator
3157 | |-'operator'
3158 | |-'int'
3159 | `-ParametersAndQualifiers
3160 |   |-'(' OpenParen
3161 |   `-')' CloseParen
3162 `-';'
3163 )txt"}));
3164 }
3165 
3166 TEST_P(SyntaxTreeTest, LiteralOperatorDeclaration) {
3167   if (!GetParam().isCXX11OrLater()) {
3168     return;
3169   }
3170   EXPECT_TRUE(treeDumpEqual(
3171       R"cpp(
3172 unsigned operator "" _c(char);
3173     )cpp",
3174       R"txt(
3175 TranslationUnit Detached
3176 `-SimpleDeclaration
3177   |-'unsigned'
3178   |-SimpleDeclarator Declarator
3179   | |-'operator'
3180   | |-'""'
3181   | |-'_c'
3182   | `-ParametersAndQualifiers
3183   |   |-'(' OpenParen
3184   |   |-ParameterDeclarationList Parameters
3185   |   | `-SimpleDeclaration ListElement
3186   |   |   `-'char'
3187   |   `-')' CloseParen
3188   `-';'
3189 )txt"));
3190 }
3191 
3192 TEST_P(SyntaxTreeTest, NumericLiteralOperatorTemplateDeclaration) {
3193   if (!GetParam().isCXX11OrLater()) {
3194     return;
3195   }
3196   EXPECT_TRUE(treeDumpEqual(
3197       R"cpp(
3198 template <char...>
3199 unsigned operator "" _t();
3200     )cpp",
3201       R"txt(
3202 TranslationUnit Detached
3203 `-TemplateDeclaration Declaration
3204   |-'template' IntroducerKeyword
3205   |-'<'
3206   |-SimpleDeclaration
3207   | `-'char'
3208   |-'...'
3209   |-'>'
3210   `-SimpleDeclaration
3211     |-'unsigned'
3212     |-SimpleDeclarator Declarator
3213     | |-'operator'
3214     | |-'""'
3215     | |-'_t'
3216     | `-ParametersAndQualifiers
3217     |   |-'(' OpenParen
3218     |   `-')' CloseParen
3219     `-';'
3220 )txt"));
3221 }
3222 
3223 TEST_P(SyntaxTreeTest, OverloadedOperatorDeclaration) {
3224   if (!GetParam().isCXX()) {
3225     return;
3226   }
3227   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3228       R"cpp(
3229 struct X {
3230   [[X& operator=(const X&);]]
3231 };
3232 )cpp",
3233       {R"txt(
3234 SimpleDeclaration
3235 |-'X'
3236 |-SimpleDeclarator Declarator
3237 | |-'&'
3238 | |-'operator'
3239 | |-'='
3240 | `-ParametersAndQualifiers
3241 |   |-'(' OpenParen
3242 |   |-ParameterDeclarationList Parameters
3243 |   | `-SimpleDeclaration ListElement
3244 |   |   |-'const'
3245 |   |   |-'X'
3246 |   |   `-SimpleDeclarator Declarator
3247 |   |     `-'&'
3248 |   `-')' CloseParen
3249 `-';'
3250 )txt"}));
3251 }
3252 
3253 TEST_P(SyntaxTreeTest, OverloadedOperatorFriendDeclaration) {
3254   if (!GetParam().isCXX()) {
3255     return;
3256   }
3257   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3258       R"cpp(
3259 struct X {
3260   [[friend X operator+(X, const X&);]]
3261 };
3262 )cpp",
3263       {R"txt(
3264 UnknownDeclaration
3265 `-SimpleDeclaration
3266   |-'friend'
3267   |-'X'
3268   |-SimpleDeclarator Declarator
3269   | |-'operator'
3270   | |-'+'
3271   | `-ParametersAndQualifiers
3272   |   |-'(' OpenParen
3273   |   |-ParameterDeclarationList Parameters
3274   |   | |-SimpleDeclaration ListElement
3275   |   | | `-'X'
3276   |   | |-',' ListDelimiter
3277   |   | `-SimpleDeclaration ListElement
3278   |   |   |-'const'
3279   |   |   |-'X'
3280   |   |   `-SimpleDeclarator Declarator
3281   |   |     `-'&'
3282   |   `-')' CloseParen
3283   `-';'
3284 )txt"}));
3285 }
3286 
3287 TEST_P(SyntaxTreeTest, ClassTemplateDeclaration) {
3288   if (!GetParam().isCXX()) {
3289     return;
3290   }
3291   EXPECT_TRUE(treeDumpEqual(
3292       R"cpp(
3293 template<typename T>
3294 struct ST {};
3295 )cpp",
3296       R"txt(
3297 TranslationUnit Detached
3298 `-TemplateDeclaration Declaration
3299   |-'template' IntroducerKeyword
3300   |-'<'
3301   |-UnknownDeclaration
3302   | |-'typename'
3303   | `-'T'
3304   |-'>'
3305   `-SimpleDeclaration
3306     |-'struct'
3307     |-'ST'
3308     |-'{'
3309     |-'}'
3310     `-';'
3311 )txt"));
3312 }
3313 
3314 TEST_P(SyntaxTreeTest, FunctionTemplateDeclaration) {
3315   if (!GetParam().isCXX()) {
3316     return;
3317   }
3318   EXPECT_TRUE(treeDumpEqual(
3319       R"cpp(
3320 template<typename T>
3321 T f();
3322 )cpp",
3323       R"txt(
3324 TranslationUnit Detached
3325 `-TemplateDeclaration Declaration
3326   |-'template' IntroducerKeyword
3327   |-'<'
3328   |-UnknownDeclaration
3329   | |-'typename'
3330   | `-'T'
3331   |-'>'
3332   `-SimpleDeclaration
3333     |-'T'
3334     |-SimpleDeclarator Declarator
3335     | |-'f'
3336     | `-ParametersAndQualifiers
3337     |   |-'(' OpenParen
3338     |   `-')' CloseParen
3339     `-';'
3340 )txt"));
3341 }
3342 
3343 TEST_P(SyntaxTreeTest, VariableTemplateDeclaration) {
3344   if (!GetParam().isCXX14OrLater()) {
3345     return;
3346   }
3347   EXPECT_TRUE(treeDumpEqual(
3348       R"cpp(
3349 template <class T> T var = 10;
3350 )cpp",
3351       R"txt(
3352 TranslationUnit Detached
3353 `-TemplateDeclaration Declaration
3354   |-'template' IntroducerKeyword
3355   |-'<'
3356   |-UnknownDeclaration
3357   | |-'class'
3358   | `-'T'
3359   |-'>'
3360   `-SimpleDeclaration
3361     |-'T'
3362     |-SimpleDeclarator Declarator
3363     | |-'var'
3364     | |-'='
3365     | `-IntegerLiteralExpression
3366     |   `-'10' LiteralToken
3367     `-';'
3368 )txt"));
3369 }
3370 
3371 TEST_P(SyntaxTreeTest, StaticMemberFunctionTemplate) {
3372   if (!GetParam().isCXX()) {
3373     return;
3374   }
3375   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3376       R"cpp(
3377 struct S {
3378   [[template<typename U>
3379   static U f();]]
3380 };
3381 )cpp",
3382       {R"txt(
3383 TemplateDeclaration Declaration
3384 |-'template' IntroducerKeyword
3385 |-'<'
3386 |-UnknownDeclaration
3387 | |-'typename'
3388 | `-'U'
3389 |-'>'
3390 `-SimpleDeclaration
3391   |-'static'
3392   |-'U'
3393   |-SimpleDeclarator Declarator
3394   | |-'f'
3395   | `-ParametersAndQualifiers
3396   |   |-'(' OpenParen
3397   |   `-')' CloseParen
3398   `-';'
3399 )txt"}));
3400 }
3401 
3402 TEST_P(SyntaxTreeTest, NestedTemplates) {
3403   if (!GetParam().isCXX()) {
3404     return;
3405   }
3406   EXPECT_TRUE(treeDumpEqual(
3407       R"cpp(
3408 template <class T>
3409 struct X {
3410   template <class U>
3411   U foo();
3412 };
3413 )cpp",
3414       R"txt(
3415 TranslationUnit Detached
3416 `-TemplateDeclaration Declaration
3417   |-'template' IntroducerKeyword
3418   |-'<'
3419   |-UnknownDeclaration
3420   | |-'class'
3421   | `-'T'
3422   |-'>'
3423   `-SimpleDeclaration
3424     |-'struct'
3425     |-'X'
3426     |-'{'
3427     |-TemplateDeclaration Declaration
3428     | |-'template' IntroducerKeyword
3429     | |-'<'
3430     | |-UnknownDeclaration
3431     | | |-'class'
3432     | | `-'U'
3433     | |-'>'
3434     | `-SimpleDeclaration
3435     |   |-'U'
3436     |   |-SimpleDeclarator Declarator
3437     |   | |-'foo'
3438     |   | `-ParametersAndQualifiers
3439     |   |   |-'(' OpenParen
3440     |   |   `-')' CloseParen
3441     |   `-';'
3442     |-'}'
3443     `-';'
3444 )txt"));
3445 }
3446 
3447 TEST_P(SyntaxTreeTest, NestedTemplatesInNamespace) {
3448   if (!GetParam().isCXX()) {
3449     return;
3450   }
3451   EXPECT_TRUE(treeDumpEqual(
3452       R"cpp(
3453 namespace n {
3454   template<typename T>
3455   struct ST {
3456     template<typename U>
3457     static U f();
3458   };
3459 }
3460 )cpp",
3461       R"txt(
3462 TranslationUnit Detached
3463 `-NamespaceDefinition
3464   |-'namespace'
3465   |-'n'
3466   |-'{'
3467   |-TemplateDeclaration Declaration
3468   | |-'template' IntroducerKeyword
3469   | |-'<'
3470   | |-UnknownDeclaration
3471   | | |-'typename'
3472   | | `-'T'
3473   | |-'>'
3474   | `-SimpleDeclaration
3475   |   |-'struct'
3476   |   |-'ST'
3477   |   |-'{'
3478   |   |-TemplateDeclaration Declaration
3479   |   | |-'template' IntroducerKeyword
3480   |   | |-'<'
3481   |   | |-UnknownDeclaration
3482   |   | | |-'typename'
3483   |   | | `-'U'
3484   |   | |-'>'
3485   |   | `-SimpleDeclaration
3486   |   |   |-'static'
3487   |   |   |-'U'
3488   |   |   |-SimpleDeclarator Declarator
3489   |   |   | |-'f'
3490   |   |   | `-ParametersAndQualifiers
3491   |   |   |   |-'(' OpenParen
3492   |   |   |   `-')' CloseParen
3493   |   |   `-';'
3494   |   |-'}'
3495   |   `-';'
3496   `-'}'
3497 )txt"));
3498 }
3499 
3500 TEST_P(SyntaxTreeTest, ClassTemplate_MemberClassDefinition) {
3501   if (!GetParam().isCXX()) {
3502     return;
3503   }
3504   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3505       R"cpp(
3506 template <class T> struct X { struct Y; };
3507 [[template <class T> struct X<T>::Y {};]]
3508 )cpp",
3509       {R"txt(
3510 TemplateDeclaration Declaration
3511 |-'template' IntroducerKeyword
3512 |-'<'
3513 |-UnknownDeclaration
3514 | |-'class'
3515 | `-'T'
3516 |-'>'
3517 `-SimpleDeclaration
3518   |-'struct'
3519   |-NestedNameSpecifier
3520   | |-SimpleTemplateNameSpecifier ListElement
3521   | | |-'X'
3522   | | |-'<'
3523   | | |-'T'
3524   | | `-'>'
3525   | `-'::' ListDelimiter
3526   |-'Y'
3527   |-'{'
3528   |-'}'
3529   `-';'
3530 )txt"}));
3531 }
3532 
3533 TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Definition) {
3534   if (!GetParam().isCXX()) {
3535     return;
3536   }
3537   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3538       R"cpp(
3539 template <class T> struct X {};
3540 [[template struct X<double>;]]
3541 )cpp",
3542       {R"txt(
3543 ExplicitTemplateInstantiation
3544 |-'template' IntroducerKeyword
3545 `-SimpleDeclaration Declaration
3546   |-'struct'
3547   |-'X'
3548   |-'<'
3549   |-'double'
3550   |-'>'
3551   `-';'
3552 )txt"}));
3553 }
3554 
3555 TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Declaration) {
3556   if (!GetParam().isCXX()) {
3557     return;
3558   }
3559   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3560       R"cpp(
3561 template <class T> struct X {};
3562 [[extern template struct X<float>;]]
3563 )cpp",
3564       {R"txt(
3565 ExplicitTemplateInstantiation
3566 |-'extern' ExternKeyword
3567 |-'template' IntroducerKeyword
3568 `-SimpleDeclaration Declaration
3569   |-'struct'
3570   |-'X'
3571   |-'<'
3572   |-'float'
3573   |-'>'
3574   `-';'
3575 )txt"}));
3576 }
3577 
3578 TEST_P(SyntaxTreeTest, ClassTemplateSpecialization_Partial) {
3579   if (!GetParam().isCXX()) {
3580     return;
3581   }
3582   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3583       R"cpp(
3584 template <class T> struct X {};
3585 [[template <class T> struct X<T*> {};]]
3586 )cpp",
3587       {R"txt(
3588 TemplateDeclaration Declaration
3589 |-'template' IntroducerKeyword
3590 |-'<'
3591 |-UnknownDeclaration
3592 | |-'class'
3593 | `-'T'
3594 |-'>'
3595 `-SimpleDeclaration
3596   |-'struct'
3597   |-'X'
3598   |-'<'
3599   |-'T'
3600   |-'*'
3601   |-'>'
3602   |-'{'
3603   |-'}'
3604   `-';'
3605 )txt"}));
3606 }
3607 
3608 TEST_P(SyntaxTreeTest, ClassTemplateSpecialization_Full) {
3609   if (!GetParam().isCXX()) {
3610     return;
3611   }
3612   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3613       R"cpp(
3614 template <class T> struct X {};
3615 [[template <> struct X<int> {};]]
3616 )cpp",
3617       {R"txt(
3618 TemplateDeclaration Declaration
3619 |-'template' IntroducerKeyword
3620 |-'<'
3621 |-'>'
3622 `-SimpleDeclaration
3623   |-'struct'
3624   |-'X'
3625   |-'<'
3626   |-'int'
3627   |-'>'
3628   |-'{'
3629   |-'}'
3630   `-';'
3631 )txt"}));
3632 }
3633 
3634 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
3635   EXPECT_TRUE(treeDumpEqual(
3636       R"cpp(
3637 ;
3638 )cpp",
3639       R"txt(
3640 TranslationUnit Detached
3641 `-EmptyDeclaration
3642   `-';'
3643 )txt"));
3644 }
3645 
3646 TEST_P(SyntaxTreeTest, StaticAssert) {
3647   if (!GetParam().isCXX11OrLater()) {
3648     return;
3649   }
3650   EXPECT_TRUE(treeDumpEqual(
3651       R"cpp(
3652 static_assert(true, "message");
3653 )cpp",
3654       R"txt(
3655 TranslationUnit Detached
3656 `-StaticAssertDeclaration
3657   |-'static_assert'
3658   |-'('
3659   |-BoolLiteralExpression Condition
3660   | `-'true' LiteralToken
3661   |-','
3662   |-StringLiteralExpression Message
3663   | `-'"message"' LiteralToken
3664   |-')'
3665   `-';'
3666 )txt"));
3667 }
3668 
3669 TEST_P(SyntaxTreeTest, StaticAssert_WithoutMessage) {
3670   if (!GetParam().isCXX17OrLater()) {
3671     return;
3672   }
3673   EXPECT_TRUE(treeDumpEqual(
3674       R"cpp(
3675 static_assert(true);
3676 )cpp",
3677       R"txt(
3678 TranslationUnit Detached
3679 `-StaticAssertDeclaration
3680   |-'static_assert'
3681   |-'('
3682   |-BoolLiteralExpression Condition
3683   | `-'true' LiteralToken
3684   |-')'
3685   `-';'
3686 )txt"));
3687 }
3688 
3689 TEST_P(SyntaxTreeTest, ExternC) {
3690   if (!GetParam().isCXX()) {
3691     return;
3692   }
3693   EXPECT_TRUE(treeDumpEqual(
3694       R"cpp(
3695 extern "C" int a;
3696 extern "C" { int b; int c; }
3697 )cpp",
3698       R"txt(
3699 TranslationUnit Detached
3700 |-LinkageSpecificationDeclaration
3701 | |-'extern'
3702 | |-'"C"'
3703 | `-SimpleDeclaration
3704 |   |-'int'
3705 |   |-SimpleDeclarator Declarator
3706 |   | `-'a'
3707 |   `-';'
3708 `-LinkageSpecificationDeclaration
3709   |-'extern'
3710   |-'"C"'
3711   |-'{'
3712   |-SimpleDeclaration
3713   | |-'int'
3714   | |-SimpleDeclarator Declarator
3715   | | `-'b'
3716   | `-';'
3717   |-SimpleDeclaration
3718   | |-'int'
3719   | |-SimpleDeclarator Declarator
3720   | | `-'c'
3721   | `-';'
3722   `-'}'
3723 )txt"));
3724 }
3725 
3726 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
3727   // Some nodes are non-modifiable, they are marked with 'I:'.
3728   EXPECT_TRUE(treeDumpEqual(
3729       R"cpp(
3730 #define HALF_IF if (1+
3731 #define HALF_IF_2 1) {}
3732 void test() {
3733   HALF_IF HALF_IF_2 else {}
3734 })cpp",
3735       R"txt(
3736 TranslationUnit Detached
3737 `-SimpleDeclaration
3738   |-'void'
3739   |-SimpleDeclarator Declarator
3740   | |-'test'
3741   | `-ParametersAndQualifiers
3742   |   |-'(' OpenParen
3743   |   `-')' CloseParen
3744   `-CompoundStatement
3745     |-'{' OpenParen
3746     |-IfStatement Statement
3747     | |-'if' IntroducerKeyword unmodifiable
3748     | |-'(' unmodifiable
3749     | |-BinaryOperatorExpression unmodifiable
3750     | | |-IntegerLiteralExpression LeftHandSide unmodifiable
3751     | | | `-'1' LiteralToken unmodifiable
3752     | | |-'+' OperatorToken unmodifiable
3753     | | `-IntegerLiteralExpression RightHandSide unmodifiable
3754     | |   `-'1' LiteralToken unmodifiable
3755     | |-')' unmodifiable
3756     | |-CompoundStatement ThenStatement unmodifiable
3757     | | |-'{' OpenParen unmodifiable
3758     | | `-'}' CloseParen unmodifiable
3759     | |-'else' ElseKeyword
3760     | `-CompoundStatement ElseStatement
3761     |   |-'{' OpenParen
3762     |   `-'}' CloseParen
3763     `-'}' CloseParen
3764 )txt"));
3765 }
3766 
3767 TEST_P(SyntaxTreeTest, ModifiableNodes) {
3768   // All nodes can be mutated.
3769   EXPECT_TRUE(treeDumpEqual(
3770       R"cpp(
3771 #define OPEN {
3772 #define CLOSE }
3773 
3774 void test() {
3775   OPEN
3776     1;
3777   CLOSE
3778 
3779   OPEN
3780     2;
3781   }
3782 }
3783 )cpp",
3784       R"txt(
3785 TranslationUnit Detached
3786 `-SimpleDeclaration
3787   |-'void'
3788   |-SimpleDeclarator Declarator
3789   | |-'test'
3790   | `-ParametersAndQualifiers
3791   |   |-'(' OpenParen
3792   |   `-')' CloseParen
3793   `-CompoundStatement
3794     |-'{' OpenParen
3795     |-CompoundStatement Statement
3796     | |-'{' OpenParen
3797     | |-ExpressionStatement Statement
3798     | | |-IntegerLiteralExpression Expression
3799     | | | `-'1' LiteralToken
3800     | | `-';'
3801     | `-'}' CloseParen
3802     |-CompoundStatement Statement
3803     | |-'{' OpenParen
3804     | |-ExpressionStatement Statement
3805     | | |-IntegerLiteralExpression Expression
3806     | | | `-'2' LiteralToken
3807     | | `-';'
3808     | `-'}' CloseParen
3809     `-'}' CloseParen
3810 )txt"));
3811 }
3812 
3813 TEST_P(SyntaxTreeTest, InitDeclarator_Equal) {
3814   if (!GetParam().isCXX()) {
3815     return;
3816   }
3817   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3818       R"cpp(
3819 struct S { S(int);};
3820 void test() {
3821   [[S s = 1]];
3822 }
3823 )cpp",
3824       {R"txt(
3825 SimpleDeclaration
3826 |-'S'
3827 `-SimpleDeclarator Declarator
3828   |-'s'
3829   |-'='
3830   `-IntegerLiteralExpression
3831     `-'1' LiteralToken
3832 )txt"}));
3833 }
3834 
3835 TEST_P(SyntaxTreeTest, InitDeclarator_Brace) {
3836   if (!GetParam().isCXX11OrLater()) {
3837     return;
3838   }
3839   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3840       R"cpp(
3841 struct S {
3842   S();
3843   S(int);
3844   S(int, float);
3845 };
3846 void test(){
3847   // FIXME: 's...' is a declarator and '{...}' is initializer
3848   [[S s0{}]];
3849   [[S s1{1}]];
3850   [[S s2{1, 2.}]];
3851 }
3852 )cpp",
3853       {R"txt(
3854 SimpleDeclaration
3855 |-'S'
3856 `-SimpleDeclarator Declarator
3857   `-UnknownExpression
3858     |-'s0'
3859     |-'{'
3860     `-'}'
3861   )txt",
3862        R"txt(
3863 SimpleDeclaration
3864 |-'S'
3865 `-SimpleDeclarator Declarator
3866   `-UnknownExpression
3867     |-'s1'
3868     |-'{'
3869     |-IntegerLiteralExpression
3870     | `-'1' LiteralToken
3871     `-'}'
3872   )txt",
3873        R"txt(
3874 SimpleDeclaration
3875 |-'S'
3876 `-SimpleDeclarator Declarator
3877   `-UnknownExpression
3878     |-'s2'
3879     |-'{'
3880     |-IntegerLiteralExpression
3881     | `-'1' LiteralToken
3882     |-','
3883     |-FloatingLiteralExpression
3884     | `-'2.' LiteralToken
3885     `-'}'
3886 )txt"}));
3887 }
3888 
3889 TEST_P(SyntaxTreeTest, InitDeclarator_EqualBrace) {
3890   if (!GetParam().isCXX11OrLater()) {
3891     return;
3892   }
3893   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3894       R"cpp(
3895 struct S {
3896   S();
3897   S(int);
3898   S(int, float);
3899 };
3900 void test() {
3901   // FIXME: '= {...}' is initializer
3902   [[S s0 = {}]];
3903   [[S s1 = {1}]];
3904   [[S s2 = {1, 2.}]];
3905 }
3906 )cpp",
3907       {R"txt(
3908 SimpleDeclaration
3909 |-'S'
3910 `-SimpleDeclarator Declarator
3911   |-'s0'
3912   |-'='
3913   `-UnknownExpression
3914     |-'{'
3915     `-'}'
3916   )txt",
3917        R"txt(
3918 SimpleDeclaration
3919 |-'S'
3920 `-SimpleDeclarator Declarator
3921   |-'s1'
3922   |-'='
3923   `-UnknownExpression
3924     |-'{'
3925     |-IntegerLiteralExpression
3926     | `-'1' LiteralToken
3927     `-'}'
3928   )txt",
3929        R"txt(
3930 SimpleDeclaration
3931 |-'S'
3932 `-SimpleDeclarator Declarator
3933   |-'s2'
3934   |-'='
3935   `-UnknownExpression
3936     |-'{'
3937     |-IntegerLiteralExpression
3938     | `-'1' LiteralToken
3939     |-','
3940     |-FloatingLiteralExpression
3941     | `-'2.' LiteralToken
3942     `-'}'
3943 )txt"}));
3944 }
3945 
3946 TEST_P(SyntaxTreeTest, InitDeclarator_Paren) {
3947   if (!GetParam().isCXX()) {
3948     return;
3949   }
3950   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3951       R"cpp(
3952 struct S {
3953   S(int);
3954   S(int, float);
3955 };
3956 // FIXME: 's...' is a declarator and '(...)' is initializer
3957 [[S s1(1);]]
3958 [[S s2(1, 2.);]]
3959 )cpp",
3960       {R"txt(
3961 SimpleDeclaration
3962 |-'S'
3963 |-SimpleDeclarator Declarator
3964 | `-UnknownExpression
3965 |   |-'s1'
3966 |   |-'('
3967 |   |-IntegerLiteralExpression
3968 |   | `-'1' LiteralToken
3969 |   `-')'
3970 `-';'
3971   )txt",
3972        R"txt(
3973 SimpleDeclaration
3974 |-'S'
3975 |-SimpleDeclarator Declarator
3976 | `-UnknownExpression
3977 |   |-'s2'
3978 |   |-'('
3979 |   |-IntegerLiteralExpression
3980 |   | `-'1' LiteralToken
3981 |   |-','
3982 |   |-FloatingLiteralExpression
3983 |   | `-'2.' LiteralToken
3984 |   `-')'
3985 `-';'
3986 )txt"}));
3987 }
3988 
3989 TEST_P(SyntaxTreeTest, ImplicitConversion_Argument) {
3990   if (!GetParam().isCXX()) {
3991     return;
3992   }
3993   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3994       R"cpp(
3995 struct X {
3996   X(int);
3997 };
3998 void TakeX(const X&);
3999 void test() {
4000   [[TakeX(1)]];
4001 }
4002 )cpp",
4003       {R"txt(
4004 CallExpression Expression
4005 |-IdExpression Callee
4006 | `-UnqualifiedId UnqualifiedId
4007 |   `-'TakeX'
4008 |-'(' OpenParen
4009 |-CallArguments Arguments
4010 | `-IntegerLiteralExpression ListElement
4011 |   `-'1' LiteralToken
4012 `-')' CloseParen
4013 )txt"}));
4014 }
4015 
4016 TEST_P(SyntaxTreeTest, ImplicitConversion_Return) {
4017   if (!GetParam().isCXX()) {
4018     return;
4019   }
4020   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4021       R"cpp(
4022 struct X {
4023   X(int);
4024 };
4025 X CreateX(){
4026   [[return 1;]]
4027 }
4028 )cpp",
4029       {R"txt(
4030 ReturnStatement Statement
4031 |-'return' IntroducerKeyword
4032 |-IntegerLiteralExpression ReturnValue
4033 | `-'1' LiteralToken
4034 `-';'
4035 )txt"}));
4036 }
4037 
4038 TEST_P(SyntaxTreeTest, ConstructorCall_ZeroArguments) {
4039   if (!GetParam().isCXX()) {
4040     return;
4041   }
4042   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4043       R"cpp(
4044 struct X {
4045   X();
4046 };
4047 X test() {
4048   [[return X();]]
4049 }
4050 )cpp",
4051       {R"txt(
4052 ReturnStatement Statement
4053 |-'return' IntroducerKeyword
4054 |-UnknownExpression ReturnValue
4055 | |-'X'
4056 | |-'('
4057 | `-')'
4058 `-';'
4059 )txt"}));
4060 }
4061 
4062 TEST_P(SyntaxTreeTest, ConstructorCall_OneArgument) {
4063   if (!GetParam().isCXX()) {
4064     return;
4065   }
4066   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4067       R"cpp(
4068 struct X {
4069   X(int);
4070 };
4071 X test() {
4072   [[return X(1);]]
4073 }
4074 )cpp",
4075       {R"txt(
4076 ReturnStatement Statement
4077 |-'return' IntroducerKeyword
4078 |-UnknownExpression ReturnValue
4079 | |-'X'
4080 | |-'('
4081 | |-IntegerLiteralExpression
4082 | | `-'1' LiteralToken
4083 | `-')'
4084 `-';'
4085 )txt"}));
4086 }
4087 
4088 TEST_P(SyntaxTreeTest, ConstructorCall_MultipleArguments) {
4089   if (!GetParam().isCXX()) {
4090     return;
4091   }
4092   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4093       R"cpp(
4094 struct X {
4095   X(int, char);
4096 };
4097 X test() {
4098   [[return X(1, '2');]]
4099 }
4100 )cpp",
4101       {R"txt(
4102 ReturnStatement Statement
4103 |-'return' IntroducerKeyword
4104 |-UnknownExpression ReturnValue
4105 | |-'X'
4106 | |-'('
4107 | |-IntegerLiteralExpression
4108 | | `-'1' LiteralToken
4109 | |-','
4110 | |-CharacterLiteralExpression
4111 | | `-''2'' LiteralToken
4112 | `-')'
4113 `-';'
4114 )txt"}));
4115 }
4116 
4117 TEST_P(SyntaxTreeTest, TypeConversion_FunctionalNotation) {
4118   if (!GetParam().isCXX()) {
4119     return;
4120   }
4121   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4122       R"cpp(
4123 float test() {
4124   [[return float(1);]]
4125 }
4126 )cpp",
4127       {R"txt(
4128 ReturnStatement Statement
4129 |-'return' IntroducerKeyword
4130 |-UnknownExpression ReturnValue
4131 | |-'float'
4132 | |-'('
4133 | |-IntegerLiteralExpression
4134 | | `-'1' LiteralToken
4135 | `-')'
4136 `-';'
4137 )txt"}));
4138 }
4139 
4140 TEST_P(SyntaxTreeTest, ArrayDeclarator_Simple) {
4141   EXPECT_TRUE(treeDumpEqual(
4142       R"cpp(
4143 int a[10];
4144 )cpp",
4145       R"txt(
4146 TranslationUnit Detached
4147 `-SimpleDeclaration
4148   |-'int'
4149   |-SimpleDeclarator Declarator
4150   | |-'a'
4151   | `-ArraySubscript
4152   |   |-'[' OpenParen
4153   |   |-IntegerLiteralExpression Size
4154   |   | `-'10' LiteralToken
4155   |   `-']' CloseParen
4156   `-';'
4157 )txt"));
4158 }
4159 
4160 TEST_P(SyntaxTreeTest, ArrayDeclarator_Multidimensional) {
4161   EXPECT_TRUE(treeDumpEqual(
4162       R"cpp(
4163 int b[1][2][3];
4164 )cpp",
4165       R"txt(
4166 TranslationUnit Detached
4167 `-SimpleDeclaration
4168   |-'int'
4169   |-SimpleDeclarator Declarator
4170   | |-'b'
4171   | |-ArraySubscript
4172   | | |-'[' OpenParen
4173   | | |-IntegerLiteralExpression Size
4174   | | | `-'1' LiteralToken
4175   | | `-']' CloseParen
4176   | |-ArraySubscript
4177   | | |-'[' OpenParen
4178   | | |-IntegerLiteralExpression Size
4179   | | | `-'2' LiteralToken
4180   | | `-']' CloseParen
4181   | `-ArraySubscript
4182   |   |-'[' OpenParen
4183   |   |-IntegerLiteralExpression Size
4184   |   | `-'3' LiteralToken
4185   |   `-']' CloseParen
4186   `-';'
4187 )txt"));
4188 }
4189 
4190 TEST_P(SyntaxTreeTest, ArrayDeclarator_UnknownBound) {
4191   EXPECT_TRUE(treeDumpEqual(
4192       R"cpp(
4193 int c[] = {1,2,3};
4194 )cpp",
4195       R"txt(
4196 TranslationUnit Detached
4197 `-SimpleDeclaration
4198   |-'int'
4199   |-SimpleDeclarator Declarator
4200   | |-'c'
4201   | |-ArraySubscript
4202   | | |-'[' OpenParen
4203   | | `-']' CloseParen
4204   | |-'='
4205   | `-UnknownExpression
4206   |   `-UnknownExpression
4207   |     |-'{'
4208   |     |-IntegerLiteralExpression
4209   |     | `-'1' LiteralToken
4210   |     |-','
4211   |     |-IntegerLiteralExpression
4212   |     | `-'2' LiteralToken
4213   |     |-','
4214   |     |-IntegerLiteralExpression
4215   |     | `-'3' LiteralToken
4216   |     `-'}'
4217   `-';'
4218 )txt"));
4219 }
4220 
4221 TEST_P(SyntaxTreeTest, ArrayDeclarator_Static) {
4222   if (!GetParam().isC99OrLater()) {
4223     return;
4224   }
4225   EXPECT_TRUE(treeDumpEqual(
4226       R"cpp(
4227 void f(int xs[static 10]);
4228 )cpp",
4229       R"txt(
4230 TranslationUnit Detached
4231 `-SimpleDeclaration
4232   |-'void'
4233   |-SimpleDeclarator Declarator
4234   | |-'f'
4235   | `-ParametersAndQualifiers
4236   |   |-'(' OpenParen
4237   |   |-ParameterDeclarationList Parameters
4238   |   | `-SimpleDeclaration ListElement
4239   |   |   |-'int'
4240   |   |   `-SimpleDeclarator Declarator
4241   |   |     |-'xs'
4242   |   |     `-ArraySubscript
4243   |   |       |-'[' OpenParen
4244   |   |       |-'static'
4245   |   |       |-IntegerLiteralExpression Size
4246   |   |       | `-'10' LiteralToken
4247   |   |       `-']' CloseParen
4248   |   `-')' CloseParen
4249   `-';'
4250 )txt"));
4251 }
4252 
4253 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) {
4254   EXPECT_TRUE(treeDumpEqual(
4255       R"cpp(
4256 int func();
4257 )cpp",
4258       R"txt(
4259 TranslationUnit Detached
4260 `-SimpleDeclaration
4261   |-'int'
4262   |-SimpleDeclarator Declarator
4263   | |-'func'
4264   | `-ParametersAndQualifiers
4265   |   |-'(' OpenParen
4266   |   `-')' CloseParen
4267   `-';'
4268 )txt"));
4269 }
4270 
4271 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) {
4272   EXPECT_TRUE(treeDumpEqual(
4273       R"cpp(
4274 int func1(int a);
4275 int func2(int *ap);
4276 int func3(int a, float b);
4277 )cpp",
4278       R"txt(
4279 TranslationUnit Detached
4280 |-SimpleDeclaration
4281 | |-'int'
4282 | |-SimpleDeclarator Declarator
4283 | | |-'func1'
4284 | | `-ParametersAndQualifiers
4285 | |   |-'(' OpenParen
4286 | |   |-ParameterDeclarationList Parameters
4287 | |   | `-SimpleDeclaration ListElement
4288 | |   |   |-'int'
4289 | |   |   `-SimpleDeclarator Declarator
4290 | |   |     `-'a'
4291 | |   `-')' CloseParen
4292 | `-';'
4293 |-SimpleDeclaration
4294 | |-'int'
4295 | |-SimpleDeclarator Declarator
4296 | | |-'func2'
4297 | | `-ParametersAndQualifiers
4298 | |   |-'(' OpenParen
4299 | |   |-ParameterDeclarationList Parameters
4300 | |   | `-SimpleDeclaration ListElement
4301 | |   |   |-'int'
4302 | |   |   `-SimpleDeclarator Declarator
4303 | |   |     |-'*'
4304 | |   |     `-'ap'
4305 | |   `-')' CloseParen
4306 | `-';'
4307 `-SimpleDeclaration
4308   |-'int'
4309   |-SimpleDeclarator Declarator
4310   | |-'func3'
4311   | `-ParametersAndQualifiers
4312   |   |-'(' OpenParen
4313   |   |-ParameterDeclarationList Parameters
4314   |   | |-SimpleDeclaration ListElement
4315   |   | | |-'int'
4316   |   | | `-SimpleDeclarator Declarator
4317   |   | |   `-'a'
4318   |   | |-',' ListDelimiter
4319   |   | `-SimpleDeclaration ListElement
4320   |   |   |-'float'
4321   |   |   `-SimpleDeclarator Declarator
4322   |   |     `-'b'
4323   |   `-')' CloseParen
4324   `-';'
4325 )txt"));
4326 }
4327 
4328 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
4329   EXPECT_TRUE(treeDumpEqual(
4330       R"cpp(
4331 int func1(int);
4332 int func2(int *);
4333 int func3(int, float);
4334 )cpp",
4335       R"txt(
4336 TranslationUnit Detached
4337 |-SimpleDeclaration
4338 | |-'int'
4339 | |-SimpleDeclarator Declarator
4340 | | |-'func1'
4341 | | `-ParametersAndQualifiers
4342 | |   |-'(' OpenParen
4343 | |   |-ParameterDeclarationList Parameters
4344 | |   | `-SimpleDeclaration ListElement
4345 | |   |   `-'int'
4346 | |   `-')' CloseParen
4347 | `-';'
4348 |-SimpleDeclaration
4349 | |-'int'
4350 | |-SimpleDeclarator Declarator
4351 | | |-'func2'
4352 | | `-ParametersAndQualifiers
4353 | |   |-'(' OpenParen
4354 | |   |-ParameterDeclarationList Parameters
4355 | |   | `-SimpleDeclaration ListElement
4356 | |   |   |-'int'
4357 | |   |   `-SimpleDeclarator Declarator
4358 | |   |     `-'*'
4359 | |   `-')' CloseParen
4360 | `-';'
4361 `-SimpleDeclaration
4362   |-'int'
4363   |-SimpleDeclarator Declarator
4364   | |-'func3'
4365   | `-ParametersAndQualifiers
4366   |   |-'(' OpenParen
4367   |   |-ParameterDeclarationList Parameters
4368   |   | |-SimpleDeclaration ListElement
4369   |   | | `-'int'
4370   |   | |-',' ListDelimiter
4371   |   | `-SimpleDeclaration ListElement
4372   |   |   `-'float'
4373   |   `-')' CloseParen
4374   `-';'
4375 )txt"));
4376 }
4377 
4378 TEST_P(SyntaxTreeTest,
4379        ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) {
4380   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4381     return;
4382   }
4383   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4384       R"cpp(
4385 template<typename T, typename... Args>
4386 [[void test(T , Args... );]]
4387 )cpp",
4388       {R"txt(
4389 SimpleDeclaration
4390 |-'void'
4391 |-SimpleDeclarator Declarator
4392 | |-'test'
4393 | `-ParametersAndQualifiers
4394 |   |-'(' OpenParen
4395 |   |-ParameterDeclarationList Parameters
4396 |   | |-SimpleDeclaration ListElement
4397 |   | | `-'T'
4398 |   | |-',' ListDelimiter
4399 |   | `-SimpleDeclaration ListElement
4400 |   |   |-'Args'
4401 |   |   `-'...'
4402 |   `-')' CloseParen
4403 `-';'
4404 )txt"}));
4405 }
4406 
4407 TEST_P(SyntaxTreeTest,
4408        ParametersAndQualifiers_InVariadicFunctionTemplate_NamedParameterPack) {
4409   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4410     return;
4411   }
4412   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4413       R"cpp(
4414 template<typename T, typename... Args>
4415 [[void test(T t, Args... args);]]
4416 )cpp",
4417       {R"txt(
4418 SimpleDeclaration
4419 |-'void'
4420 |-SimpleDeclarator Declarator
4421 | |-'test'
4422 | `-ParametersAndQualifiers
4423 |   |-'(' OpenParen
4424 |   |-ParameterDeclarationList Parameters
4425 |   | |-SimpleDeclaration ListElement
4426 |   | | |-'T'
4427 |   | | `-SimpleDeclarator Declarator
4428 |   | |   `-'t'
4429 |   | |-',' ListDelimiter
4430 |   | `-SimpleDeclaration ListElement
4431 |   |   |-'Args'
4432 |   |   |-'...'
4433 |   |   `-SimpleDeclarator Declarator
4434 |   |     `-'args'
4435 |   `-')' CloseParen
4436 `-';'
4437 )txt"}));
4438 }
4439 
4440 TEST_P(SyntaxTreeTest,
4441        ParametersAndQualifiers_InFreeFunctions_VariadicArguments) {
4442   if (!GetParam().isCXX11OrLater()) {
4443     return;
4444   }
4445   EXPECT_TRUE(treeDumpEqual(
4446       R"cpp(
4447 void test(int , char ...);
4448 )cpp",
4449       R"txt(
4450 TranslationUnit Detached
4451 `-SimpleDeclaration
4452   |-'void'
4453   |-SimpleDeclarator Declarator
4454   | |-'test'
4455   | `-ParametersAndQualifiers
4456   |   |-'(' OpenParen
4457   |   |-ParameterDeclarationList Parameters
4458   |   | |-SimpleDeclaration ListElement
4459   |   | | `-'int'
4460   |   | |-',' ListDelimiter
4461   |   | `-SimpleDeclaration ListElement
4462   |   |   `-'char'
4463   |   |-'...'
4464   |   `-')' CloseParen
4465   `-';'
4466 )txt"));
4467 }
4468 
4469 TEST_P(SyntaxTreeTest,
4470        ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
4471   if (!GetParam().isCXX()) {
4472     return;
4473   }
4474   EXPECT_TRUE(treeDumpEqual(
4475       R"cpp(
4476 int func(const int a, volatile int b, const volatile int c);
4477 )cpp",
4478       R"txt(
4479 TranslationUnit Detached
4480 `-SimpleDeclaration
4481   |-'int'
4482   |-SimpleDeclarator Declarator
4483   | |-'func'
4484   | `-ParametersAndQualifiers
4485   |   |-'(' OpenParen
4486   |   |-ParameterDeclarationList Parameters
4487   |   | |-SimpleDeclaration ListElement
4488   |   | | |-'const'
4489   |   | | |-'int'
4490   |   | | `-SimpleDeclarator Declarator
4491   |   | |   `-'a'
4492   |   | |-',' ListDelimiter
4493   |   | |-SimpleDeclaration ListElement
4494   |   | | |-'volatile'
4495   |   | | |-'int'
4496   |   | | `-SimpleDeclarator Declarator
4497   |   | |   `-'b'
4498   |   | |-',' ListDelimiter
4499   |   | `-SimpleDeclaration ListElement
4500   |   |   |-'const'
4501   |   |   |-'volatile'
4502   |   |   |-'int'
4503   |   |   `-SimpleDeclarator Declarator
4504   |   |     `-'c'
4505   |   `-')' CloseParen
4506   `-';'
4507 )txt"));
4508 }
4509 
4510 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
4511   if (!GetParam().isCXX()) {
4512     return;
4513   }
4514   EXPECT_TRUE(treeDumpEqual(
4515       R"cpp(
4516 int func(int& a);
4517 )cpp",
4518       R"txt(
4519 TranslationUnit Detached
4520 `-SimpleDeclaration
4521   |-'int'
4522   |-SimpleDeclarator Declarator
4523   | |-'func'
4524   | `-ParametersAndQualifiers
4525   |   |-'(' OpenParen
4526   |   |-ParameterDeclarationList Parameters
4527   |   | `-SimpleDeclaration ListElement
4528   |   |   |-'int'
4529   |   |   `-SimpleDeclarator Declarator
4530   |   |     |-'&'
4531   |   |     `-'a'
4532   |   `-')' CloseParen
4533   `-';'
4534 )txt"));
4535 }
4536 
4537 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
4538   if (!GetParam().isCXX11OrLater()) {
4539     return;
4540   }
4541   EXPECT_TRUE(treeDumpEqual(
4542       R"cpp(
4543 int func(int&& a);
4544 )cpp",
4545       R"txt(
4546 TranslationUnit Detached
4547 `-SimpleDeclaration
4548   |-'int'
4549   |-SimpleDeclarator Declarator
4550   | |-'func'
4551   | `-ParametersAndQualifiers
4552   |   |-'(' OpenParen
4553   |   |-ParameterDeclarationList Parameters
4554   |   | `-SimpleDeclaration ListElement
4555   |   |   |-'int'
4556   |   |   `-SimpleDeclarator Declarator
4557   |   |     |-'&&'
4558   |   |     `-'a'
4559   |   `-')' CloseParen
4560   `-';'
4561 )txt"));
4562 }
4563 
4564 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
4565   if (!GetParam().isCXX()) {
4566     return;
4567   }
4568   EXPECT_TRUE(treeDumpEqual(
4569       R"cpp(
4570 struct Test {
4571   int a();
4572 };
4573 )cpp",
4574       R"txt(
4575 TranslationUnit Detached
4576 `-SimpleDeclaration
4577   |-'struct'
4578   |-'Test'
4579   |-'{'
4580   |-SimpleDeclaration
4581   | |-'int'
4582   | |-SimpleDeclarator Declarator
4583   | | |-'a'
4584   | | `-ParametersAndQualifiers
4585   | |   |-'(' OpenParen
4586   | |   `-')' CloseParen
4587   | `-';'
4588   |-'}'
4589   `-';'
4590 )txt"));
4591 }
4592 
4593 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
4594   if (!GetParam().isCXX()) {
4595     return;
4596   }
4597   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4598       R"cpp(
4599 struct Test {
4600   [[int b() const;]]
4601   [[int c() volatile;]]
4602   [[int d() const volatile;]]
4603 };
4604 )cpp",
4605       {R"txt(
4606 SimpleDeclaration
4607 |-'int'
4608 |-SimpleDeclarator Declarator
4609 | |-'b'
4610 | `-ParametersAndQualifiers
4611 |   |-'(' OpenParen
4612 |   |-')' CloseParen
4613 |   `-'const'
4614 `-';'
4615 )txt",
4616        R"txt(
4617 SimpleDeclaration
4618 |-'int'
4619 |-SimpleDeclarator Declarator
4620 | |-'c'
4621 | `-ParametersAndQualifiers
4622 |   |-'(' OpenParen
4623 |   |-')' CloseParen
4624 |   `-'volatile'
4625 `-';'
4626 )txt",
4627        R"txt(
4628 SimpleDeclaration
4629 |-'int'
4630 |-SimpleDeclarator Declarator
4631 | |-'d'
4632 | `-ParametersAndQualifiers
4633 |   |-'(' OpenParen
4634 |   |-')' CloseParen
4635 |   |-'const'
4636 |   `-'volatile'
4637 `-';'
4638 )txt"}));
4639 }
4640 
4641 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
4642   if (!GetParam().isCXX11OrLater()) {
4643     return;
4644   }
4645   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4646       R"cpp(
4647 struct Test {
4648   [[int e() &;]]
4649 };
4650 )cpp",
4651       {R"txt(
4652 SimpleDeclaration
4653 |-'int'
4654 |-SimpleDeclarator Declarator
4655 | |-'e'
4656 | `-ParametersAndQualifiers
4657 |   |-'(' OpenParen
4658 |   |-')' CloseParen
4659 |   `-'&'
4660 `-';'
4661 )txt"}));
4662 }
4663 
4664 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
4665   if (!GetParam().isCXX11OrLater()) {
4666     return;
4667   }
4668   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4669       R"cpp(
4670 struct Test {
4671   [[int f() &&;]]
4672 };
4673 )cpp",
4674       {R"txt(
4675 SimpleDeclaration
4676 |-'int'
4677 |-SimpleDeclarator Declarator
4678 | |-'f'
4679 | `-ParametersAndQualifiers
4680 |   |-'(' OpenParen
4681 |   |-')' CloseParen
4682 |   `-'&&'
4683 `-';'
4684 )txt"}));
4685 }
4686 
4687 TEST_P(SyntaxTreeTest, TrailingReturn) {
4688   if (!GetParam().isCXX11OrLater()) {
4689     return;
4690   }
4691   EXPECT_TRUE(treeDumpEqual(
4692       R"cpp(
4693 auto foo() -> int;
4694 )cpp",
4695       R"txt(
4696 TranslationUnit Detached
4697 `-SimpleDeclaration
4698   |-'auto'
4699   |-SimpleDeclarator Declarator
4700   | |-'foo'
4701   | `-ParametersAndQualifiers
4702   |   |-'(' OpenParen
4703   |   |-')' CloseParen
4704   |   `-TrailingReturnType TrailingReturn
4705   |     |-'->' ArrowToken
4706   |     `-'int'
4707   `-';'
4708 )txt"));
4709 }
4710 
4711 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
4712   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
4713     return;
4714   }
4715   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4716       R"cpp(
4717 struct MyException1 {};
4718 struct MyException2 {};
4719 [[int a() throw();]]
4720 [[int b() throw(...);]]
4721 [[int c() throw(MyException1);]]
4722 [[int d() throw(MyException1, MyException2);]]
4723 )cpp",
4724       {R"txt(
4725 SimpleDeclaration
4726 |-'int'
4727 |-SimpleDeclarator Declarator
4728 | |-'a'
4729 | `-ParametersAndQualifiers
4730 |   |-'(' OpenParen
4731 |   |-')' CloseParen
4732 |   |-'throw'
4733 |   |-'('
4734 |   `-')'
4735 `-';'
4736 )txt",
4737        R"txt(
4738 SimpleDeclaration
4739 |-'int'
4740 |-SimpleDeclarator Declarator
4741 | |-'b'
4742 | `-ParametersAndQualifiers
4743 |   |-'(' OpenParen
4744 |   |-')' CloseParen
4745 |   |-'throw'
4746 |   |-'('
4747 |   |-'...'
4748 |   `-')'
4749 `-';'
4750 )txt",
4751        R"txt(
4752 SimpleDeclaration
4753 |-'int'
4754 |-SimpleDeclarator Declarator
4755 | |-'c'
4756 | `-ParametersAndQualifiers
4757 |   |-'(' OpenParen
4758 |   |-')' CloseParen
4759 |   |-'throw'
4760 |   |-'('
4761 |   |-'MyException1'
4762 |   `-')'
4763 `-';'
4764 )txt",
4765        R"txt(
4766 SimpleDeclaration
4767 |-'int'
4768 |-SimpleDeclarator Declarator
4769 | |-'d'
4770 | `-ParametersAndQualifiers
4771 |   |-'(' OpenParen
4772 |   |-')' CloseParen
4773 |   |-'throw'
4774 |   |-'('
4775 |   |-'MyException1'
4776 |   |-','
4777 |   |-'MyException2'
4778 |   `-')'
4779 `-';'
4780 )txt"}));
4781 }
4782 
4783 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
4784   if (!GetParam().isCXX11OrLater()) {
4785     return;
4786   }
4787   EXPECT_TRUE(treeDumpEqual(
4788       R"cpp(
4789 int a() noexcept;
4790 int b() noexcept(true);
4791 )cpp",
4792       R"txt(
4793 TranslationUnit Detached
4794 |-SimpleDeclaration
4795 | |-'int'
4796 | |-SimpleDeclarator Declarator
4797 | | |-'a'
4798 | | `-ParametersAndQualifiers
4799 | |   |-'(' OpenParen
4800 | |   |-')' CloseParen
4801 | |   `-'noexcept'
4802 | `-';'
4803 `-SimpleDeclaration
4804   |-'int'
4805   |-SimpleDeclarator Declarator
4806   | |-'b'
4807   | `-ParametersAndQualifiers
4808   |   |-'(' OpenParen
4809   |   |-')' CloseParen
4810   |   |-'noexcept'
4811   |   |-'('
4812   |   |-BoolLiteralExpression
4813   |   | `-'true' LiteralToken
4814   |   `-')'
4815   `-';'
4816 )txt"));
4817 }
4818 
4819 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
4820   EXPECT_TRUE(treeDumpEqual(
4821       R"cpp(
4822 int (a);
4823 int *(b);
4824 int (*c)(int);
4825 int *(d)(int);
4826 )cpp",
4827       R"txt(
4828 TranslationUnit Detached
4829 |-SimpleDeclaration
4830 | |-'int'
4831 | |-SimpleDeclarator Declarator
4832 | | `-ParenDeclarator
4833 | |   |-'(' OpenParen
4834 | |   |-'a'
4835 | |   `-')' CloseParen
4836 | `-';'
4837 |-SimpleDeclaration
4838 | |-'int'
4839 | |-SimpleDeclarator Declarator
4840 | | |-'*'
4841 | | `-ParenDeclarator
4842 | |   |-'(' OpenParen
4843 | |   |-'b'
4844 | |   `-')' CloseParen
4845 | `-';'
4846 |-SimpleDeclaration
4847 | |-'int'
4848 | |-SimpleDeclarator Declarator
4849 | | |-ParenDeclarator
4850 | | | |-'(' OpenParen
4851 | | | |-'*'
4852 | | | |-'c'
4853 | | | `-')' CloseParen
4854 | | `-ParametersAndQualifiers
4855 | |   |-'(' OpenParen
4856 | |   |-ParameterDeclarationList Parameters
4857 | |   | `-SimpleDeclaration ListElement
4858 | |   |   `-'int'
4859 | |   `-')' CloseParen
4860 | `-';'
4861 `-SimpleDeclaration
4862   |-'int'
4863   |-SimpleDeclarator Declarator
4864   | |-'*'
4865   | |-ParenDeclarator
4866   | | |-'(' OpenParen
4867   | | |-'d'
4868   | | `-')' CloseParen
4869   | `-ParametersAndQualifiers
4870   |   |-'(' OpenParen
4871   |   |-ParameterDeclarationList Parameters
4872   |   | `-SimpleDeclaration ListElement
4873   |   |   `-'int'
4874   |   `-')' CloseParen
4875   `-';'
4876 )txt"));
4877 }
4878 
4879 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
4880   EXPECT_TRUE(treeDumpEqual(
4881       R"cpp(
4882 const int west = -1;
4883 int const east = 1;
4884 )cpp",
4885       R"txt(
4886 TranslationUnit Detached
4887 |-SimpleDeclaration
4888 | |-'const'
4889 | |-'int'
4890 | |-SimpleDeclarator Declarator
4891 | | |-'west'
4892 | | |-'='
4893 | | `-PrefixUnaryOperatorExpression
4894 | |   |-'-' OperatorToken
4895 | |   `-IntegerLiteralExpression Operand
4896 | |     `-'1' LiteralToken
4897 | `-';'
4898 `-SimpleDeclaration
4899   |-'int'
4900   |-'const'
4901   |-SimpleDeclarator Declarator
4902   | |-'east'
4903   | |-'='
4904   | `-IntegerLiteralExpression
4905   |   `-'1' LiteralToken
4906   `-';'
4907 )txt"));
4908 }
4909 
4910 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
4911   EXPECT_TRUE(treeDumpEqual(
4912       R"cpp(
4913 const int const universal = 0;
4914 )cpp",
4915       R"txt(
4916 TranslationUnit Detached
4917 `-SimpleDeclaration
4918   |-'const'
4919   |-'int'
4920   |-'const'
4921   |-SimpleDeclarator Declarator
4922   | |-'universal'
4923   | |-'='
4924   | `-IntegerLiteralExpression
4925   |   `-'0' LiteralToken
4926   `-';'
4927 )txt"));
4928 }
4929 
4930 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
4931   EXPECT_TRUE(treeDumpEqual(
4932       R"cpp(
4933 const int const *const *volatile b;
4934 )cpp",
4935       R"txt(
4936 TranslationUnit Detached
4937 `-SimpleDeclaration
4938   |-'const'
4939   |-'int'
4940   |-'const'
4941   |-SimpleDeclarator Declarator
4942   | |-'*'
4943   | |-'const'
4944   | |-'*'
4945   | |-'volatile'
4946   | `-'b'
4947   `-';'
4948 )txt"));
4949 }
4950 
4951 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
4952   if (!GetParam().isCXX11OrLater()) {
4953     return;
4954   }
4955   EXPECT_TRUE(treeDumpEqual(
4956       R"cpp(
4957 auto foo() -> auto(*)(int) -> double*;
4958 )cpp",
4959       R"txt(
4960 TranslationUnit Detached
4961 `-SimpleDeclaration
4962   |-'auto'
4963   |-SimpleDeclarator Declarator
4964   | |-'foo'
4965   | `-ParametersAndQualifiers
4966   |   |-'(' OpenParen
4967   |   |-')' CloseParen
4968   |   `-TrailingReturnType TrailingReturn
4969   |     |-'->' ArrowToken
4970   |     |-'auto'
4971   |     `-SimpleDeclarator Declarator
4972   |       |-ParenDeclarator
4973   |       | |-'(' OpenParen
4974   |       | |-'*'
4975   |       | `-')' CloseParen
4976   |       `-ParametersAndQualifiers
4977   |         |-'(' OpenParen
4978   |         |-ParameterDeclarationList Parameters
4979   |         | `-SimpleDeclaration ListElement
4980   |         |   `-'int'
4981   |         |-')' CloseParen
4982   |         `-TrailingReturnType TrailingReturn
4983   |           |-'->' ArrowToken
4984   |           |-'double'
4985   |           `-SimpleDeclarator Declarator
4986   |             `-'*'
4987   `-';'
4988 )txt"));
4989 }
4990 
4991 TEST_P(SyntaxTreeTest, MemberPointers) {
4992   if (!GetParam().isCXX()) {
4993     return;
4994   }
4995   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4996       R"cpp(
4997 struct X {};
4998 [[int X::* a;]]
4999 [[const int X::* b;]]
5000 )cpp",
5001       {R"txt(
5002 SimpleDeclaration
5003 |-'int'
5004 |-SimpleDeclarator Declarator
5005 | |-MemberPointer
5006 | | |-'X'
5007 | | |-'::'
5008 | | `-'*'
5009 | `-'a'
5010 `-';'
5011 )txt",
5012        R"txt(
5013 SimpleDeclaration
5014 |-'const'
5015 |-'int'
5016 |-SimpleDeclarator Declarator
5017 | |-MemberPointer
5018 | | |-'X'
5019 | | |-'::'
5020 | | `-'*'
5021 | `-'b'
5022 `-';'
5023 )txt"}));
5024 }
5025 
5026 TEST_P(SyntaxTreeTest, MemberFunctionPointer) {
5027   if (!GetParam().isCXX()) {
5028     return;
5029   }
5030   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5031       R"cpp(
5032 struct X {
5033   struct Y {};
5034 };
5035 [[void (X::*xp)();]]
5036 [[void (X::**xpp)(const int*);]]
5037 // FIXME: Generate the right syntax tree for this type,
5038 // i.e. create a syntax node for the outer member pointer
5039 [[void (X::Y::*xyp)(const int*, char);]]
5040 )cpp",
5041       {R"txt(
5042 SimpleDeclaration
5043 |-'void'
5044 |-SimpleDeclarator Declarator
5045 | |-ParenDeclarator
5046 | | |-'(' OpenParen
5047 | | |-MemberPointer
5048 | | | |-'X'
5049 | | | |-'::'
5050 | | | `-'*'
5051 | | |-'xp'
5052 | | `-')' CloseParen
5053 | `-ParametersAndQualifiers
5054 |   |-'(' OpenParen
5055 |   `-')' CloseParen
5056 `-';'
5057 )txt",
5058        R"txt(
5059 SimpleDeclaration
5060 |-'void'
5061 |-SimpleDeclarator Declarator
5062 | |-ParenDeclarator
5063 | | |-'(' OpenParen
5064 | | |-MemberPointer
5065 | | | |-'X'
5066 | | | |-'::'
5067 | | | `-'*'
5068 | | |-'*'
5069 | | |-'xpp'
5070 | | `-')' CloseParen
5071 | `-ParametersAndQualifiers
5072 |   |-'(' OpenParen
5073 |   |-ParameterDeclarationList Parameters
5074 |   | `-SimpleDeclaration ListElement
5075 |   |   |-'const'
5076 |   |   |-'int'
5077 |   |   `-SimpleDeclarator Declarator
5078 |   |     `-'*'
5079 |   `-')' CloseParen
5080 `-';'
5081 )txt",
5082        R"txt(
5083 SimpleDeclaration
5084 |-'void'
5085 |-SimpleDeclarator Declarator
5086 | |-ParenDeclarator
5087 | | |-'(' OpenParen
5088 | | |-'X'
5089 | | |-'::'
5090 | | |-MemberPointer
5091 | | | |-'Y'
5092 | | | |-'::'
5093 | | | `-'*'
5094 | | |-'xyp'
5095 | | `-')' CloseParen
5096 | `-ParametersAndQualifiers
5097 |   |-'(' OpenParen
5098 |   |-ParameterDeclarationList Parameters
5099 |   | |-SimpleDeclaration ListElement
5100 |   | | |-'const'
5101 |   | | |-'int'
5102 |   | | `-SimpleDeclarator Declarator
5103 |   | |   `-'*'
5104 |   | |-',' ListDelimiter
5105 |   | `-SimpleDeclaration ListElement
5106 |   |   `-'char'
5107 |   `-')' CloseParen
5108 `-';'
5109 )txt"}));
5110 }
5111 
5112 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
5113   EXPECT_TRUE(treeDumpEqual(
5114       R"cpp(
5115 void x(char a, short (*b)(int));
5116 )cpp",
5117       R"txt(
5118 TranslationUnit Detached
5119 `-SimpleDeclaration
5120   |-'void'
5121   |-SimpleDeclarator Declarator
5122   | |-'x'
5123   | `-ParametersAndQualifiers
5124   |   |-'(' OpenParen
5125   |   |-ParameterDeclarationList Parameters
5126   |   | |-SimpleDeclaration ListElement
5127   |   | | |-'char'
5128   |   | | `-SimpleDeclarator Declarator
5129   |   | |   `-'a'
5130   |   | |-',' ListDelimiter
5131   |   | `-SimpleDeclaration ListElement
5132   |   |   |-'short'
5133   |   |   `-SimpleDeclarator Declarator
5134   |   |     |-ParenDeclarator
5135   |   |     | |-'(' OpenParen
5136   |   |     | |-'*'
5137   |   |     | |-'b'
5138   |   |     | `-')' CloseParen
5139   |   |     `-ParametersAndQualifiers
5140   |   |       |-'(' OpenParen
5141   |   |       |-ParameterDeclarationList Parameters
5142   |   |       | `-SimpleDeclaration ListElement
5143   |   |       |   `-'int'
5144   |   |       `-')' CloseParen
5145   |   `-')' CloseParen
5146   `-';'
5147 )txt"));
5148 }
5149 
5150 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
5151   EXPECT_TRUE(treeDumpEqual(
5152       R"cpp(
5153 void x(char a, short (*b)(int), long (**c)(long long));
5154 )cpp",
5155       R"txt(
5156 TranslationUnit Detached
5157 `-SimpleDeclaration
5158   |-'void'
5159   |-SimpleDeclarator Declarator
5160   | |-'x'
5161   | `-ParametersAndQualifiers
5162   |   |-'(' OpenParen
5163   |   |-ParameterDeclarationList Parameters
5164   |   | |-SimpleDeclaration ListElement
5165   |   | | |-'char'
5166   |   | | `-SimpleDeclarator Declarator
5167   |   | |   `-'a'
5168   |   | |-',' ListDelimiter
5169   |   | |-SimpleDeclaration ListElement
5170   |   | | |-'short'
5171   |   | | `-SimpleDeclarator Declarator
5172   |   | |   |-ParenDeclarator
5173   |   | |   | |-'(' OpenParen
5174   |   | |   | |-'*'
5175   |   | |   | |-'b'
5176   |   | |   | `-')' CloseParen
5177   |   | |   `-ParametersAndQualifiers
5178   |   | |     |-'(' OpenParen
5179   |   | |     |-ParameterDeclarationList Parameters
5180   |   | |     | `-SimpleDeclaration ListElement
5181   |   | |     |   `-'int'
5182   |   | |     `-')' CloseParen
5183   |   | |-',' ListDelimiter
5184   |   | `-SimpleDeclaration ListElement
5185   |   |   |-'long'
5186   |   |   `-SimpleDeclarator Declarator
5187   |   |     |-ParenDeclarator
5188   |   |     | |-'(' OpenParen
5189   |   |     | |-'*'
5190   |   |     | |-'*'
5191   |   |     | |-'c'
5192   |   |     | `-')' CloseParen
5193   |   |     `-ParametersAndQualifiers
5194   |   |       |-'(' OpenParen
5195   |   |       |-ParameterDeclarationList Parameters
5196   |   |       | `-SimpleDeclaration ListElement
5197   |   |       |   |-'long'
5198   |   |       |   `-'long'
5199   |   |       `-')' CloseParen
5200   |   `-')' CloseParen
5201   `-';'
5202 )txt"));
5203 }
5204 
5205 } // namespace
5206