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   // FIXME: Remove `UnknownExpression` due to implicit `CXXFunctionalCastExpr`
4073   [[return X(1);]]
4074 }
4075 )cpp",
4076       {R"txt(
4077 ReturnStatement Statement
4078 |-'return' IntroducerKeyword
4079 |-UnknownExpression ReturnValue
4080 | `-UnknownExpression
4081 |   |-'X'
4082 |   |-'('
4083 |   |-IntegerLiteralExpression
4084 |   | `-'1' LiteralToken
4085 |   `-')'
4086 `-';'
4087 )txt"}));
4088 }
4089 
4090 TEST_P(SyntaxTreeTest, ConstructorCall_MultipleArguments) {
4091   if (!GetParam().isCXX()) {
4092     return;
4093   }
4094   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4095       R"cpp(
4096 struct X {
4097   X(int, char);
4098 };
4099 X test() {
4100   [[return X(1, '2');]]
4101 }
4102 )cpp",
4103       {R"txt(
4104 ReturnStatement Statement
4105 |-'return' IntroducerKeyword
4106 |-UnknownExpression ReturnValue
4107 | |-'X'
4108 | |-'('
4109 | |-IntegerLiteralExpression
4110 | | `-'1' LiteralToken
4111 | |-','
4112 | |-CharacterLiteralExpression
4113 | | `-''2'' LiteralToken
4114 | `-')'
4115 `-';'
4116 )txt"}));
4117 }
4118 
4119 TEST_P(SyntaxTreeTest, TypeConversion_FunctionalNotation) {
4120   if (!GetParam().isCXX()) {
4121     return;
4122   }
4123   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4124       R"cpp(
4125 float test() {
4126   [[return float(1);]]
4127 }
4128 )cpp",
4129       {R"txt(
4130 ReturnStatement Statement
4131 |-'return' IntroducerKeyword
4132 |-UnknownExpression ReturnValue
4133 | |-'float'
4134 | |-'('
4135 | |-IntegerLiteralExpression
4136 | | `-'1' LiteralToken
4137 | `-')'
4138 `-';'
4139 )txt"}));
4140 }
4141 
4142 TEST_P(SyntaxTreeTest, ArrayDeclarator_Simple) {
4143   EXPECT_TRUE(treeDumpEqual(
4144       R"cpp(
4145 int a[10];
4146 )cpp",
4147       R"txt(
4148 TranslationUnit Detached
4149 `-SimpleDeclaration
4150   |-'int'
4151   |-SimpleDeclarator Declarator
4152   | |-'a'
4153   | `-ArraySubscript
4154   |   |-'[' OpenParen
4155   |   |-IntegerLiteralExpression Size
4156   |   | `-'10' LiteralToken
4157   |   `-']' CloseParen
4158   `-';'
4159 )txt"));
4160 }
4161 
4162 TEST_P(SyntaxTreeTest, ArrayDeclarator_Multidimensional) {
4163   EXPECT_TRUE(treeDumpEqual(
4164       R"cpp(
4165 int b[1][2][3];
4166 )cpp",
4167       R"txt(
4168 TranslationUnit Detached
4169 `-SimpleDeclaration
4170   |-'int'
4171   |-SimpleDeclarator Declarator
4172   | |-'b'
4173   | |-ArraySubscript
4174   | | |-'[' OpenParen
4175   | | |-IntegerLiteralExpression Size
4176   | | | `-'1' LiteralToken
4177   | | `-']' CloseParen
4178   | |-ArraySubscript
4179   | | |-'[' OpenParen
4180   | | |-IntegerLiteralExpression Size
4181   | | | `-'2' LiteralToken
4182   | | `-']' CloseParen
4183   | `-ArraySubscript
4184   |   |-'[' OpenParen
4185   |   |-IntegerLiteralExpression Size
4186   |   | `-'3' LiteralToken
4187   |   `-']' CloseParen
4188   `-';'
4189 )txt"));
4190 }
4191 
4192 TEST_P(SyntaxTreeTest, ArrayDeclarator_UnknownBound) {
4193   EXPECT_TRUE(treeDumpEqual(
4194       R"cpp(
4195 int c[] = {1,2,3};
4196 )cpp",
4197       R"txt(
4198 TranslationUnit Detached
4199 `-SimpleDeclaration
4200   |-'int'
4201   |-SimpleDeclarator Declarator
4202   | |-'c'
4203   | |-ArraySubscript
4204   | | |-'[' OpenParen
4205   | | `-']' CloseParen
4206   | |-'='
4207   | `-UnknownExpression
4208   |   `-UnknownExpression
4209   |     |-'{'
4210   |     |-IntegerLiteralExpression
4211   |     | `-'1' LiteralToken
4212   |     |-','
4213   |     |-IntegerLiteralExpression
4214   |     | `-'2' LiteralToken
4215   |     |-','
4216   |     |-IntegerLiteralExpression
4217   |     | `-'3' LiteralToken
4218   |     `-'}'
4219   `-';'
4220 )txt"));
4221 }
4222 
4223 TEST_P(SyntaxTreeTest, ArrayDeclarator_Static) {
4224   if (!GetParam().isC99OrLater()) {
4225     return;
4226   }
4227   EXPECT_TRUE(treeDumpEqual(
4228       R"cpp(
4229 void f(int xs[static 10]);
4230 )cpp",
4231       R"txt(
4232 TranslationUnit Detached
4233 `-SimpleDeclaration
4234   |-'void'
4235   |-SimpleDeclarator Declarator
4236   | |-'f'
4237   | `-ParametersAndQualifiers
4238   |   |-'(' OpenParen
4239   |   |-ParameterDeclarationList Parameters
4240   |   | `-SimpleDeclaration ListElement
4241   |   |   |-'int'
4242   |   |   `-SimpleDeclarator Declarator
4243   |   |     |-'xs'
4244   |   |     `-ArraySubscript
4245   |   |       |-'[' OpenParen
4246   |   |       |-'static'
4247   |   |       |-IntegerLiteralExpression Size
4248   |   |       | `-'10' LiteralToken
4249   |   |       `-']' CloseParen
4250   |   `-')' CloseParen
4251   `-';'
4252 )txt"));
4253 }
4254 
4255 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) {
4256   EXPECT_TRUE(treeDumpEqual(
4257       R"cpp(
4258 int func();
4259 )cpp",
4260       R"txt(
4261 TranslationUnit Detached
4262 `-SimpleDeclaration
4263   |-'int'
4264   |-SimpleDeclarator Declarator
4265   | |-'func'
4266   | `-ParametersAndQualifiers
4267   |   |-'(' OpenParen
4268   |   `-')' CloseParen
4269   `-';'
4270 )txt"));
4271 }
4272 
4273 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) {
4274   EXPECT_TRUE(treeDumpEqual(
4275       R"cpp(
4276 int func1(int a);
4277 int func2(int *ap);
4278 int func3(int a, float b);
4279 )cpp",
4280       R"txt(
4281 TranslationUnit Detached
4282 |-SimpleDeclaration
4283 | |-'int'
4284 | |-SimpleDeclarator Declarator
4285 | | |-'func1'
4286 | | `-ParametersAndQualifiers
4287 | |   |-'(' OpenParen
4288 | |   |-ParameterDeclarationList Parameters
4289 | |   | `-SimpleDeclaration ListElement
4290 | |   |   |-'int'
4291 | |   |   `-SimpleDeclarator Declarator
4292 | |   |     `-'a'
4293 | |   `-')' CloseParen
4294 | `-';'
4295 |-SimpleDeclaration
4296 | |-'int'
4297 | |-SimpleDeclarator Declarator
4298 | | |-'func2'
4299 | | `-ParametersAndQualifiers
4300 | |   |-'(' OpenParen
4301 | |   |-ParameterDeclarationList Parameters
4302 | |   | `-SimpleDeclaration ListElement
4303 | |   |   |-'int'
4304 | |   |   `-SimpleDeclarator Declarator
4305 | |   |     |-'*'
4306 | |   |     `-'ap'
4307 | |   `-')' CloseParen
4308 | `-';'
4309 `-SimpleDeclaration
4310   |-'int'
4311   |-SimpleDeclarator Declarator
4312   | |-'func3'
4313   | `-ParametersAndQualifiers
4314   |   |-'(' OpenParen
4315   |   |-ParameterDeclarationList Parameters
4316   |   | |-SimpleDeclaration ListElement
4317   |   | | |-'int'
4318   |   | | `-SimpleDeclarator Declarator
4319   |   | |   `-'a'
4320   |   | |-',' ListDelimiter
4321   |   | `-SimpleDeclaration ListElement
4322   |   |   |-'float'
4323   |   |   `-SimpleDeclarator Declarator
4324   |   |     `-'b'
4325   |   `-')' CloseParen
4326   `-';'
4327 )txt"));
4328 }
4329 
4330 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
4331   EXPECT_TRUE(treeDumpEqual(
4332       R"cpp(
4333 int func1(int);
4334 int func2(int *);
4335 int func3(int, float);
4336 )cpp",
4337       R"txt(
4338 TranslationUnit Detached
4339 |-SimpleDeclaration
4340 | |-'int'
4341 | |-SimpleDeclarator Declarator
4342 | | |-'func1'
4343 | | `-ParametersAndQualifiers
4344 | |   |-'(' OpenParen
4345 | |   |-ParameterDeclarationList Parameters
4346 | |   | `-SimpleDeclaration ListElement
4347 | |   |   `-'int'
4348 | |   `-')' CloseParen
4349 | `-';'
4350 |-SimpleDeclaration
4351 | |-'int'
4352 | |-SimpleDeclarator Declarator
4353 | | |-'func2'
4354 | | `-ParametersAndQualifiers
4355 | |   |-'(' OpenParen
4356 | |   |-ParameterDeclarationList Parameters
4357 | |   | `-SimpleDeclaration ListElement
4358 | |   |   |-'int'
4359 | |   |   `-SimpleDeclarator Declarator
4360 | |   |     `-'*'
4361 | |   `-')' CloseParen
4362 | `-';'
4363 `-SimpleDeclaration
4364   |-'int'
4365   |-SimpleDeclarator Declarator
4366   | |-'func3'
4367   | `-ParametersAndQualifiers
4368   |   |-'(' OpenParen
4369   |   |-ParameterDeclarationList Parameters
4370   |   | |-SimpleDeclaration ListElement
4371   |   | | `-'int'
4372   |   | |-',' ListDelimiter
4373   |   | `-SimpleDeclaration ListElement
4374   |   |   `-'float'
4375   |   `-')' CloseParen
4376   `-';'
4377 )txt"));
4378 }
4379 
4380 TEST_P(SyntaxTreeTest,
4381        ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) {
4382   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4383     return;
4384   }
4385   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4386       R"cpp(
4387 template<typename T, typename... Args>
4388 [[void test(T , Args... );]]
4389 )cpp",
4390       {R"txt(
4391 SimpleDeclaration
4392 |-'void'
4393 |-SimpleDeclarator Declarator
4394 | |-'test'
4395 | `-ParametersAndQualifiers
4396 |   |-'(' OpenParen
4397 |   |-ParameterDeclarationList Parameters
4398 |   | |-SimpleDeclaration ListElement
4399 |   | | `-'T'
4400 |   | |-',' ListDelimiter
4401 |   | `-SimpleDeclaration ListElement
4402 |   |   |-'Args'
4403 |   |   `-'...'
4404 |   `-')' CloseParen
4405 `-';'
4406 )txt"}));
4407 }
4408 
4409 TEST_P(SyntaxTreeTest,
4410        ParametersAndQualifiers_InVariadicFunctionTemplate_NamedParameterPack) {
4411   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4412     return;
4413   }
4414   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4415       R"cpp(
4416 template<typename T, typename... Args>
4417 [[void test(T t, Args... args);]]
4418 )cpp",
4419       {R"txt(
4420 SimpleDeclaration
4421 |-'void'
4422 |-SimpleDeclarator Declarator
4423 | |-'test'
4424 | `-ParametersAndQualifiers
4425 |   |-'(' OpenParen
4426 |   |-ParameterDeclarationList Parameters
4427 |   | |-SimpleDeclaration ListElement
4428 |   | | |-'T'
4429 |   | | `-SimpleDeclarator Declarator
4430 |   | |   `-'t'
4431 |   | |-',' ListDelimiter
4432 |   | `-SimpleDeclaration ListElement
4433 |   |   |-'Args'
4434 |   |   |-'...'
4435 |   |   `-SimpleDeclarator Declarator
4436 |   |     `-'args'
4437 |   `-')' CloseParen
4438 `-';'
4439 )txt"}));
4440 }
4441 
4442 TEST_P(SyntaxTreeTest,
4443        ParametersAndQualifiers_InFreeFunctions_VariadicArguments) {
4444   if (!GetParam().isCXX11OrLater()) {
4445     return;
4446   }
4447   EXPECT_TRUE(treeDumpEqual(
4448       R"cpp(
4449 void test(int , char ...);
4450 )cpp",
4451       R"txt(
4452 TranslationUnit Detached
4453 `-SimpleDeclaration
4454   |-'void'
4455   |-SimpleDeclarator Declarator
4456   | |-'test'
4457   | `-ParametersAndQualifiers
4458   |   |-'(' OpenParen
4459   |   |-ParameterDeclarationList Parameters
4460   |   | |-SimpleDeclaration ListElement
4461   |   | | `-'int'
4462   |   | |-',' ListDelimiter
4463   |   | `-SimpleDeclaration ListElement
4464   |   |   `-'char'
4465   |   |-'...'
4466   |   `-')' CloseParen
4467   `-';'
4468 )txt"));
4469 }
4470 
4471 TEST_P(SyntaxTreeTest,
4472        ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
4473   if (!GetParam().isCXX()) {
4474     return;
4475   }
4476   EXPECT_TRUE(treeDumpEqual(
4477       R"cpp(
4478 int func(const int a, volatile int b, const volatile int c);
4479 )cpp",
4480       R"txt(
4481 TranslationUnit Detached
4482 `-SimpleDeclaration
4483   |-'int'
4484   |-SimpleDeclarator Declarator
4485   | |-'func'
4486   | `-ParametersAndQualifiers
4487   |   |-'(' OpenParen
4488   |   |-ParameterDeclarationList Parameters
4489   |   | |-SimpleDeclaration ListElement
4490   |   | | |-'const'
4491   |   | | |-'int'
4492   |   | | `-SimpleDeclarator Declarator
4493   |   | |   `-'a'
4494   |   | |-',' ListDelimiter
4495   |   | |-SimpleDeclaration ListElement
4496   |   | | |-'volatile'
4497   |   | | |-'int'
4498   |   | | `-SimpleDeclarator Declarator
4499   |   | |   `-'b'
4500   |   | |-',' ListDelimiter
4501   |   | `-SimpleDeclaration ListElement
4502   |   |   |-'const'
4503   |   |   |-'volatile'
4504   |   |   |-'int'
4505   |   |   `-SimpleDeclarator Declarator
4506   |   |     `-'c'
4507   |   `-')' CloseParen
4508   `-';'
4509 )txt"));
4510 }
4511 
4512 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
4513   if (!GetParam().isCXX()) {
4514     return;
4515   }
4516   EXPECT_TRUE(treeDumpEqual(
4517       R"cpp(
4518 int func(int& a);
4519 )cpp",
4520       R"txt(
4521 TranslationUnit Detached
4522 `-SimpleDeclaration
4523   |-'int'
4524   |-SimpleDeclarator Declarator
4525   | |-'func'
4526   | `-ParametersAndQualifiers
4527   |   |-'(' OpenParen
4528   |   |-ParameterDeclarationList Parameters
4529   |   | `-SimpleDeclaration ListElement
4530   |   |   |-'int'
4531   |   |   `-SimpleDeclarator Declarator
4532   |   |     |-'&'
4533   |   |     `-'a'
4534   |   `-')' CloseParen
4535   `-';'
4536 )txt"));
4537 }
4538 
4539 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
4540   if (!GetParam().isCXX11OrLater()) {
4541     return;
4542   }
4543   EXPECT_TRUE(treeDumpEqual(
4544       R"cpp(
4545 int func(int&& a);
4546 )cpp",
4547       R"txt(
4548 TranslationUnit Detached
4549 `-SimpleDeclaration
4550   |-'int'
4551   |-SimpleDeclarator Declarator
4552   | |-'func'
4553   | `-ParametersAndQualifiers
4554   |   |-'(' OpenParen
4555   |   |-ParameterDeclarationList Parameters
4556   |   | `-SimpleDeclaration ListElement
4557   |   |   |-'int'
4558   |   |   `-SimpleDeclarator Declarator
4559   |   |     |-'&&'
4560   |   |     `-'a'
4561   |   `-')' CloseParen
4562   `-';'
4563 )txt"));
4564 }
4565 
4566 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
4567   if (!GetParam().isCXX()) {
4568     return;
4569   }
4570   EXPECT_TRUE(treeDumpEqual(
4571       R"cpp(
4572 struct Test {
4573   int a();
4574 };
4575 )cpp",
4576       R"txt(
4577 TranslationUnit Detached
4578 `-SimpleDeclaration
4579   |-'struct'
4580   |-'Test'
4581   |-'{'
4582   |-SimpleDeclaration
4583   | |-'int'
4584   | |-SimpleDeclarator Declarator
4585   | | |-'a'
4586   | | `-ParametersAndQualifiers
4587   | |   |-'(' OpenParen
4588   | |   `-')' CloseParen
4589   | `-';'
4590   |-'}'
4591   `-';'
4592 )txt"));
4593 }
4594 
4595 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
4596   if (!GetParam().isCXX()) {
4597     return;
4598   }
4599   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4600       R"cpp(
4601 struct Test {
4602   [[int b() const;]]
4603   [[int c() volatile;]]
4604   [[int d() const volatile;]]
4605 };
4606 )cpp",
4607       {R"txt(
4608 SimpleDeclaration
4609 |-'int'
4610 |-SimpleDeclarator Declarator
4611 | |-'b'
4612 | `-ParametersAndQualifiers
4613 |   |-'(' OpenParen
4614 |   |-')' CloseParen
4615 |   `-'const'
4616 `-';'
4617 )txt",
4618        R"txt(
4619 SimpleDeclaration
4620 |-'int'
4621 |-SimpleDeclarator Declarator
4622 | |-'c'
4623 | `-ParametersAndQualifiers
4624 |   |-'(' OpenParen
4625 |   |-')' CloseParen
4626 |   `-'volatile'
4627 `-';'
4628 )txt",
4629        R"txt(
4630 SimpleDeclaration
4631 |-'int'
4632 |-SimpleDeclarator Declarator
4633 | |-'d'
4634 | `-ParametersAndQualifiers
4635 |   |-'(' OpenParen
4636 |   |-')' CloseParen
4637 |   |-'const'
4638 |   `-'volatile'
4639 `-';'
4640 )txt"}));
4641 }
4642 
4643 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
4644   if (!GetParam().isCXX11OrLater()) {
4645     return;
4646   }
4647   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4648       R"cpp(
4649 struct Test {
4650   [[int e() &;]]
4651 };
4652 )cpp",
4653       {R"txt(
4654 SimpleDeclaration
4655 |-'int'
4656 |-SimpleDeclarator Declarator
4657 | |-'e'
4658 | `-ParametersAndQualifiers
4659 |   |-'(' OpenParen
4660 |   |-')' CloseParen
4661 |   `-'&'
4662 `-';'
4663 )txt"}));
4664 }
4665 
4666 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
4667   if (!GetParam().isCXX11OrLater()) {
4668     return;
4669   }
4670   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4671       R"cpp(
4672 struct Test {
4673   [[int f() &&;]]
4674 };
4675 )cpp",
4676       {R"txt(
4677 SimpleDeclaration
4678 |-'int'
4679 |-SimpleDeclarator Declarator
4680 | |-'f'
4681 | `-ParametersAndQualifiers
4682 |   |-'(' OpenParen
4683 |   |-')' CloseParen
4684 |   `-'&&'
4685 `-';'
4686 )txt"}));
4687 }
4688 
4689 TEST_P(SyntaxTreeTest, TrailingReturn) {
4690   if (!GetParam().isCXX11OrLater()) {
4691     return;
4692   }
4693   EXPECT_TRUE(treeDumpEqual(
4694       R"cpp(
4695 auto foo() -> int;
4696 )cpp",
4697       R"txt(
4698 TranslationUnit Detached
4699 `-SimpleDeclaration
4700   |-'auto'
4701   |-SimpleDeclarator Declarator
4702   | |-'foo'
4703   | `-ParametersAndQualifiers
4704   |   |-'(' OpenParen
4705   |   |-')' CloseParen
4706   |   `-TrailingReturnType TrailingReturn
4707   |     |-'->' ArrowToken
4708   |     `-'int'
4709   `-';'
4710 )txt"));
4711 }
4712 
4713 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
4714   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
4715     return;
4716   }
4717   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4718       R"cpp(
4719 struct MyException1 {};
4720 struct MyException2 {};
4721 [[int a() throw();]]
4722 [[int b() throw(...);]]
4723 [[int c() throw(MyException1);]]
4724 [[int d() throw(MyException1, MyException2);]]
4725 )cpp",
4726       {R"txt(
4727 SimpleDeclaration
4728 |-'int'
4729 |-SimpleDeclarator Declarator
4730 | |-'a'
4731 | `-ParametersAndQualifiers
4732 |   |-'(' OpenParen
4733 |   |-')' CloseParen
4734 |   |-'throw'
4735 |   |-'('
4736 |   `-')'
4737 `-';'
4738 )txt",
4739        R"txt(
4740 SimpleDeclaration
4741 |-'int'
4742 |-SimpleDeclarator Declarator
4743 | |-'b'
4744 | `-ParametersAndQualifiers
4745 |   |-'(' OpenParen
4746 |   |-')' CloseParen
4747 |   |-'throw'
4748 |   |-'('
4749 |   |-'...'
4750 |   `-')'
4751 `-';'
4752 )txt",
4753        R"txt(
4754 SimpleDeclaration
4755 |-'int'
4756 |-SimpleDeclarator Declarator
4757 | |-'c'
4758 | `-ParametersAndQualifiers
4759 |   |-'(' OpenParen
4760 |   |-')' CloseParen
4761 |   |-'throw'
4762 |   |-'('
4763 |   |-'MyException1'
4764 |   `-')'
4765 `-';'
4766 )txt",
4767        R"txt(
4768 SimpleDeclaration
4769 |-'int'
4770 |-SimpleDeclarator Declarator
4771 | |-'d'
4772 | `-ParametersAndQualifiers
4773 |   |-'(' OpenParen
4774 |   |-')' CloseParen
4775 |   |-'throw'
4776 |   |-'('
4777 |   |-'MyException1'
4778 |   |-','
4779 |   |-'MyException2'
4780 |   `-')'
4781 `-';'
4782 )txt"}));
4783 }
4784 
4785 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
4786   if (!GetParam().isCXX11OrLater()) {
4787     return;
4788   }
4789   EXPECT_TRUE(treeDumpEqual(
4790       R"cpp(
4791 int a() noexcept;
4792 int b() noexcept(true);
4793 )cpp",
4794       R"txt(
4795 TranslationUnit Detached
4796 |-SimpleDeclaration
4797 | |-'int'
4798 | |-SimpleDeclarator Declarator
4799 | | |-'a'
4800 | | `-ParametersAndQualifiers
4801 | |   |-'(' OpenParen
4802 | |   |-')' CloseParen
4803 | |   `-'noexcept'
4804 | `-';'
4805 `-SimpleDeclaration
4806   |-'int'
4807   |-SimpleDeclarator Declarator
4808   | |-'b'
4809   | `-ParametersAndQualifiers
4810   |   |-'(' OpenParen
4811   |   |-')' CloseParen
4812   |   |-'noexcept'
4813   |   |-'('
4814   |   |-BoolLiteralExpression
4815   |   | `-'true' LiteralToken
4816   |   `-')'
4817   `-';'
4818 )txt"));
4819 }
4820 
4821 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
4822   EXPECT_TRUE(treeDumpEqual(
4823       R"cpp(
4824 int (a);
4825 int *(b);
4826 int (*c)(int);
4827 int *(d)(int);
4828 )cpp",
4829       R"txt(
4830 TranslationUnit Detached
4831 |-SimpleDeclaration
4832 | |-'int'
4833 | |-SimpleDeclarator Declarator
4834 | | `-ParenDeclarator
4835 | |   |-'(' OpenParen
4836 | |   |-'a'
4837 | |   `-')' CloseParen
4838 | `-';'
4839 |-SimpleDeclaration
4840 | |-'int'
4841 | |-SimpleDeclarator Declarator
4842 | | |-'*'
4843 | | `-ParenDeclarator
4844 | |   |-'(' OpenParen
4845 | |   |-'b'
4846 | |   `-')' CloseParen
4847 | `-';'
4848 |-SimpleDeclaration
4849 | |-'int'
4850 | |-SimpleDeclarator Declarator
4851 | | |-ParenDeclarator
4852 | | | |-'(' OpenParen
4853 | | | |-'*'
4854 | | | |-'c'
4855 | | | `-')' CloseParen
4856 | | `-ParametersAndQualifiers
4857 | |   |-'(' OpenParen
4858 | |   |-ParameterDeclarationList Parameters
4859 | |   | `-SimpleDeclaration ListElement
4860 | |   |   `-'int'
4861 | |   `-')' CloseParen
4862 | `-';'
4863 `-SimpleDeclaration
4864   |-'int'
4865   |-SimpleDeclarator Declarator
4866   | |-'*'
4867   | |-ParenDeclarator
4868   | | |-'(' OpenParen
4869   | | |-'d'
4870   | | `-')' CloseParen
4871   | `-ParametersAndQualifiers
4872   |   |-'(' OpenParen
4873   |   |-ParameterDeclarationList Parameters
4874   |   | `-SimpleDeclaration ListElement
4875   |   |   `-'int'
4876   |   `-')' CloseParen
4877   `-';'
4878 )txt"));
4879 }
4880 
4881 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
4882   EXPECT_TRUE(treeDumpEqual(
4883       R"cpp(
4884 const int west = -1;
4885 int const east = 1;
4886 )cpp",
4887       R"txt(
4888 TranslationUnit Detached
4889 |-SimpleDeclaration
4890 | |-'const'
4891 | |-'int'
4892 | |-SimpleDeclarator Declarator
4893 | | |-'west'
4894 | | |-'='
4895 | | `-PrefixUnaryOperatorExpression
4896 | |   |-'-' OperatorToken
4897 | |   `-IntegerLiteralExpression Operand
4898 | |     `-'1' LiteralToken
4899 | `-';'
4900 `-SimpleDeclaration
4901   |-'int'
4902   |-'const'
4903   |-SimpleDeclarator Declarator
4904   | |-'east'
4905   | |-'='
4906   | `-IntegerLiteralExpression
4907   |   `-'1' LiteralToken
4908   `-';'
4909 )txt"));
4910 }
4911 
4912 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
4913   EXPECT_TRUE(treeDumpEqual(
4914       R"cpp(
4915 const int const universal = 0;
4916 )cpp",
4917       R"txt(
4918 TranslationUnit Detached
4919 `-SimpleDeclaration
4920   |-'const'
4921   |-'int'
4922   |-'const'
4923   |-SimpleDeclarator Declarator
4924   | |-'universal'
4925   | |-'='
4926   | `-IntegerLiteralExpression
4927   |   `-'0' LiteralToken
4928   `-';'
4929 )txt"));
4930 }
4931 
4932 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
4933   EXPECT_TRUE(treeDumpEqual(
4934       R"cpp(
4935 const int const *const *volatile b;
4936 )cpp",
4937       R"txt(
4938 TranslationUnit Detached
4939 `-SimpleDeclaration
4940   |-'const'
4941   |-'int'
4942   |-'const'
4943   |-SimpleDeclarator Declarator
4944   | |-'*'
4945   | |-'const'
4946   | |-'*'
4947   | |-'volatile'
4948   | `-'b'
4949   `-';'
4950 )txt"));
4951 }
4952 
4953 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
4954   if (!GetParam().isCXX11OrLater()) {
4955     return;
4956   }
4957   EXPECT_TRUE(treeDumpEqual(
4958       R"cpp(
4959 auto foo() -> auto(*)(int) -> double*;
4960 )cpp",
4961       R"txt(
4962 TranslationUnit Detached
4963 `-SimpleDeclaration
4964   |-'auto'
4965   |-SimpleDeclarator Declarator
4966   | |-'foo'
4967   | `-ParametersAndQualifiers
4968   |   |-'(' OpenParen
4969   |   |-')' CloseParen
4970   |   `-TrailingReturnType TrailingReturn
4971   |     |-'->' ArrowToken
4972   |     |-'auto'
4973   |     `-SimpleDeclarator Declarator
4974   |       |-ParenDeclarator
4975   |       | |-'(' OpenParen
4976   |       | |-'*'
4977   |       | `-')' CloseParen
4978   |       `-ParametersAndQualifiers
4979   |         |-'(' OpenParen
4980   |         |-ParameterDeclarationList Parameters
4981   |         | `-SimpleDeclaration ListElement
4982   |         |   `-'int'
4983   |         |-')' CloseParen
4984   |         `-TrailingReturnType TrailingReturn
4985   |           |-'->' ArrowToken
4986   |           |-'double'
4987   |           `-SimpleDeclarator Declarator
4988   |             `-'*'
4989   `-';'
4990 )txt"));
4991 }
4992 
4993 TEST_P(SyntaxTreeTest, MemberPointers) {
4994   if (!GetParam().isCXX()) {
4995     return;
4996   }
4997   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4998       R"cpp(
4999 struct X {};
5000 [[int X::* a;]]
5001 [[const int X::* b;]]
5002 )cpp",
5003       {R"txt(
5004 SimpleDeclaration
5005 |-'int'
5006 |-SimpleDeclarator Declarator
5007 | |-MemberPointer
5008 | | |-'X'
5009 | | |-'::'
5010 | | `-'*'
5011 | `-'a'
5012 `-';'
5013 )txt",
5014        R"txt(
5015 SimpleDeclaration
5016 |-'const'
5017 |-'int'
5018 |-SimpleDeclarator Declarator
5019 | |-MemberPointer
5020 | | |-'X'
5021 | | |-'::'
5022 | | `-'*'
5023 | `-'b'
5024 `-';'
5025 )txt"}));
5026 }
5027 
5028 TEST_P(SyntaxTreeTest, MemberFunctionPointer) {
5029   if (!GetParam().isCXX()) {
5030     return;
5031   }
5032   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5033       R"cpp(
5034 struct X {
5035   struct Y {};
5036 };
5037 [[void (X::*xp)();]]
5038 [[void (X::**xpp)(const int*);]]
5039 // FIXME: Generate the right syntax tree for this type,
5040 // i.e. create a syntax node for the outer member pointer
5041 [[void (X::Y::*xyp)(const int*, char);]]
5042 )cpp",
5043       {R"txt(
5044 SimpleDeclaration
5045 |-'void'
5046 |-SimpleDeclarator Declarator
5047 | |-ParenDeclarator
5048 | | |-'(' OpenParen
5049 | | |-MemberPointer
5050 | | | |-'X'
5051 | | | |-'::'
5052 | | | `-'*'
5053 | | |-'xp'
5054 | | `-')' CloseParen
5055 | `-ParametersAndQualifiers
5056 |   |-'(' OpenParen
5057 |   `-')' CloseParen
5058 `-';'
5059 )txt",
5060        R"txt(
5061 SimpleDeclaration
5062 |-'void'
5063 |-SimpleDeclarator Declarator
5064 | |-ParenDeclarator
5065 | | |-'(' OpenParen
5066 | | |-MemberPointer
5067 | | | |-'X'
5068 | | | |-'::'
5069 | | | `-'*'
5070 | | |-'*'
5071 | | |-'xpp'
5072 | | `-')' CloseParen
5073 | `-ParametersAndQualifiers
5074 |   |-'(' OpenParen
5075 |   |-ParameterDeclarationList Parameters
5076 |   | `-SimpleDeclaration ListElement
5077 |   |   |-'const'
5078 |   |   |-'int'
5079 |   |   `-SimpleDeclarator Declarator
5080 |   |     `-'*'
5081 |   `-')' CloseParen
5082 `-';'
5083 )txt",
5084        R"txt(
5085 SimpleDeclaration
5086 |-'void'
5087 |-SimpleDeclarator Declarator
5088 | |-ParenDeclarator
5089 | | |-'(' OpenParen
5090 | | |-'X'
5091 | | |-'::'
5092 | | |-MemberPointer
5093 | | | |-'Y'
5094 | | | |-'::'
5095 | | | `-'*'
5096 | | |-'xyp'
5097 | | `-')' CloseParen
5098 | `-ParametersAndQualifiers
5099 |   |-'(' OpenParen
5100 |   |-ParameterDeclarationList Parameters
5101 |   | |-SimpleDeclaration ListElement
5102 |   | | |-'const'
5103 |   | | |-'int'
5104 |   | | `-SimpleDeclarator Declarator
5105 |   | |   `-'*'
5106 |   | |-',' ListDelimiter
5107 |   | `-SimpleDeclaration ListElement
5108 |   |   `-'char'
5109 |   `-')' CloseParen
5110 `-';'
5111 )txt"}));
5112 }
5113 
5114 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
5115   EXPECT_TRUE(treeDumpEqual(
5116       R"cpp(
5117 void x(char a, short (*b)(int));
5118 )cpp",
5119       R"txt(
5120 TranslationUnit Detached
5121 `-SimpleDeclaration
5122   |-'void'
5123   |-SimpleDeclarator Declarator
5124   | |-'x'
5125   | `-ParametersAndQualifiers
5126   |   |-'(' OpenParen
5127   |   |-ParameterDeclarationList Parameters
5128   |   | |-SimpleDeclaration ListElement
5129   |   | | |-'char'
5130   |   | | `-SimpleDeclarator Declarator
5131   |   | |   `-'a'
5132   |   | |-',' ListDelimiter
5133   |   | `-SimpleDeclaration ListElement
5134   |   |   |-'short'
5135   |   |   `-SimpleDeclarator Declarator
5136   |   |     |-ParenDeclarator
5137   |   |     | |-'(' OpenParen
5138   |   |     | |-'*'
5139   |   |     | |-'b'
5140   |   |     | `-')' CloseParen
5141   |   |     `-ParametersAndQualifiers
5142   |   |       |-'(' OpenParen
5143   |   |       |-ParameterDeclarationList Parameters
5144   |   |       | `-SimpleDeclaration ListElement
5145   |   |       |   `-'int'
5146   |   |       `-')' CloseParen
5147   |   `-')' CloseParen
5148   `-';'
5149 )txt"));
5150 }
5151 
5152 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
5153   EXPECT_TRUE(treeDumpEqual(
5154       R"cpp(
5155 void x(char a, short (*b)(int), long (**c)(long long));
5156 )cpp",
5157       R"txt(
5158 TranslationUnit Detached
5159 `-SimpleDeclaration
5160   |-'void'
5161   |-SimpleDeclarator Declarator
5162   | |-'x'
5163   | `-ParametersAndQualifiers
5164   |   |-'(' OpenParen
5165   |   |-ParameterDeclarationList Parameters
5166   |   | |-SimpleDeclaration ListElement
5167   |   | | |-'char'
5168   |   | | `-SimpleDeclarator Declarator
5169   |   | |   `-'a'
5170   |   | |-',' ListDelimiter
5171   |   | |-SimpleDeclaration ListElement
5172   |   | | |-'short'
5173   |   | | `-SimpleDeclarator Declarator
5174   |   | |   |-ParenDeclarator
5175   |   | |   | |-'(' OpenParen
5176   |   | |   | |-'*'
5177   |   | |   | |-'b'
5178   |   | |   | `-')' CloseParen
5179   |   | |   `-ParametersAndQualifiers
5180   |   | |     |-'(' OpenParen
5181   |   | |     |-ParameterDeclarationList Parameters
5182   |   | |     | `-SimpleDeclaration ListElement
5183   |   | |     |   `-'int'
5184   |   | |     `-')' CloseParen
5185   |   | |-',' ListDelimiter
5186   |   | `-SimpleDeclaration ListElement
5187   |   |   |-'long'
5188   |   |   `-SimpleDeclarator Declarator
5189   |   |     |-ParenDeclarator
5190   |   |     | |-'(' OpenParen
5191   |   |     | |-'*'
5192   |   |     | |-'*'
5193   |   |     | |-'c'
5194   |   |     | `-')' CloseParen
5195   |   |     `-ParametersAndQualifiers
5196   |   |       |-'(' OpenParen
5197   |   |       |-ParameterDeclarationList Parameters
5198   |   |       | `-SimpleDeclaration ListElement
5199   |   |       |   |-'long'
5200   |   |       |   `-'long'
5201   |   |       `-')' CloseParen
5202   |   `-')' CloseParen
5203   `-';'
5204 )txt"));
5205 }
5206 
5207 } // namespace
5208