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