xref: /llvm-project/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp (revision dc3d4743277b47c0bc8cddbeb4b5e265252ee304)
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 SimpleDeclaration_declarator
31 | | |-'main'
32 | | `-ParametersAndQualifiers
33 | |   |-'(' OpenParen
34 | |   `-')' CloseParen
35 | `-CompoundStatement
36 |   |-'{' OpenParen
37 |   `-'}' CloseParen
38 `-SimpleDeclaration
39   |-'void'
40   |-SimpleDeclarator SimpleDeclaration_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 SimpleDeclaration_declarator
62 | | `-'a'
63 | `-';'
64 `-SimpleDeclaration
65   |-'int'
66   |-SimpleDeclarator SimpleDeclaration_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 SimpleDeclaration_declarator
85   | |-'foo'
86   | `-ParametersAndQualifiers
87   |   |-'(' OpenParen
88   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
89   |   | |-SimpleDeclaration List_element
90   |   | | |-'int'
91   |   | | `-SimpleDeclarator SimpleDeclaration_declarator
92   |   | |   `-'a'
93   |   | |-',' List_delimiter
94   |   | `-SimpleDeclaration List_element
95   |   |   |-'int'
96   |   |   `-SimpleDeclarator SimpleDeclaration_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 CompoundStatement_statement
115 |-'if' IntroducerKeyword
116 |-'('
117 |-IntegerLiteralExpression
118 | `-'1' LiteralToken
119 |-')'
120 `-CompoundStatement IfStatement_thenStatement
121   |-'{' OpenParen
122   `-'}' CloseParen
123   )txt",
124        R"txt(
125 IfStatement CompoundStatement_statement
126 |-'if' IntroducerKeyword
127 |-'('
128 |-IntegerLiteralExpression
129 | `-'1' LiteralToken
130 |-')'
131 |-CompoundStatement IfStatement_thenStatement
132 | |-'{' OpenParen
133 | `-'}' CloseParen
134 |-'else' IfStatement_elseKeyword
135 `-IfStatement IfStatement_elseStatement
136   |-'if' IntroducerKeyword
137   |-'('
138   |-IntegerLiteralExpression
139   | `-'0' LiteralToken
140   |-')'
141   `-CompoundStatement IfStatement_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 CompoundStatement_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 CompoundStatement_statement
181 |-'for' IntroducerKeyword
182 |-'('
183 |-SimpleDeclaration
184 | |-'int'
185 | |-SimpleDeclarator SimpleDeclaration_declarator
186 | | `-'x'
187 | `-':'
188 |-IdExpression
189 | `-UnqualifiedId IdExpression_id
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 CompoundStatement_statement
206 |-SimpleDeclaration
207 | |-'int'
208 | `-SimpleDeclarator SimpleDeclaration_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 CompoundStatement_statement
229 |-'switch' IntroducerKeyword
230 |-'('
231 |-IntegerLiteralExpression
232 | `-'1' LiteralToken
233 |-')'
234 `-CompoundStatement BodyStatement
235   |-'{' OpenParen
236   |-CaseStatement CompoundStatement_statement
237   | |-'case' IntroducerKeyword
238   | |-IntegerLiteralExpression CaseStatement_value
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 CompoundStatement_statement
259 |-'while' IntroducerKeyword
260 |-'('
261 |-IntegerLiteralExpression
262 | `-'1' LiteralToken
263 |-')'
264 `-CompoundStatement BodyStatement
265   |-'{' OpenParen
266   |-ContinueStatement CompoundStatement_statement
267   | |-'continue' IntroducerKeyword
268   | `-';'
269   |-BreakStatement CompoundStatement_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 CompoundStatement_statement
288 |-'foo'
289 |-':'
290 `-ReturnStatement
291   |-'return' IntroducerKeyword
292   |-IntegerLiteralExpression ReturnStatement_value
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 SimpleDeclaration_declarator
313   | |-'test'
314   | `-ParametersAndQualifiers
315   |   |-'(' OpenParen
316   |   `-')' CloseParen
317   `-CompoundStatement
318     |-'{' OpenParen
319     |-ExpressionStatement CompoundStatement_statement
320     | |-CallExpression ExpressionStatement_expression
321     | | |-IdExpression CallExpression_callee
322     | | | `-UnqualifiedId IdExpression_id
323     | | |   `-'test'
324     | | |-'(' OpenParen
325     | | `-')' CloseParen
326     | `-';'
327     |-IfStatement CompoundStatement_statement
328     | |-'if' IntroducerKeyword
329     | |-'('
330     | |-IntegerLiteralExpression
331     | | `-'1' LiteralToken
332     | |-')'
333     | |-ExpressionStatement IfStatement_thenStatement
334     | | |-CallExpression ExpressionStatement_expression
335     | | | |-IdExpression CallExpression_callee
336     | | | | `-UnqualifiedId IdExpression_id
337     | | | |   `-'test'
338     | | | |-'(' OpenParen
339     | | | `-')' CloseParen
340     | | `-';'
341     | |-'else' IfStatement_elseKeyword
342     | `-ExpressionStatement IfStatement_elseStatement
343     |   |-CallExpression ExpressionStatement_expression
344     |   | |-IdExpression CallExpression_callee
345     |   | | `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
363 `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
383 |-IdExpression CallExpression_callee
384 | `-UnqualifiedId IdExpression_id
385 |   |-'operator'
386 |   `-'+'
387 |-'(' OpenParen
388 |-CallArguments CallExpression_arguments
389 | |-IdExpression List_element
390 | | `-UnqualifiedId IdExpression_id
391 | |   `-'x'
392 | |-',' List_delimiter
393 | `-IdExpression List_element
394 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
415 |-MemberExpression CallExpression_callee
416 | |-IdExpression MemberExpression_object
417 | | `-UnqualifiedId IdExpression_id
418 | |   `-'x'
419 | |-'.' MemberExpression_accessToken
420 | `-IdExpression MemberExpression_member
421 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
442 |-IdExpression CallExpression_callee
443 | `-UnqualifiedId IdExpression_id
444 |   |-'operator'
445 |   |-'""'
446 |   `-'_w'
447 |-'(' OpenParen
448 |-CallArguments CallExpression_arguments
449 | `-CharacterLiteralExpression List_element
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 ExpressionStatement_expression
468 |-MemberExpression CallExpression_callee
469 | |-IdExpression MemberExpression_object
470 | | `-UnqualifiedId IdExpression_id
471 | |   `-'x'
472 | |-'.' MemberExpression_accessToken
473 | `-IdExpression MemberExpression_member
474 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
499 |-MemberExpression CallExpression_callee
500 | |-IdExpression MemberExpression_object
501 | | `-UnqualifiedId IdExpression_id
502 | |   `-'x'
503 | |-'.' MemberExpression_accessToken
504 | `-IdExpression MemberExpression_member
505 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
530 |-IdExpression CallExpression_callee
531 | `-UnqualifiedId IdExpression_id
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 | |-'::' List_delimiter
562 | |-IdentifierNameSpecifier List_element
563 | | `-'n'
564 | `-'::' List_delimiter
565 |-'S'
566 `-SimpleDeclarator SimpleDeclaration_declarator
567   `-UnknownExpression
568     `-'s1'
569 )txt",
570        R"txt(
571 SimpleDeclaration
572 |-NestedNameSpecifier
573 | |-IdentifierNameSpecifier List_element
574 | | `-'n'
575 | `-'::' List_delimiter
576 |-'S'
577 `-SimpleDeclarator SimpleDeclaration_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 | |-'::' List_delimiter
602 | |-SimpleTemplateNameSpecifier List_element
603 | | |-'template'
604 | | |-'ST'
605 | | |-'<'
606 | | |-'int'
607 | | `-'>'
608 | `-'::' List_delimiter
609 |-'S'
610 `-SimpleDeclarator SimpleDeclaration_declarator
611   `-UnknownExpression
612     `-'s1'
613 )txt",
614        R"txt(
615 SimpleDeclaration
616 |-NestedNameSpecifier
617 | |-'::' List_delimiter
618 | |-SimpleTemplateNameSpecifier List_element
619 | | |-'ST'
620 | | |-'<'
621 | | |-'int'
622 | | `-'>'
623 | `-'::' List_delimiter
624 |-'S'
625 `-SimpleDeclarator SimpleDeclaration_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 ExpressionStatement_expression
646 |-IdExpression CallExpression_callee
647 | |-NestedNameSpecifier IdExpression_qualifier
648 | | |-DecltypeNameSpecifier List_element
649 | | | |-'decltype'
650 | | | |-'('
651 | | | |-IdExpression
652 | | | | `-UnqualifiedId IdExpression_id
653 | | | |   `-'s'
654 | | | `-')'
655 | | `-'::' List_delimiter
656 | `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
680 |-IdExpression CallExpression_callee
681 | |-NestedNameSpecifier IdExpression_qualifier
682 | | |-IdentifierNameSpecifier List_element
683 | | | `-'S'
684 | | `-'::' List_delimiter
685 | `-UnqualifiedId IdExpression_id
686 |   |-'f'
687 |   |-'<'
688 |   |-'int'
689 |   `-'>'
690 |-'(' OpenParen
691 `-')' CloseParen
692 )txt",
693        R"txt(
694 CallExpression ExpressionStatement_expression
695 |-IdExpression CallExpression_callee
696 | |-NestedNameSpecifier IdExpression_qualifier
697 | | |-IdentifierNameSpecifier List_element
698 | | | `-'S'
699 | | `-'::' List_delimiter
700 | |-'template' TemplateKeyword
701 | `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
730 |-IdExpression CallExpression_callee
731 | |-NestedNameSpecifier IdExpression_qualifier
732 | | |-'::' List_delimiter
733 | | |-IdentifierNameSpecifier List_element
734 | | | `-'n'
735 | | |-'::' List_delimiter
736 | | |-SimpleTemplateNameSpecifier List_element
737 | | | |-'template'
738 | | | |-'ST'
739 | | | |-'<'
740 | | | |-'int'
741 | | | `-'>'
742 | | `-'::' List_delimiter
743 | |-'template' TemplateKeyword
744 | `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
774 |-IdExpression CallExpression_callee
775 | |-NestedNameSpecifier IdExpression_qualifier
776 | | |-IdentifierNameSpecifier List_element
777 | | | `-'T'
778 | | |-'::' List_delimiter
779 | | |-SimpleTemplateNameSpecifier List_element
780 | | | |-'template'
781 | | | |-'U'
782 | | | |-'<'
783 | | | |-'int'
784 | | | `-'>'
785 | | `-'::' List_delimiter
786 | `-UnqualifiedId IdExpression_id
787 |   `-'f'
788 |-'(' OpenParen
789 `-')' CloseParen
790 )txt",
791        R"txt(
792 CallExpression ExpressionStatement_expression
793 |-IdExpression CallExpression_callee
794 | |-NestedNameSpecifier IdExpression_qualifier
795 | | |-IdentifierNameSpecifier List_element
796 | | | `-'T'
797 | | |-'::' List_delimiter
798 | | |-IdentifierNameSpecifier List_element
799 | | | `-'U'
800 | | `-'::' List_delimiter
801 | `-UnqualifiedId IdExpression_id
802 |   `-'f'
803 |-'(' OpenParen
804 `-')' CloseParen
805 )txt",
806        R"txt(
807 CallExpression ExpressionStatement_expression
808 |-IdExpression CallExpression_callee
809 | |-NestedNameSpecifier IdExpression_qualifier
810 | | |-IdentifierNameSpecifier List_element
811 | | | `-'T'
812 | | `-'::' List_delimiter
813 | |-'template' TemplateKeyword
814 | `-UnqualifiedId IdExpression_id
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 ReturnStatement_value
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 ExpressionStatement_expression
858 |-ThisExpression MemberExpression_object
859 | `-'this' IntroducerKeyword
860 |-'->' MemberExpression_accessToken
861 `-IdExpression MemberExpression_member
862   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
882 `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
898 |-'(' OpenParen
899 |-IntegerLiteralExpression ParenExpression_subExpression
900 | `-'1' LiteralToken
901 `-')' CloseParen
902 )txt",
903        R"txt(
904 ParenExpression ExpressionStatement_expression
905 |-'(' OpenParen
906 |-ParenExpression ParenExpression_subExpression
907 | |-'(' OpenParen
908 | |-IntegerLiteralExpression ParenExpression_subExpression
909 | | `-'1' LiteralToken
910 | `-')' CloseParen
911 `-')' CloseParen
912 )txt",
913        R"txt(
914 ParenExpression ExpressionStatement_expression
915 |-'(' OpenParen
916 |-BinaryOperatorExpression ParenExpression_subExpression
917 | |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
918 | | `-'1' LiteralToken
919 | |-'+' OperatorExpression_operatorToken
920 | `-ParenExpression BinaryOperatorExpression_rightHandSide
921 |   |-'(' OpenParen
922 |   |-IntegerLiteralExpression ParenExpression_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 ExpressionStatement_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 ExpressionStatement_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 ExpressionStatement_expression
985 `-'12_i' LiteralToken
986 )txt",
987        R"txt(
988 IntegerUserDefinedLiteralExpression ExpressionStatement_expression
989 `-'12_r' LiteralToken
990 )txt",
991        R"txt(
992 IntegerUserDefinedLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1016 `-'1.2_f' LiteralToken
1017 )txt",
1018        R"txt(
1019 FloatUserDefinedLiteralExpression ExpressionStatement_expression
1020 `-'1.2_r' LiteralToken
1021 )txt",
1022        R"txt(
1023 FloatUserDefinedLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1041 `-'12ll' LiteralToken
1042 )txt",
1043        R"txt(
1044 IntegerLiteralExpression ExpressionStatement_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 ExpressionStatement_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 ExpressionStatement_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 ExpressionStatement_expression
1095 `-''a'' LiteralToken
1096 )txt",
1097        R"txt(
1098 CharacterLiteralExpression ExpressionStatement_expression
1099 `-''\n'' LiteralToken
1100 )txt",
1101        R"txt(
1102 CharacterLiteralExpression ExpressionStatement_expression
1103 `-''\x20'' LiteralToken
1104 )txt",
1105        R"txt(
1106 CharacterLiteralExpression ExpressionStatement_expression
1107 `-''\0'' LiteralToken
1108 )txt",
1109        R"txt(
1110 CharacterLiteralExpression ExpressionStatement_expression
1111 `-'L'a'' LiteralToken
1112 )txt",
1113        R"txt(
1114 CharacterLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1134 `-'u'a'' LiteralToken
1135 )txt",
1136        R"txt(
1137 CharacterLiteralExpression ExpressionStatement_expression
1138 `-'u'構'' LiteralToken
1139 )txt",
1140        R"txt(
1141 CharacterLiteralExpression ExpressionStatement_expression
1142 `-'U'a'' LiteralToken
1143 )txt",
1144        R"txt(
1145 CharacterLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1163 `-'u8'a'' LiteralToken
1164 )txt",
1165        R"txt(
1166 CharacterLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1183 `-'1e-2' LiteralToken
1184 )txt",
1185        R"txt(
1186 FloatingLiteralExpression ExpressionStatement_expression
1187 `-'2.' LiteralToken
1188 )txt",
1189        R"txt(
1190 FloatingLiteralExpression ExpressionStatement_expression
1191 `-'.2' LiteralToken
1192 )txt",
1193        R"txt(
1194 FloatingLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1214 `-'0xfp1' LiteralToken
1215 )txt",
1216        R"txt(
1217 FloatingLiteralExpression ExpressionStatement_expression
1218 `-'0xf.p1' LiteralToken
1219 )txt",
1220        R"txt(
1221 FloatingLiteralExpression ExpressionStatement_expression
1222 `-'0x.fp1' LiteralToken
1223 )txt",
1224        R"txt(
1225 FloatingLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1240 `-'"a\n\0\x20"' LiteralToken
1241 )txt",
1242        R"txt(
1243 StringLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1262 `-'u8"a\x1f\x05"' LiteralToken
1263 )txt",
1264        R"txt(
1265 StringLiteralExpression ExpressionStatement_expression
1266 `-'u"C++抽象構文木"' LiteralToken
1267 )txt",
1268        R"txt(
1269 StringLiteralExpression ExpressionStatement_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 SimpleDeclaration_declarator\n"
1292       "  | |-'test'\n"
1293       "  | `-ParametersAndQualifiers\n"
1294       "  |   |-'(' OpenParen\n"
1295       "  |   `-')' CloseParen\n"
1296       "  `-CompoundStatement\n"
1297       "    |-'{' OpenParen\n"
1298       "    |-ExpressionStatement CompoundStatement_statement\n"
1299       "    | |-StringLiteralExpression ExpressionStatement_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 ExpressionStatement_expression
1320 `-'true' LiteralToken
1321 )txt",
1322        R"txt(
1323 BoolLiteralExpression ExpressionStatement_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 ExpressionStatement_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 ExpressionStatement_expression
1354 |-IdExpression UnaryOperatorExpression_operand
1355 | `-UnqualifiedId IdExpression_id
1356 |   `-'a'
1357 `-'++' OperatorExpression_operatorToken
1358 )txt",
1359        R"txt(
1360 PostfixUnaryOperatorExpression ExpressionStatement_expression
1361 |-IdExpression UnaryOperatorExpression_operand
1362 | `-UnqualifiedId IdExpression_id
1363 |   `-'a'
1364 `-'--' OperatorExpression_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 ExpressionStatement_expression
1384 |-'--' OperatorExpression_operatorToken
1385 `-IdExpression UnaryOperatorExpression_operand
1386   `-UnqualifiedId IdExpression_id
1387     `-'a'
1388 )txt",
1389        R"txt(
1390 PrefixUnaryOperatorExpression ExpressionStatement_expression
1391 |-'++' OperatorExpression_operatorToken
1392 `-IdExpression UnaryOperatorExpression_operand
1393   `-UnqualifiedId IdExpression_id
1394     `-'a'
1395 )txt",
1396        R"txt(
1397 PrefixUnaryOperatorExpression ExpressionStatement_expression
1398 |-'~' OperatorExpression_operatorToken
1399 `-IdExpression UnaryOperatorExpression_operand
1400   `-UnqualifiedId IdExpression_id
1401     `-'a'
1402 )txt",
1403        R"txt(
1404 PrefixUnaryOperatorExpression ExpressionStatement_expression
1405 |-'-' OperatorExpression_operatorToken
1406 `-IdExpression UnaryOperatorExpression_operand
1407   `-UnqualifiedId IdExpression_id
1408     `-'a'
1409 )txt",
1410        R"txt(
1411 PrefixUnaryOperatorExpression ExpressionStatement_expression
1412 |-'+' OperatorExpression_operatorToken
1413 `-IdExpression UnaryOperatorExpression_operand
1414   `-UnqualifiedId IdExpression_id
1415     `-'a'
1416 )txt",
1417        R"txt(
1418 PrefixUnaryOperatorExpression ExpressionStatement_expression
1419 |-'&' OperatorExpression_operatorToken
1420 `-IdExpression UnaryOperatorExpression_operand
1421   `-UnqualifiedId IdExpression_id
1422     `-'a'
1423 )txt",
1424        R"txt(
1425 PrefixUnaryOperatorExpression ExpressionStatement_expression
1426 |-'*' OperatorExpression_operatorToken
1427 `-IdExpression UnaryOperatorExpression_operand
1428   `-UnqualifiedId IdExpression_id
1429     `-'ap'
1430 )txt",
1431        R"txt(
1432 PrefixUnaryOperatorExpression ExpressionStatement_expression
1433 |-'!' OperatorExpression_operatorToken
1434 `-IdExpression UnaryOperatorExpression_operand
1435   `-UnqualifiedId IdExpression_id
1436     `-'a'
1437 )txt",
1438        R"txt(
1439 PrefixUnaryOperatorExpression ExpressionStatement_expression
1440 |-'__real' OperatorExpression_operatorToken
1441 `-IdExpression UnaryOperatorExpression_operand
1442   `-UnqualifiedId IdExpression_id
1443     `-'a'
1444 )txt",
1445        R"txt(
1446 PrefixUnaryOperatorExpression ExpressionStatement_expression
1447 |-'__imag' OperatorExpression_operatorToken
1448 `-IdExpression UnaryOperatorExpression_operand
1449   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1467 |-'compl' OperatorExpression_operatorToken
1468 `-IdExpression UnaryOperatorExpression_operand
1469   `-UnqualifiedId IdExpression_id
1470     `-'a'
1471 )txt",
1472        R"txt(
1473 PrefixUnaryOperatorExpression ExpressionStatement_expression
1474 |-'not' OperatorExpression_operatorToken
1475 `-IdExpression UnaryOperatorExpression_operand
1476   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1496 |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1497 | `-'1' LiteralToken
1498 |-'-' OperatorExpression_operatorToken
1499 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1500   `-'2' LiteralToken
1501 )txt",
1502        R"txt(
1503 BinaryOperatorExpression ExpressionStatement_expression
1504 |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1505 | `-'1' LiteralToken
1506 |-'==' OperatorExpression_operatorToken
1507 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1508   `-'2' LiteralToken
1509 )txt",
1510        R"txt(
1511 BinaryOperatorExpression ExpressionStatement_expression
1512 |-IdExpression BinaryOperatorExpression_leftHandSide
1513 | `-UnqualifiedId IdExpression_id
1514 |   `-'a'
1515 |-'=' OperatorExpression_operatorToken
1516 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1517   `-'1' LiteralToken
1518 )txt",
1519        R"txt(
1520 BinaryOperatorExpression ExpressionStatement_expression
1521 |-IdExpression BinaryOperatorExpression_leftHandSide
1522 | `-UnqualifiedId IdExpression_id
1523 |   `-'a'
1524 |-'<<=' OperatorExpression_operatorToken
1525 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1526   `-'1' LiteralToken
1527 )txt",
1528        R"txt(
1529 BinaryOperatorExpression ExpressionStatement_expression
1530 |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1531 | `-'1' LiteralToken
1532 |-'||' OperatorExpression_operatorToken
1533 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1534   `-'0' LiteralToken
1535 )txt",
1536        R"txt(
1537 BinaryOperatorExpression ExpressionStatement_expression
1538 |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1539 | `-'1' LiteralToken
1540 |-'&' OperatorExpression_operatorToken
1541 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1542   `-'2' LiteralToken
1543 )txt",
1544        R"txt(
1545 BinaryOperatorExpression ExpressionStatement_expression
1546 |-IdExpression BinaryOperatorExpression_leftHandSide
1547 | `-UnqualifiedId IdExpression_id
1548 |   `-'a'
1549 |-'!=' OperatorExpression_operatorToken
1550 `-IntegerLiteralExpression BinaryOperatorExpression_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 ExpressionStatement_expression
1570 |-BoolLiteralExpression BinaryOperatorExpression_leftHandSide
1571 | `-'true' LiteralToken
1572 |-'||' OperatorExpression_operatorToken
1573 `-BoolLiteralExpression BinaryOperatorExpression_rightHandSide
1574   `-'false' LiteralToken
1575 )txt",
1576        R"txt(
1577 BinaryOperatorExpression ExpressionStatement_expression
1578 |-BoolLiteralExpression BinaryOperatorExpression_leftHandSide
1579 | `-'true' LiteralToken
1580 |-'or' OperatorExpression_operatorToken
1581 `-BoolLiteralExpression BinaryOperatorExpression_rightHandSide
1582   `-'false' LiteralToken
1583 )txt",
1584        R"txt(
1585 BinaryOperatorExpression ExpressionStatement_expression
1586 |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1587 | `-'1' LiteralToken
1588 |-'bitand' OperatorExpression_operatorToken
1589 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1590   `-'2' LiteralToken
1591 )txt",
1592        R"txt(
1593 BinaryOperatorExpression ExpressionStatement_expression
1594 |-IdExpression BinaryOperatorExpression_leftHandSide
1595 | `-UnqualifiedId IdExpression_id
1596 |   `-'a'
1597 |-'xor_eq' OperatorExpression_operatorToken
1598 `-IntegerLiteralExpression BinaryOperatorExpression_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 ExpressionStatement_expression
1612 |-ParenExpression BinaryOperatorExpression_leftHandSide
1613 | |-'(' OpenParen
1614 | |-BinaryOperatorExpression ParenExpression_subExpression
1615 | | |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1616 | | | `-'1' LiteralToken
1617 | | |-'+' OperatorExpression_operatorToken
1618 | | `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1619 | |   `-'2' LiteralToken
1620 | `-')' CloseParen
1621 |-'*' OperatorExpression_operatorToken
1622 `-ParenExpression BinaryOperatorExpression_rightHandSide
1623   |-'(' OpenParen
1624   |-BinaryOperatorExpression ParenExpression_subExpression
1625   | |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1626   | | `-'4' LiteralToken
1627   | |-'/' OperatorExpression_operatorToken
1628   | `-IntegerLiteralExpression BinaryOperatorExpression_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 ExpressionStatement_expression
1644 |-BinaryOperatorExpression BinaryOperatorExpression_leftHandSide
1645 | |-IdExpression BinaryOperatorExpression_leftHandSide
1646 | | `-UnqualifiedId IdExpression_id
1647 | |   `-'a'
1648 | |-'+' OperatorExpression_operatorToken
1649 | `-IdExpression BinaryOperatorExpression_rightHandSide
1650 |   `-UnqualifiedId IdExpression_id
1651 |     `-'b'
1652 |-'+' OperatorExpression_operatorToken
1653 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1654   `-'42' LiteralToken
1655 )txt",
1656        R"txt(
1657 BinaryOperatorExpression ExpressionStatement_expression
1658 |-IdExpression BinaryOperatorExpression_leftHandSide
1659 | `-UnqualifiedId IdExpression_id
1660 |   `-'a'
1661 |-'=' OperatorExpression_operatorToken
1662 `-BinaryOperatorExpression BinaryOperatorExpression_rightHandSide
1663   |-IdExpression BinaryOperatorExpression_leftHandSide
1664   | `-UnqualifiedId IdExpression_id
1665   |   `-'b'
1666   |-'=' OperatorExpression_operatorToken
1667   `-IntegerLiteralExpression BinaryOperatorExpression_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 ExpressionStatement_expression
1682 |-BinaryOperatorExpression BinaryOperatorExpression_leftHandSide
1683 | |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1684 | | `-'1' LiteralToken
1685 | |-'+' OperatorExpression_operatorToken
1686 | `-BinaryOperatorExpression BinaryOperatorExpression_rightHandSide
1687 |   |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1688 |   | `-'2' LiteralToken
1689 |   |-'*' OperatorExpression_operatorToken
1690 |   `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1691 |     `-'3' LiteralToken
1692 |-'+' OperatorExpression_operatorToken
1693 `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1694   `-'4' LiteralToken
1695 )txt",
1696        R"txt(
1697 BinaryOperatorExpression ExpressionStatement_expression
1698 |-BinaryOperatorExpression BinaryOperatorExpression_leftHandSide
1699 | |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1700 | | `-'1' LiteralToken
1701 | |-'%' OperatorExpression_operatorToken
1702 | `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide
1703 |   `-'2' LiteralToken
1704 |-'+' OperatorExpression_operatorToken
1705 `-BinaryOperatorExpression BinaryOperatorExpression_rightHandSide
1706   |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide
1707   | `-'3' LiteralToken
1708   |-'*' OperatorExpression_operatorToken
1709   `-IntegerLiteralExpression BinaryOperatorExpression_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 ExpressionStatement_expression
1729 |-IdExpression BinaryOperatorExpression_leftHandSide
1730 | `-UnqualifiedId IdExpression_id
1731 |   `-'x'
1732 |-'=' OperatorExpression_operatorToken
1733 `-IdExpression BinaryOperatorExpression_rightHandSide
1734   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1757 |-UnknownExpression BinaryOperatorExpression_leftHandSide
1758 | `-IdExpression
1759 |   `-UnqualifiedId IdExpression_id
1760 |     `-'x'
1761 |-'+' OperatorExpression_operatorToken
1762 `-IdExpression BinaryOperatorExpression_rightHandSide
1763   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1783 |-IdExpression BinaryOperatorExpression_leftHandSide
1784 | `-UnqualifiedId IdExpression_id
1785 |   `-'x'
1786 |-'<' OperatorExpression_operatorToken
1787 `-IdExpression BinaryOperatorExpression_rightHandSide
1788   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1808 |-IdExpression BinaryOperatorExpression_leftHandSide
1809 | `-UnqualifiedId IdExpression_id
1810 |   `-'x'
1811 |-'<<' OperatorExpression_operatorToken
1812 `-IdExpression BinaryOperatorExpression_rightHandSide
1813   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1833 |-IdExpression BinaryOperatorExpression_leftHandSide
1834 | `-UnqualifiedId IdExpression_id
1835 |   `-'x'
1836 |-',' OperatorExpression_operatorToken
1837 `-IdExpression BinaryOperatorExpression_rightHandSide
1838   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1858 |-IdExpression BinaryOperatorExpression_leftHandSide
1859 | `-UnqualifiedId IdExpression_id
1860 |   `-'xp'
1861 |-'->*' OperatorExpression_operatorToken
1862 `-IdExpression BinaryOperatorExpression_rightHandSide
1863   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1883 |-'!' OperatorExpression_operatorToken
1884 `-IdExpression UnaryOperatorExpression_operand
1885   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1905 |-'&' OperatorExpression_operatorToken
1906 `-IdExpression UnaryOperatorExpression_operand
1907   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1927 |-'++' OperatorExpression_operatorToken
1928 `-IdExpression UnaryOperatorExpression_operand
1929   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1949 |-IdExpression UnaryOperatorExpression_operand
1950 | `-UnqualifiedId IdExpression_id
1951 |   `-'x'
1952 `-'++' OperatorExpression_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 ExpressionStatement_expression
1968 |-IdExpression MemberExpression_object
1969 | `-UnqualifiedId IdExpression_id
1970 |   `-'s'
1971 |-'.' MemberExpression_accessToken
1972 `-IdExpression MemberExpression_member
1973   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
1993 |-IdExpression MemberExpression_object
1994 | `-UnqualifiedId IdExpression_id
1995 |   `-'s'
1996 |-'.' MemberExpression_accessToken
1997 `-IdExpression MemberExpression_member
1998   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2015 |-IdExpression MemberExpression_object
2016 | `-UnqualifiedId IdExpression_id
2017 |   `-'sp'
2018 |-'->' MemberExpression_accessToken
2019 `-IdExpression MemberExpression_member
2020   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2037 |-MemberExpression MemberExpression_object
2038 | |-IdExpression MemberExpression_object
2039 | | `-UnqualifiedId IdExpression_id
2040 | |   `-'s'
2041 | |-'.' MemberExpression_accessToken
2042 | `-IdExpression MemberExpression_member
2043 |   `-UnqualifiedId IdExpression_id
2044 |     `-'next'
2045 |-'->' MemberExpression_accessToken
2046 `-IdExpression MemberExpression_member
2047   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2067 |-MemberExpression CallExpression_callee
2068 | |-IdExpression MemberExpression_object
2069 | | `-UnqualifiedId IdExpression_id
2070 | |   `-'s'
2071 | |-'.' MemberExpression_accessToken
2072 | `-IdExpression MemberExpression_member
2073 |   `-UnqualifiedId IdExpression_id
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 CompoundStatement_statement
2101 | `-MemberExpression ExpressionStatement_expression
2102 |   |-IdExpression MemberExpression_object
2103 |   | `-UnqualifiedId IdExpression_id
2104 |   |   `-'s'
2105 |   |-'.' MemberExpression_accessToken
2106 |   `-IdExpression MemberExpression_member
2107 |     `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2133 |-MemberExpression CallExpression_callee
2134 | |-IdExpression MemberExpression_object
2135 | | `-UnqualifiedId IdExpression_id
2136 | |   `-'sp'
2137 | |-'->' MemberExpression_accessToken
2138 | `-IdExpression MemberExpression_member
2139 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2165 |-MemberExpression CallExpression_callee
2166 | |-IdExpression MemberExpression_object
2167 | | `-UnqualifiedId IdExpression_id
2168 | |   `-'s'
2169 | |-'.' MemberExpression_accessToken
2170 | |-'template'
2171 | `-IdExpression MemberExpression_member
2172 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2199 |-MemberExpression CallExpression_callee
2200 | |-IdExpression MemberExpression_object
2201 | | `-UnqualifiedId IdExpression_id
2202 | |   `-'s'
2203 | |-'.' MemberExpression_accessToken
2204 | `-IdExpression MemberExpression_member
2205 |   |-NestedNameSpecifier IdExpression_qualifier
2206 |   | |-IdentifierNameSpecifier List_element
2207 |   | | `-'Base'
2208 |   | `-'::' List_delimiter
2209 |   `-UnqualifiedId IdExpression_id
2210 |     `-'f'
2211 |-'(' OpenParen
2212 `-')' CloseParen
2213       )txt",
2214        R"txt(
2215 CallExpression ExpressionStatement_expression
2216 |-MemberExpression CallExpression_callee
2217 | |-IdExpression MemberExpression_object
2218 | | `-UnqualifiedId IdExpression_id
2219 | |   `-'s'
2220 | |-'.' MemberExpression_accessToken
2221 | `-IdExpression MemberExpression_member
2222 |   |-NestedNameSpecifier IdExpression_qualifier
2223 |   | |-'::' List_delimiter
2224 |   | |-IdentifierNameSpecifier List_element
2225 |   | | `-'S'
2226 |   | `-'::' List_delimiter
2227 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2260 |-MemberExpression CallExpression_callee
2261 | |-CallExpression MemberExpression_object
2262 | | |-MemberExpression CallExpression_callee
2263 | | | |-IdExpression MemberExpression_object
2264 | | | | `-UnqualifiedId IdExpression_id
2265 | | | |   `-'sp'
2266 | | | |-'->' MemberExpression_accessToken
2267 | | | `-IdExpression MemberExpression_member
2268 | | |   `-UnqualifiedId IdExpression_id
2269 | | |     `-'getU'
2270 | | |-'(' OpenParen
2271 | | `-')' CloseParen
2272 | |-'.' MemberExpression_accessToken
2273 | `-IdExpression MemberExpression_member
2274 |   |-NestedNameSpecifier IdExpression_qualifier
2275 |   | |-SimpleTemplateNameSpecifier List_element
2276 |   | | |-'template'
2277 |   | | |-'U'
2278 |   | | |-'<'
2279 |   | | |-'int'
2280 |   | | `-'>'
2281 |   | `-'::' List_delimiter
2282 |   |-'template' TemplateKeyword
2283 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2308 |-MemberExpression CallExpression_callee
2309 | |-IdExpression MemberExpression_object
2310 | | `-UnqualifiedId IdExpression_id
2311 | |   `-'s'
2312 | |-'.' MemberExpression_accessToken
2313 | `-IdExpression MemberExpression_member
2314 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2336 |-IdExpression CallExpression_callee
2337 | `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2359 |-CallExpression CallExpression_callee
2360 | |-IdExpression CallExpression_callee
2361 | | `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2390 |-MemberExpression CallExpression_callee
2391 | |-ThisExpression MemberExpression_object
2392 | | `-'this' IntroducerKeyword
2393 | |-'->' MemberExpression_accessToken
2394 | `-IdExpression MemberExpression_member
2395 |   `-UnqualifiedId IdExpression_id
2396 |     `-'f'
2397 |-'(' OpenParen
2398 `-')' CloseParen
2399       )txt",
2400        R"txt(
2401 CallExpression ExpressionStatement_expression
2402 |-IdExpression CallExpression_callee
2403 | `-UnqualifiedId IdExpression_id
2404 |   `-'f'
2405 |-'(' OpenParen
2406 `-')' CloseParen
2407       )txt",
2408        R"txt(
2409 CallExpression ExpressionStatement_expression
2410 |-MemberExpression CallExpression_callee
2411 | |-ThisExpression MemberExpression_object
2412 | | `-'this' IntroducerKeyword
2413 | |-'->' MemberExpression_accessToken
2414 | `-IdExpression MemberExpression_member
2415 |   |-NestedNameSpecifier IdExpression_qualifier
2416 |   | |-IdentifierNameSpecifier List_element
2417 |   | | `-'Base'
2418 |   | `-'::' List_delimiter
2419 |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2440 |-IdExpression CallExpression_callee
2441 | `-UnqualifiedId IdExpression_id
2442 |   `-'pf'
2443 |-'(' OpenParen
2444 `-')' CloseParen
2445 )txt",
2446        R"txt(
2447 CallExpression ExpressionStatement_expression
2448 |-ParenExpression CallExpression_callee
2449 | |-'(' OpenParen
2450 | |-PrefixUnaryOperatorExpression ParenExpression_subExpression
2451 | | |-'*' OperatorExpression_operatorToken
2452 | | `-IdExpression UnaryOperatorExpression_operand
2453 | |   `-UnqualifiedId IdExpression_id
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 ExpressionStatement_expression
2478 |-ParenExpression CallExpression_callee
2479 | |-'(' OpenParen
2480 | |-BinaryOperatorExpression ParenExpression_subExpression
2481 | | |-IdExpression BinaryOperatorExpression_leftHandSide
2482 | | | `-UnqualifiedId IdExpression_id
2483 | | |   `-'s'
2484 | | |-'.*' OperatorExpression_operatorToken
2485 | | `-IdExpression BinaryOperatorExpression_rightHandSide
2486 | |   `-UnqualifiedId IdExpression_id
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 CompoundStatement_statement
2507 |-CallExpression ExpressionStatement_expression
2508 | |-IdExpression CallExpression_callee
2509 | | `-UnqualifiedId IdExpression_id
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 CompoundStatement_statement
2530 |-CallExpression ExpressionStatement_expression
2531 | |-IdExpression CallExpression_callee
2532 | | `-UnqualifiedId IdExpression_id
2533 | |   `-'f'
2534 | |-'(' OpenParen
2535 | |-CallArguments CallExpression_arguments
2536 | | `-IntegerLiteralExpression List_element
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 CompoundStatement_statement
2556 |-CallExpression ExpressionStatement_expression
2557 | |-IdExpression CallExpression_callee
2558 | | `-UnqualifiedId IdExpression_id
2559 | |   `-'f'
2560 | |-'(' OpenParen
2561 | |-CallArguments CallExpression_arguments
2562 | | |-IntegerLiteralExpression List_element
2563 | | | `-'1' LiteralToken
2564 | | |-',' List_delimiter
2565 | | |-CharacterLiteralExpression List_element
2566 | | | `-''2'' LiteralToken
2567 | | |-',' List_delimiter
2568 | | `-FloatingLiteralExpression List_element
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 CompoundStatement_statement
2588 |-CallExpression ExpressionStatement_expression
2589 | |-IdExpression CallExpression_callee
2590 | | `-UnqualifiedId IdExpression_id
2591 | |   `-'f'
2592 | |-'(' OpenParen
2593 | |-CallArguments CallExpression_arguments
2594 | | `-BinaryOperatorExpression List_element
2595 | |   |-IdExpression BinaryOperatorExpression_leftHandSide
2596 | |   | `-UnqualifiedId IdExpression_id
2597 | |   |   `-'a'
2598 | |   |-'=' OperatorExpression_operatorToken
2599 | |   `-IntegerLiteralExpression BinaryOperatorExpression_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 CompoundStatement_statement
2619 |-CallExpression ExpressionStatement_expression
2620 | |-IdExpression CallExpression_callee
2621 | | `-UnqualifiedId IdExpression_id
2622 | |   `-'f'
2623 | |-'(' OpenParen
2624 | |-CallArguments CallExpression_arguments
2625 | | `-UnknownExpression List_element
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 CompoundStatement_statement
2652 |-CallExpression ExpressionStatement_expression
2653 | |-IdExpression CallExpression_callee
2654 | | `-UnqualifiedId IdExpression_id
2655 | |   `-'f'
2656 | |-'(' OpenParen
2657 | |-CallArguments CallExpression_arguments
2658 | | `-UnknownExpression List_element
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 CompoundStatement_statement
2692 |-CallExpression ExpressionStatement_expression
2693 | |-IdExpression CallExpression_callee
2694 | | `-UnqualifiedId IdExpression_id
2695 | |   `-'f'
2696 | |-'(' OpenParen
2697 | |-CallArguments CallExpression_arguments
2698 | | `-UnknownExpression List_element
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 ExpressionStatement_expression
2734 |-UnknownExpression CallExpression_callee
2735 | `-'test'
2736 |-'(' OpenParen
2737 |-CallArguments CallExpression_arguments
2738 | `-UnknownExpression List_element
2739 |   |-IdExpression
2740 |   | `-UnqualifiedId IdExpression_id
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 SimpleDeclaration_declarator
2758 | | |-'*'
2759 | | `-'a'
2760 | |-','
2761 | |-SimpleDeclarator SimpleDeclaration_declarator
2762 | | `-'b'
2763 | `-';'
2764 `-SimpleDeclaration
2765   |-'int'
2766   |-SimpleDeclarator SimpleDeclaration_declarator
2767   | |-'*'
2768   | `-'c'
2769   |-','
2770   |-SimpleDeclarator SimpleDeclaration_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 SimpleDeclaration_declarator
2787   | |-'*'
2788   | `-'a'
2789   |-','
2790   |-SimpleDeclarator SimpleDeclaration_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 SimpleDeclaration_declarator
2809   | |-'foo'
2810   | `-ParametersAndQualifiers
2811   |   |-'(' OpenParen
2812   |   `-')' CloseParen
2813   `-CompoundStatement
2814     |-'{' OpenParen
2815     |-DeclarationStatement CompoundStatement_statement
2816     | |-SimpleDeclaration
2817     | | |-'int'
2818     | | |-SimpleDeclarator SimpleDeclaration_declarator
2819     | | | |-'*'
2820     | | | `-'a'
2821     | | |-','
2822     | | `-SimpleDeclarator SimpleDeclaration_declarator
2823     | |   `-'b'
2824     | `-';'
2825     |-DeclarationStatement CompoundStatement_statement
2826     | |-SimpleDeclaration
2827     | | |-'typedef'
2828     | | |-'int'
2829     | | |-SimpleDeclarator SimpleDeclaration_declarator
2830     | | | |-'*'
2831     | | | `-'ta'
2832     | | |-','
2833     | | `-SimpleDeclarator SimpleDeclaration_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 SimpleDeclaration_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 | `-'::' List_delimiter
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 List_element
2980 | | `-'ns'
2981 | `-'::' List_delimiter
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 List_element
3003 | | `-'T'
3004 | `-'::' List_delimiter
3005 |-'foo'
3006 `-';'
3007 )txt",
3008        R"txt(
3009 UsingDeclaration
3010 |-'using'
3011 |-'typename'
3012 |-NestedNameSpecifier
3013 | |-IdentifierNameSpecifier List_element
3014 | | `-'T'
3015 | `-'::' List_delimiter
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 SimpleDeclaration_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 SimpleDeclaration_declarator
3085 | |-'*'
3086 | `-'y2'
3087 `-';'
3088 )txt",
3089        R"txt(
3090 SimpleDeclaration
3091 |-'struct'
3092 |-'{'
3093 |-'}'
3094 |-SimpleDeclarator SimpleDeclaration_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 SimpleDeclaration_declarator
3116 | |-'f'
3117 | `-ParametersAndQualifiers
3118 |   |-'(' OpenParen
3119 |   `-')' CloseParen
3120 `-CompoundStatement
3121   |-'{' OpenParen
3122   `-'}' CloseParen
3123 )txt"}));
3124 }
3125 
3126 TEST_P(SyntaxTreeTest, ConversionMemberFunction) {
3127   if (!GetParam().isCXX()) {
3128     return;
3129   }
3130   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3131       R"cpp(
3132 struct X {
3133   [[operator int();]]
3134 };
3135 )cpp",
3136       {R"txt(
3137 SimpleDeclaration
3138 |-SimpleDeclarator SimpleDeclaration_declarator
3139 | |-'operator'
3140 | |-'int'
3141 | `-ParametersAndQualifiers
3142 |   |-'(' OpenParen
3143 |   `-')' CloseParen
3144 `-';'
3145 )txt"}));
3146 }
3147 
3148 TEST_P(SyntaxTreeTest, LiteralOperatorDeclaration) {
3149   if (!GetParam().isCXX11OrLater()) {
3150     return;
3151   }
3152   EXPECT_TRUE(treeDumpEqual(
3153       R"cpp(
3154 unsigned operator "" _c(char);
3155     )cpp",
3156       R"txt(
3157 TranslationUnit Detached
3158 `-SimpleDeclaration
3159   |-'unsigned'
3160   |-SimpleDeclarator SimpleDeclaration_declarator
3161   | |-'operator'
3162   | |-'""'
3163   | |-'_c'
3164   | `-ParametersAndQualifiers
3165   |   |-'(' OpenParen
3166   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
3167   |   | `-SimpleDeclaration List_element
3168   |   |   `-'char'
3169   |   `-')' CloseParen
3170   `-';'
3171 )txt"));
3172 }
3173 
3174 TEST_P(SyntaxTreeTest, NumericLiteralOperatorTemplateDeclaration) {
3175   if (!GetParam().isCXX11OrLater()) {
3176     return;
3177   }
3178   EXPECT_TRUE(treeDumpEqual(
3179       R"cpp(
3180 template <char...>
3181 unsigned operator "" _t();
3182     )cpp",
3183       R"txt(
3184 TranslationUnit Detached
3185 `-TemplateDeclaration TemplateDeclaration_declaration
3186   |-'template' IntroducerKeyword
3187   |-'<'
3188   |-SimpleDeclaration
3189   | `-'char'
3190   |-'...'
3191   |-'>'
3192   `-SimpleDeclaration
3193     |-'unsigned'
3194     |-SimpleDeclarator SimpleDeclaration_declarator
3195     | |-'operator'
3196     | |-'""'
3197     | |-'_t'
3198     | `-ParametersAndQualifiers
3199     |   |-'(' OpenParen
3200     |   `-')' CloseParen
3201     `-';'
3202 )txt"));
3203 }
3204 
3205 TEST_P(SyntaxTreeTest, OverloadedOperatorDeclaration) {
3206   if (!GetParam().isCXX()) {
3207     return;
3208   }
3209   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3210       R"cpp(
3211 struct X {
3212   [[X& operator=(const X&);]]
3213 };
3214 )cpp",
3215       {R"txt(
3216 SimpleDeclaration
3217 |-'X'
3218 |-SimpleDeclarator SimpleDeclaration_declarator
3219 | |-'&'
3220 | |-'operator'
3221 | |-'='
3222 | `-ParametersAndQualifiers
3223 |   |-'(' OpenParen
3224 |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
3225 |   | `-SimpleDeclaration List_element
3226 |   |   |-'const'
3227 |   |   |-'X'
3228 |   |   `-SimpleDeclarator SimpleDeclaration_declarator
3229 |   |     `-'&'
3230 |   `-')' CloseParen
3231 `-';'
3232 )txt"}));
3233 }
3234 
3235 TEST_P(SyntaxTreeTest, OverloadedOperatorFriendDeclaration) {
3236   if (!GetParam().isCXX()) {
3237     return;
3238   }
3239   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3240       R"cpp(
3241 struct X {
3242   [[friend X operator+(X, const X&);]]
3243 };
3244 )cpp",
3245       {R"txt(
3246 UnknownDeclaration
3247 `-SimpleDeclaration
3248   |-'friend'
3249   |-'X'
3250   |-SimpleDeclarator SimpleDeclaration_declarator
3251   | |-'operator'
3252   | |-'+'
3253   | `-ParametersAndQualifiers
3254   |   |-'(' OpenParen
3255   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
3256   |   | |-SimpleDeclaration List_element
3257   |   | | `-'X'
3258   |   | |-',' List_delimiter
3259   |   | `-SimpleDeclaration List_element
3260   |   |   |-'const'
3261   |   |   |-'X'
3262   |   |   `-SimpleDeclarator SimpleDeclaration_declarator
3263   |   |     `-'&'
3264   |   `-')' CloseParen
3265   `-';'
3266 )txt"}));
3267 }
3268 
3269 TEST_P(SyntaxTreeTest, ClassTemplateDeclaration) {
3270   if (!GetParam().isCXX()) {
3271     return;
3272   }
3273   EXPECT_TRUE(treeDumpEqual(
3274       R"cpp(
3275 template<typename T>
3276 struct ST {};
3277 )cpp",
3278       R"txt(
3279 TranslationUnit Detached
3280 `-TemplateDeclaration TemplateDeclaration_declaration
3281   |-'template' IntroducerKeyword
3282   |-'<'
3283   |-UnknownDeclaration
3284   | |-'typename'
3285   | `-'T'
3286   |-'>'
3287   `-SimpleDeclaration
3288     |-'struct'
3289     |-'ST'
3290     |-'{'
3291     |-'}'
3292     `-';'
3293 )txt"));
3294 }
3295 
3296 TEST_P(SyntaxTreeTest, FunctionTemplateDeclaration) {
3297   if (!GetParam().isCXX()) {
3298     return;
3299   }
3300   EXPECT_TRUE(treeDumpEqual(
3301       R"cpp(
3302 template<typename T>
3303 T f();
3304 )cpp",
3305       R"txt(
3306 TranslationUnit Detached
3307 `-TemplateDeclaration TemplateDeclaration_declaration
3308   |-'template' IntroducerKeyword
3309   |-'<'
3310   |-UnknownDeclaration
3311   | |-'typename'
3312   | `-'T'
3313   |-'>'
3314   `-SimpleDeclaration
3315     |-'T'
3316     |-SimpleDeclarator SimpleDeclaration_declarator
3317     | |-'f'
3318     | `-ParametersAndQualifiers
3319     |   |-'(' OpenParen
3320     |   `-')' CloseParen
3321     `-';'
3322 )txt"));
3323 }
3324 
3325 TEST_P(SyntaxTreeTest, VariableTemplateDeclaration) {
3326   if (!GetParam().isCXX14OrLater()) {
3327     return;
3328   }
3329   EXPECT_TRUE(treeDumpEqual(
3330       R"cpp(
3331 template <class T> T var = 10;
3332 )cpp",
3333       R"txt(
3334 TranslationUnit Detached
3335 `-TemplateDeclaration TemplateDeclaration_declaration
3336   |-'template' IntroducerKeyword
3337   |-'<'
3338   |-UnknownDeclaration
3339   | |-'class'
3340   | `-'T'
3341   |-'>'
3342   `-SimpleDeclaration
3343     |-'T'
3344     |-SimpleDeclarator SimpleDeclaration_declarator
3345     | |-'var'
3346     | |-'='
3347     | `-IntegerLiteralExpression
3348     |   `-'10' LiteralToken
3349     `-';'
3350 )txt"));
3351 }
3352 
3353 TEST_P(SyntaxTreeTest, StaticMemberFunctionTemplate) {
3354   if (!GetParam().isCXX()) {
3355     return;
3356   }
3357   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3358       R"cpp(
3359 struct S {
3360   [[template<typename U>
3361   static U f();]]
3362 };
3363 )cpp",
3364       {R"txt(
3365 TemplateDeclaration TemplateDeclaration_declaration
3366 |-'template' IntroducerKeyword
3367 |-'<'
3368 |-UnknownDeclaration
3369 | |-'typename'
3370 | `-'U'
3371 |-'>'
3372 `-SimpleDeclaration
3373   |-'static'
3374   |-'U'
3375   |-SimpleDeclarator SimpleDeclaration_declarator
3376   | |-'f'
3377   | `-ParametersAndQualifiers
3378   |   |-'(' OpenParen
3379   |   `-')' CloseParen
3380   `-';'
3381 )txt"}));
3382 }
3383 
3384 TEST_P(SyntaxTreeTest, NestedTemplates) {
3385   if (!GetParam().isCXX()) {
3386     return;
3387   }
3388   EXPECT_TRUE(treeDumpEqual(
3389       R"cpp(
3390 template <class T>
3391 struct X {
3392   template <class U>
3393   U foo();
3394 };
3395 )cpp",
3396       R"txt(
3397 TranslationUnit Detached
3398 `-TemplateDeclaration TemplateDeclaration_declaration
3399   |-'template' IntroducerKeyword
3400   |-'<'
3401   |-UnknownDeclaration
3402   | |-'class'
3403   | `-'T'
3404   |-'>'
3405   `-SimpleDeclaration
3406     |-'struct'
3407     |-'X'
3408     |-'{'
3409     |-TemplateDeclaration TemplateDeclaration_declaration
3410     | |-'template' IntroducerKeyword
3411     | |-'<'
3412     | |-UnknownDeclaration
3413     | | |-'class'
3414     | | `-'U'
3415     | |-'>'
3416     | `-SimpleDeclaration
3417     |   |-'U'
3418     |   |-SimpleDeclarator SimpleDeclaration_declarator
3419     |   | |-'foo'
3420     |   | `-ParametersAndQualifiers
3421     |   |   |-'(' OpenParen
3422     |   |   `-')' CloseParen
3423     |   `-';'
3424     |-'}'
3425     `-';'
3426 )txt"));
3427 }
3428 
3429 TEST_P(SyntaxTreeTest, NestedTemplatesInNamespace) {
3430   if (!GetParam().isCXX()) {
3431     return;
3432   }
3433   EXPECT_TRUE(treeDumpEqual(
3434       R"cpp(
3435 namespace n {
3436   template<typename T>
3437   struct ST {
3438     template<typename U>
3439     static U f();
3440   };
3441 }
3442 )cpp",
3443       R"txt(
3444 TranslationUnit Detached
3445 `-NamespaceDefinition
3446   |-'namespace'
3447   |-'n'
3448   |-'{'
3449   |-TemplateDeclaration TemplateDeclaration_declaration
3450   | |-'template' IntroducerKeyword
3451   | |-'<'
3452   | |-UnknownDeclaration
3453   | | |-'typename'
3454   | | `-'T'
3455   | |-'>'
3456   | `-SimpleDeclaration
3457   |   |-'struct'
3458   |   |-'ST'
3459   |   |-'{'
3460   |   |-TemplateDeclaration TemplateDeclaration_declaration
3461   |   | |-'template' IntroducerKeyword
3462   |   | |-'<'
3463   |   | |-UnknownDeclaration
3464   |   | | |-'typename'
3465   |   | | `-'U'
3466   |   | |-'>'
3467   |   | `-SimpleDeclaration
3468   |   |   |-'static'
3469   |   |   |-'U'
3470   |   |   |-SimpleDeclarator SimpleDeclaration_declarator
3471   |   |   | |-'f'
3472   |   |   | `-ParametersAndQualifiers
3473   |   |   |   |-'(' OpenParen
3474   |   |   |   `-')' CloseParen
3475   |   |   `-';'
3476   |   |-'}'
3477   |   `-';'
3478   `-'}'
3479 )txt"));
3480 }
3481 
3482 TEST_P(SyntaxTreeTest, ClassTemplate_MemberClassDefinition) {
3483   if (!GetParam().isCXX()) {
3484     return;
3485   }
3486   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3487       R"cpp(
3488 template <class T> struct X { struct Y; };
3489 [[template <class T> struct X<T>::Y {};]]
3490 )cpp",
3491       {R"txt(
3492 TemplateDeclaration TemplateDeclaration_declaration
3493 |-'template' IntroducerKeyword
3494 |-'<'
3495 |-UnknownDeclaration
3496 | |-'class'
3497 | `-'T'
3498 |-'>'
3499 `-SimpleDeclaration
3500   |-'struct'
3501   |-NestedNameSpecifier
3502   | |-SimpleTemplateNameSpecifier List_element
3503   | | |-'X'
3504   | | |-'<'
3505   | | |-'T'
3506   | | `-'>'
3507   | `-'::' List_delimiter
3508   |-'Y'
3509   |-'{'
3510   |-'}'
3511   `-';'
3512 )txt"}));
3513 }
3514 
3515 TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Definition) {
3516   if (!GetParam().isCXX()) {
3517     return;
3518   }
3519   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3520       R"cpp(
3521 template <class T> struct X {};
3522 [[template struct X<double>;]]
3523 )cpp",
3524       {R"txt(
3525 ExplicitTemplateInstantiation
3526 |-'template' IntroducerKeyword
3527 `-SimpleDeclaration ExplicitTemplateInstantiation_declaration
3528   |-'struct'
3529   |-'X'
3530   |-'<'
3531   |-'double'
3532   |-'>'
3533   `-';'
3534 )txt"}));
3535 }
3536 
3537 TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Declaration) {
3538   if (!GetParam().isCXX()) {
3539     return;
3540   }
3541   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3542       R"cpp(
3543 template <class T> struct X {};
3544 [[extern template struct X<float>;]]
3545 )cpp",
3546       {R"txt(
3547 ExplicitTemplateInstantiation
3548 |-'extern' ExternKeyword
3549 |-'template' IntroducerKeyword
3550 `-SimpleDeclaration ExplicitTemplateInstantiation_declaration
3551   |-'struct'
3552   |-'X'
3553   |-'<'
3554   |-'float'
3555   |-'>'
3556   `-';'
3557 )txt"}));
3558 }
3559 
3560 TEST_P(SyntaxTreeTest, ClassTemplateSpecialization_Partial) {
3561   if (!GetParam().isCXX()) {
3562     return;
3563   }
3564   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3565       R"cpp(
3566 template <class T> struct X {};
3567 [[template <class T> struct X<T*> {};]]
3568 )cpp",
3569       {R"txt(
3570 TemplateDeclaration TemplateDeclaration_declaration
3571 |-'template' IntroducerKeyword
3572 |-'<'
3573 |-UnknownDeclaration
3574 | |-'class'
3575 | `-'T'
3576 |-'>'
3577 `-SimpleDeclaration
3578   |-'struct'
3579   |-'X'
3580   |-'<'
3581   |-'T'
3582   |-'*'
3583   |-'>'
3584   |-'{'
3585   |-'}'
3586   `-';'
3587 )txt"}));
3588 }
3589 
3590 TEST_P(SyntaxTreeTest, ClassTemplateSpecialization_Full) {
3591   if (!GetParam().isCXX()) {
3592     return;
3593   }
3594   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3595       R"cpp(
3596 template <class T> struct X {};
3597 [[template <> struct X<int> {};]]
3598 )cpp",
3599       {R"txt(
3600 TemplateDeclaration TemplateDeclaration_declaration
3601 |-'template' IntroducerKeyword
3602 |-'<'
3603 |-'>'
3604 `-SimpleDeclaration
3605   |-'struct'
3606   |-'X'
3607   |-'<'
3608   |-'int'
3609   |-'>'
3610   |-'{'
3611   |-'}'
3612   `-';'
3613 )txt"}));
3614 }
3615 
3616 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
3617   EXPECT_TRUE(treeDumpEqual(
3618       R"cpp(
3619 ;
3620 )cpp",
3621       R"txt(
3622 TranslationUnit Detached
3623 `-EmptyDeclaration
3624   `-';'
3625 )txt"));
3626 }
3627 
3628 TEST_P(SyntaxTreeTest, StaticAssert) {
3629   if (!GetParam().isCXX11OrLater()) {
3630     return;
3631   }
3632   EXPECT_TRUE(treeDumpEqual(
3633       R"cpp(
3634 static_assert(true, "message");
3635 )cpp",
3636       R"txt(
3637 TranslationUnit Detached
3638 `-StaticAssertDeclaration
3639   |-'static_assert'
3640   |-'('
3641   |-BoolLiteralExpression StaticAssertDeclaration_condition
3642   | `-'true' LiteralToken
3643   |-','
3644   |-StringLiteralExpression StaticAssertDeclaration_message
3645   | `-'"message"' LiteralToken
3646   |-')'
3647   `-';'
3648 )txt"));
3649 }
3650 
3651 TEST_P(SyntaxTreeTest, StaticAssert_WithoutMessage) {
3652   if (!GetParam().isCXX17OrLater()) {
3653     return;
3654   }
3655   EXPECT_TRUE(treeDumpEqual(
3656       R"cpp(
3657 static_assert(true);
3658 )cpp",
3659       R"txt(
3660 TranslationUnit Detached
3661 `-StaticAssertDeclaration
3662   |-'static_assert'
3663   |-'('
3664   |-BoolLiteralExpression StaticAssertDeclaration_condition
3665   | `-'true' LiteralToken
3666   |-')'
3667   `-';'
3668 )txt"));
3669 }
3670 
3671 TEST_P(SyntaxTreeTest, ExternC) {
3672   if (!GetParam().isCXX()) {
3673     return;
3674   }
3675   EXPECT_TRUE(treeDumpEqual(
3676       R"cpp(
3677 extern "C" int a;
3678 extern "C" { int b; int c; }
3679 )cpp",
3680       R"txt(
3681 TranslationUnit Detached
3682 |-LinkageSpecificationDeclaration
3683 | |-'extern'
3684 | |-'"C"'
3685 | `-SimpleDeclaration
3686 |   |-'int'
3687 |   |-SimpleDeclarator SimpleDeclaration_declarator
3688 |   | `-'a'
3689 |   `-';'
3690 `-LinkageSpecificationDeclaration
3691   |-'extern'
3692   |-'"C"'
3693   |-'{'
3694   |-SimpleDeclaration
3695   | |-'int'
3696   | |-SimpleDeclarator SimpleDeclaration_declarator
3697   | | `-'b'
3698   | `-';'
3699   |-SimpleDeclaration
3700   | |-'int'
3701   | |-SimpleDeclarator SimpleDeclaration_declarator
3702   | | `-'c'
3703   | `-';'
3704   `-'}'
3705 )txt"));
3706 }
3707 
3708 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
3709   // Some nodes are non-modifiable, they are marked with 'I:'.
3710   EXPECT_TRUE(treeDumpEqual(
3711       R"cpp(
3712 #define HALF_IF if (1+
3713 #define HALF_IF_2 1) {}
3714 void test() {
3715   HALF_IF HALF_IF_2 else {}
3716 })cpp",
3717       R"txt(
3718 TranslationUnit Detached
3719 `-SimpleDeclaration
3720   |-'void'
3721   |-SimpleDeclarator SimpleDeclaration_declarator
3722   | |-'test'
3723   | `-ParametersAndQualifiers
3724   |   |-'(' OpenParen
3725   |   `-')' CloseParen
3726   `-CompoundStatement
3727     |-'{' OpenParen
3728     |-IfStatement CompoundStatement_statement
3729     | |-'if' IntroducerKeyword unmodifiable
3730     | |-'(' unmodifiable
3731     | |-BinaryOperatorExpression unmodifiable
3732     | | |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide unmodifiable
3733     | | | `-'1' LiteralToken unmodifiable
3734     | | |-'+' OperatorExpression_operatorToken unmodifiable
3735     | | `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide unmodifiable
3736     | |   `-'1' LiteralToken unmodifiable
3737     | |-')' unmodifiable
3738     | |-CompoundStatement IfStatement_thenStatement unmodifiable
3739     | | |-'{' OpenParen unmodifiable
3740     | | `-'}' CloseParen unmodifiable
3741     | |-'else' IfStatement_elseKeyword
3742     | `-CompoundStatement IfStatement_elseStatement
3743     |   |-'{' OpenParen
3744     |   `-'}' CloseParen
3745     `-'}' CloseParen
3746 )txt"));
3747 }
3748 
3749 TEST_P(SyntaxTreeTest, ModifiableNodes) {
3750   // All nodes can be mutated.
3751   EXPECT_TRUE(treeDumpEqual(
3752       R"cpp(
3753 #define OPEN {
3754 #define CLOSE }
3755 
3756 void test() {
3757   OPEN
3758     1;
3759   CLOSE
3760 
3761   OPEN
3762     2;
3763   }
3764 }
3765 )cpp",
3766       R"txt(
3767 TranslationUnit Detached
3768 `-SimpleDeclaration
3769   |-'void'
3770   |-SimpleDeclarator SimpleDeclaration_declarator
3771   | |-'test'
3772   | `-ParametersAndQualifiers
3773   |   |-'(' OpenParen
3774   |   `-')' CloseParen
3775   `-CompoundStatement
3776     |-'{' OpenParen
3777     |-CompoundStatement CompoundStatement_statement
3778     | |-'{' OpenParen
3779     | |-ExpressionStatement CompoundStatement_statement
3780     | | |-IntegerLiteralExpression ExpressionStatement_expression
3781     | | | `-'1' LiteralToken
3782     | | `-';'
3783     | `-'}' CloseParen
3784     |-CompoundStatement CompoundStatement_statement
3785     | |-'{' OpenParen
3786     | |-ExpressionStatement CompoundStatement_statement
3787     | | |-IntegerLiteralExpression ExpressionStatement_expression
3788     | | | `-'2' LiteralToken
3789     | | `-';'
3790     | `-'}' CloseParen
3791     `-'}' CloseParen
3792 )txt"));
3793 }
3794 
3795 TEST_P(SyntaxTreeTest, ArrayDeclarator_Simple) {
3796   EXPECT_TRUE(treeDumpEqual(
3797       R"cpp(
3798 int a[10];
3799 )cpp",
3800       R"txt(
3801 TranslationUnit Detached
3802 `-SimpleDeclaration
3803   |-'int'
3804   |-SimpleDeclarator SimpleDeclaration_declarator
3805   | |-'a'
3806   | `-ArraySubscript
3807   |   |-'[' OpenParen
3808   |   |-IntegerLiteralExpression ArraySubscript_sizeExpression
3809   |   | `-'10' LiteralToken
3810   |   `-']' CloseParen
3811   `-';'
3812 )txt"));
3813 }
3814 
3815 TEST_P(SyntaxTreeTest, ArrayDeclarator_Multidimensional) {
3816   EXPECT_TRUE(treeDumpEqual(
3817       R"cpp(
3818 int b[1][2][3];
3819 )cpp",
3820       R"txt(
3821 TranslationUnit Detached
3822 `-SimpleDeclaration
3823   |-'int'
3824   |-SimpleDeclarator SimpleDeclaration_declarator
3825   | |-'b'
3826   | |-ArraySubscript
3827   | | |-'[' OpenParen
3828   | | |-IntegerLiteralExpression ArraySubscript_sizeExpression
3829   | | | `-'1' LiteralToken
3830   | | `-']' CloseParen
3831   | |-ArraySubscript
3832   | | |-'[' OpenParen
3833   | | |-IntegerLiteralExpression ArraySubscript_sizeExpression
3834   | | | `-'2' LiteralToken
3835   | | `-']' CloseParen
3836   | `-ArraySubscript
3837   |   |-'[' OpenParen
3838   |   |-IntegerLiteralExpression ArraySubscript_sizeExpression
3839   |   | `-'3' LiteralToken
3840   |   `-']' CloseParen
3841   `-';'
3842 )txt"));
3843 }
3844 
3845 TEST_P(SyntaxTreeTest, ArrayDeclarator_UnknownBound) {
3846   EXPECT_TRUE(treeDumpEqual(
3847       R"cpp(
3848 int c[] = {1,2,3};
3849 )cpp",
3850       R"txt(
3851 TranslationUnit Detached
3852 `-SimpleDeclaration
3853   |-'int'
3854   |-SimpleDeclarator SimpleDeclaration_declarator
3855   | |-'c'
3856   | |-ArraySubscript
3857   | | |-'[' OpenParen
3858   | | `-']' CloseParen
3859   | |-'='
3860   | `-UnknownExpression
3861   |   `-UnknownExpression
3862   |     |-'{'
3863   |     |-IntegerLiteralExpression
3864   |     | `-'1' LiteralToken
3865   |     |-','
3866   |     |-IntegerLiteralExpression
3867   |     | `-'2' LiteralToken
3868   |     |-','
3869   |     |-IntegerLiteralExpression
3870   |     | `-'3' LiteralToken
3871   |     `-'}'
3872   `-';'
3873 )txt"));
3874 }
3875 
3876 TEST_P(SyntaxTreeTest, ArrayDeclarator_Static) {
3877   if (!GetParam().isC99OrLater()) {
3878     return;
3879   }
3880   EXPECT_TRUE(treeDumpEqual(
3881       R"cpp(
3882 void f(int xs[static 10]);
3883 )cpp",
3884       R"txt(
3885 TranslationUnit Detached
3886 `-SimpleDeclaration
3887   |-'void'
3888   |-SimpleDeclarator SimpleDeclaration_declarator
3889   | |-'f'
3890   | `-ParametersAndQualifiers
3891   |   |-'(' OpenParen
3892   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
3893   |   | `-SimpleDeclaration List_element
3894   |   |   |-'int'
3895   |   |   `-SimpleDeclarator SimpleDeclaration_declarator
3896   |   |     |-'xs'
3897   |   |     `-ArraySubscript
3898   |   |       |-'[' OpenParen
3899   |   |       |-'static'
3900   |   |       |-IntegerLiteralExpression ArraySubscript_sizeExpression
3901   |   |       | `-'10' LiteralToken
3902   |   |       `-']' CloseParen
3903   |   `-')' CloseParen
3904   `-';'
3905 )txt"));
3906 }
3907 
3908 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) {
3909   EXPECT_TRUE(treeDumpEqual(
3910       R"cpp(
3911 int func();
3912 )cpp",
3913       R"txt(
3914 TranslationUnit Detached
3915 `-SimpleDeclaration
3916   |-'int'
3917   |-SimpleDeclarator SimpleDeclaration_declarator
3918   | |-'func'
3919   | `-ParametersAndQualifiers
3920   |   |-'(' OpenParen
3921   |   `-')' CloseParen
3922   `-';'
3923 )txt"));
3924 }
3925 
3926 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) {
3927   EXPECT_TRUE(treeDumpEqual(
3928       R"cpp(
3929 int func1(int a);
3930 int func2(int *ap);
3931 int func3(int a, float b);
3932 )cpp",
3933       R"txt(
3934 TranslationUnit Detached
3935 |-SimpleDeclaration
3936 | |-'int'
3937 | |-SimpleDeclarator SimpleDeclaration_declarator
3938 | | |-'func1'
3939 | | `-ParametersAndQualifiers
3940 | |   |-'(' OpenParen
3941 | |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
3942 | |   | `-SimpleDeclaration List_element
3943 | |   |   |-'int'
3944 | |   |   `-SimpleDeclarator SimpleDeclaration_declarator
3945 | |   |     `-'a'
3946 | |   `-')' CloseParen
3947 | `-';'
3948 |-SimpleDeclaration
3949 | |-'int'
3950 | |-SimpleDeclarator SimpleDeclaration_declarator
3951 | | |-'func2'
3952 | | `-ParametersAndQualifiers
3953 | |   |-'(' OpenParen
3954 | |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
3955 | |   | `-SimpleDeclaration List_element
3956 | |   |   |-'int'
3957 | |   |   `-SimpleDeclarator SimpleDeclaration_declarator
3958 | |   |     |-'*'
3959 | |   |     `-'ap'
3960 | |   `-')' CloseParen
3961 | `-';'
3962 `-SimpleDeclaration
3963   |-'int'
3964   |-SimpleDeclarator SimpleDeclaration_declarator
3965   | |-'func3'
3966   | `-ParametersAndQualifiers
3967   |   |-'(' OpenParen
3968   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
3969   |   | |-SimpleDeclaration List_element
3970   |   | | |-'int'
3971   |   | | `-SimpleDeclarator SimpleDeclaration_declarator
3972   |   | |   `-'a'
3973   |   | |-',' List_delimiter
3974   |   | `-SimpleDeclaration List_element
3975   |   |   |-'float'
3976   |   |   `-SimpleDeclarator SimpleDeclaration_declarator
3977   |   |     `-'b'
3978   |   `-')' CloseParen
3979   `-';'
3980 )txt"));
3981 }
3982 
3983 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
3984   EXPECT_TRUE(treeDumpEqual(
3985       R"cpp(
3986 int func1(int);
3987 int func2(int *);
3988 int func3(int, float);
3989 )cpp",
3990       R"txt(
3991 TranslationUnit Detached
3992 |-SimpleDeclaration
3993 | |-'int'
3994 | |-SimpleDeclarator SimpleDeclaration_declarator
3995 | | |-'func1'
3996 | | `-ParametersAndQualifiers
3997 | |   |-'(' OpenParen
3998 | |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
3999 | |   | `-SimpleDeclaration List_element
4000 | |   |   `-'int'
4001 | |   `-')' CloseParen
4002 | `-';'
4003 |-SimpleDeclaration
4004 | |-'int'
4005 | |-SimpleDeclarator SimpleDeclaration_declarator
4006 | | |-'func2'
4007 | | `-ParametersAndQualifiers
4008 | |   |-'(' OpenParen
4009 | |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4010 | |   | `-SimpleDeclaration List_element
4011 | |   |   |-'int'
4012 | |   |   `-SimpleDeclarator SimpleDeclaration_declarator
4013 | |   |     `-'*'
4014 | |   `-')' CloseParen
4015 | `-';'
4016 `-SimpleDeclaration
4017   |-'int'
4018   |-SimpleDeclarator SimpleDeclaration_declarator
4019   | |-'func3'
4020   | `-ParametersAndQualifiers
4021   |   |-'(' OpenParen
4022   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4023   |   | |-SimpleDeclaration List_element
4024   |   | | `-'int'
4025   |   | |-',' List_delimiter
4026   |   | `-SimpleDeclaration List_element
4027   |   |   `-'float'
4028   |   `-')' CloseParen
4029   `-';'
4030 )txt"));
4031 }
4032 
4033 TEST_P(SyntaxTreeTest,
4034        ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) {
4035   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4036     return;
4037   }
4038   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4039       R"cpp(
4040 template<typename T, typename... Args>
4041 [[void test(T , Args... );]]
4042 )cpp",
4043       {R"txt(
4044 SimpleDeclaration
4045 |-'void'
4046 |-SimpleDeclarator SimpleDeclaration_declarator
4047 | |-'test'
4048 | `-ParametersAndQualifiers
4049 |   |-'(' OpenParen
4050 |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4051 |   | |-SimpleDeclaration List_element
4052 |   | | `-'T'
4053 |   | |-',' List_delimiter
4054 |   | `-SimpleDeclaration List_element
4055 |   |   |-'Args'
4056 |   |   `-'...'
4057 |   `-')' CloseParen
4058 `-';'
4059 )txt"}));
4060 }
4061 
4062 TEST_P(SyntaxTreeTest,
4063        ParametersAndQualifiers_InVariadicFunctionTemplate_NamedParameterPack) {
4064   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4065     return;
4066   }
4067   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4068       R"cpp(
4069 template<typename T, typename... Args>
4070 [[void test(T t, Args... args);]]
4071 )cpp",
4072       {R"txt(
4073 SimpleDeclaration
4074 |-'void'
4075 |-SimpleDeclarator SimpleDeclaration_declarator
4076 | |-'test'
4077 | `-ParametersAndQualifiers
4078 |   |-'(' OpenParen
4079 |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4080 |   | |-SimpleDeclaration List_element
4081 |   | | |-'T'
4082 |   | | `-SimpleDeclarator SimpleDeclaration_declarator
4083 |   | |   `-'t'
4084 |   | |-',' List_delimiter
4085 |   | `-SimpleDeclaration List_element
4086 |   |   |-'Args'
4087 |   |   |-'...'
4088 |   |   `-SimpleDeclarator SimpleDeclaration_declarator
4089 |   |     `-'args'
4090 |   `-')' CloseParen
4091 `-';'
4092 )txt"}));
4093 }
4094 
4095 TEST_P(SyntaxTreeTest,
4096        ParametersAndQualifiers_InFreeFunctions_VariadicArguments) {
4097   if (!GetParam().isCXX11OrLater()) {
4098     return;
4099   }
4100   EXPECT_TRUE(treeDumpEqual(
4101       R"cpp(
4102 void test(int , char ...);
4103 )cpp",
4104       R"txt(
4105 TranslationUnit Detached
4106 `-SimpleDeclaration
4107   |-'void'
4108   |-SimpleDeclarator SimpleDeclaration_declarator
4109   | |-'test'
4110   | `-ParametersAndQualifiers
4111   |   |-'(' OpenParen
4112   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4113   |   | |-SimpleDeclaration List_element
4114   |   | | `-'int'
4115   |   | |-',' List_delimiter
4116   |   | `-SimpleDeclaration List_element
4117   |   |   `-'char'
4118   |   |-'...'
4119   |   `-')' CloseParen
4120   `-';'
4121 )txt"));
4122 }
4123 
4124 TEST_P(SyntaxTreeTest,
4125        ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
4126   if (!GetParam().isCXX()) {
4127     return;
4128   }
4129   EXPECT_TRUE(treeDumpEqual(
4130       R"cpp(
4131 int func(const int a, volatile int b, const volatile int c);
4132 )cpp",
4133       R"txt(
4134 TranslationUnit Detached
4135 `-SimpleDeclaration
4136   |-'int'
4137   |-SimpleDeclarator SimpleDeclaration_declarator
4138   | |-'func'
4139   | `-ParametersAndQualifiers
4140   |   |-'(' OpenParen
4141   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4142   |   | |-SimpleDeclaration List_element
4143   |   | | |-'const'
4144   |   | | |-'int'
4145   |   | | `-SimpleDeclarator SimpleDeclaration_declarator
4146   |   | |   `-'a'
4147   |   | |-',' List_delimiter
4148   |   | |-SimpleDeclaration List_element
4149   |   | | |-'volatile'
4150   |   | | |-'int'
4151   |   | | `-SimpleDeclarator SimpleDeclaration_declarator
4152   |   | |   `-'b'
4153   |   | |-',' List_delimiter
4154   |   | `-SimpleDeclaration List_element
4155   |   |   |-'const'
4156   |   |   |-'volatile'
4157   |   |   |-'int'
4158   |   |   `-SimpleDeclarator SimpleDeclaration_declarator
4159   |   |     `-'c'
4160   |   `-')' CloseParen
4161   `-';'
4162 )txt"));
4163 }
4164 
4165 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
4166   if (!GetParam().isCXX()) {
4167     return;
4168   }
4169   EXPECT_TRUE(treeDumpEqual(
4170       R"cpp(
4171 int func(int& a);
4172 )cpp",
4173       R"txt(
4174 TranslationUnit Detached
4175 `-SimpleDeclaration
4176   |-'int'
4177   |-SimpleDeclarator SimpleDeclaration_declarator
4178   | |-'func'
4179   | `-ParametersAndQualifiers
4180   |   |-'(' OpenParen
4181   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4182   |   | `-SimpleDeclaration List_element
4183   |   |   |-'int'
4184   |   |   `-SimpleDeclarator SimpleDeclaration_declarator
4185   |   |     |-'&'
4186   |   |     `-'a'
4187   |   `-')' CloseParen
4188   `-';'
4189 )txt"));
4190 }
4191 
4192 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
4193   if (!GetParam().isCXX11OrLater()) {
4194     return;
4195   }
4196   EXPECT_TRUE(treeDumpEqual(
4197       R"cpp(
4198 int func(int&& a);
4199 )cpp",
4200       R"txt(
4201 TranslationUnit Detached
4202 `-SimpleDeclaration
4203   |-'int'
4204   |-SimpleDeclarator SimpleDeclaration_declarator
4205   | |-'func'
4206   | `-ParametersAndQualifiers
4207   |   |-'(' OpenParen
4208   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4209   |   | `-SimpleDeclaration List_element
4210   |   |   |-'int'
4211   |   |   `-SimpleDeclarator SimpleDeclaration_declarator
4212   |   |     |-'&&'
4213   |   |     `-'a'
4214   |   `-')' CloseParen
4215   `-';'
4216 )txt"));
4217 }
4218 
4219 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
4220   if (!GetParam().isCXX()) {
4221     return;
4222   }
4223   EXPECT_TRUE(treeDumpEqual(
4224       R"cpp(
4225 struct Test {
4226   int a();
4227 };
4228 )cpp",
4229       R"txt(
4230 TranslationUnit Detached
4231 `-SimpleDeclaration
4232   |-'struct'
4233   |-'Test'
4234   |-'{'
4235   |-SimpleDeclaration
4236   | |-'int'
4237   | |-SimpleDeclarator SimpleDeclaration_declarator
4238   | | |-'a'
4239   | | `-ParametersAndQualifiers
4240   | |   |-'(' OpenParen
4241   | |   `-')' CloseParen
4242   | `-';'
4243   |-'}'
4244   `-';'
4245 )txt"));
4246 }
4247 
4248 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
4249   if (!GetParam().isCXX()) {
4250     return;
4251   }
4252   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4253       R"cpp(
4254 struct Test {
4255   [[int b() const;]]
4256   [[int c() volatile;]]
4257   [[int d() const volatile;]]
4258 };
4259 )cpp",
4260       {R"txt(
4261 SimpleDeclaration
4262 |-'int'
4263 |-SimpleDeclarator SimpleDeclaration_declarator
4264 | |-'b'
4265 | `-ParametersAndQualifiers
4266 |   |-'(' OpenParen
4267 |   |-')' CloseParen
4268 |   `-'const'
4269 `-';'
4270 )txt",
4271        R"txt(
4272 SimpleDeclaration
4273 |-'int'
4274 |-SimpleDeclarator SimpleDeclaration_declarator
4275 | |-'c'
4276 | `-ParametersAndQualifiers
4277 |   |-'(' OpenParen
4278 |   |-')' CloseParen
4279 |   `-'volatile'
4280 `-';'
4281 )txt",
4282        R"txt(
4283 SimpleDeclaration
4284 |-'int'
4285 |-SimpleDeclarator SimpleDeclaration_declarator
4286 | |-'d'
4287 | `-ParametersAndQualifiers
4288 |   |-'(' OpenParen
4289 |   |-')' CloseParen
4290 |   |-'const'
4291 |   `-'volatile'
4292 `-';'
4293 )txt"}));
4294 }
4295 
4296 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
4297   if (!GetParam().isCXX11OrLater()) {
4298     return;
4299   }
4300   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4301       R"cpp(
4302 struct Test {
4303   [[int e() &;]]
4304 };
4305 )cpp",
4306       {R"txt(
4307 SimpleDeclaration
4308 |-'int'
4309 |-SimpleDeclarator SimpleDeclaration_declarator
4310 | |-'e'
4311 | `-ParametersAndQualifiers
4312 |   |-'(' OpenParen
4313 |   |-')' CloseParen
4314 |   `-'&'
4315 `-';'
4316 )txt"}));
4317 }
4318 
4319 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
4320   if (!GetParam().isCXX11OrLater()) {
4321     return;
4322   }
4323   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4324       R"cpp(
4325 struct Test {
4326   [[int f() &&;]]
4327 };
4328 )cpp",
4329       {R"txt(
4330 SimpleDeclaration
4331 |-'int'
4332 |-SimpleDeclarator SimpleDeclaration_declarator
4333 | |-'f'
4334 | `-ParametersAndQualifiers
4335 |   |-'(' OpenParen
4336 |   |-')' CloseParen
4337 |   `-'&&'
4338 `-';'
4339 )txt"}));
4340 }
4341 
4342 TEST_P(SyntaxTreeTest, TrailingReturn) {
4343   if (!GetParam().isCXX11OrLater()) {
4344     return;
4345   }
4346   EXPECT_TRUE(treeDumpEqual(
4347       R"cpp(
4348 auto foo() -> int;
4349 )cpp",
4350       R"txt(
4351 TranslationUnit Detached
4352 `-SimpleDeclaration
4353   |-'auto'
4354   |-SimpleDeclarator SimpleDeclaration_declarator
4355   | |-'foo'
4356   | `-ParametersAndQualifiers
4357   |   |-'(' OpenParen
4358   |   |-')' CloseParen
4359   |   `-TrailingReturnType ParametersAndQualifiers_trailingReturn
4360   |     |-'->' ArrowToken
4361   |     `-'int'
4362   `-';'
4363 )txt"));
4364 }
4365 
4366 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
4367   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
4368     return;
4369   }
4370   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4371       R"cpp(
4372 struct MyException1 {};
4373 struct MyException2 {};
4374 [[int a() throw();]]
4375 [[int b() throw(...);]]
4376 [[int c() throw(MyException1);]]
4377 [[int d() throw(MyException1, MyException2);]]
4378 )cpp",
4379       {R"txt(
4380 SimpleDeclaration
4381 |-'int'
4382 |-SimpleDeclarator SimpleDeclaration_declarator
4383 | |-'a'
4384 | `-ParametersAndQualifiers
4385 |   |-'(' OpenParen
4386 |   |-')' CloseParen
4387 |   |-'throw'
4388 |   |-'('
4389 |   `-')'
4390 `-';'
4391 )txt",
4392        R"txt(
4393 SimpleDeclaration
4394 |-'int'
4395 |-SimpleDeclarator SimpleDeclaration_declarator
4396 | |-'b'
4397 | `-ParametersAndQualifiers
4398 |   |-'(' OpenParen
4399 |   |-')' CloseParen
4400 |   |-'throw'
4401 |   |-'('
4402 |   |-'...'
4403 |   `-')'
4404 `-';'
4405 )txt",
4406        R"txt(
4407 SimpleDeclaration
4408 |-'int'
4409 |-SimpleDeclarator SimpleDeclaration_declarator
4410 | |-'c'
4411 | `-ParametersAndQualifiers
4412 |   |-'(' OpenParen
4413 |   |-')' CloseParen
4414 |   |-'throw'
4415 |   |-'('
4416 |   |-'MyException1'
4417 |   `-')'
4418 `-';'
4419 )txt",
4420        R"txt(
4421 SimpleDeclaration
4422 |-'int'
4423 |-SimpleDeclarator SimpleDeclaration_declarator
4424 | |-'d'
4425 | `-ParametersAndQualifiers
4426 |   |-'(' OpenParen
4427 |   |-')' CloseParen
4428 |   |-'throw'
4429 |   |-'('
4430 |   |-'MyException1'
4431 |   |-','
4432 |   |-'MyException2'
4433 |   `-')'
4434 `-';'
4435 )txt"}));
4436 }
4437 
4438 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
4439   if (!GetParam().isCXX11OrLater()) {
4440     return;
4441   }
4442   EXPECT_TRUE(treeDumpEqual(
4443       R"cpp(
4444 int a() noexcept;
4445 int b() noexcept(true);
4446 )cpp",
4447       R"txt(
4448 TranslationUnit Detached
4449 |-SimpleDeclaration
4450 | |-'int'
4451 | |-SimpleDeclarator SimpleDeclaration_declarator
4452 | | |-'a'
4453 | | `-ParametersAndQualifiers
4454 | |   |-'(' OpenParen
4455 | |   |-')' CloseParen
4456 | |   `-'noexcept'
4457 | `-';'
4458 `-SimpleDeclaration
4459   |-'int'
4460   |-SimpleDeclarator SimpleDeclaration_declarator
4461   | |-'b'
4462   | `-ParametersAndQualifiers
4463   |   |-'(' OpenParen
4464   |   |-')' CloseParen
4465   |   |-'noexcept'
4466   |   |-'('
4467   |   |-BoolLiteralExpression
4468   |   | `-'true' LiteralToken
4469   |   `-')'
4470   `-';'
4471 )txt"));
4472 }
4473 
4474 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
4475   EXPECT_TRUE(treeDumpEqual(
4476       R"cpp(
4477 int (a);
4478 int *(b);
4479 int (*c)(int);
4480 int *(d)(int);
4481 )cpp",
4482       R"txt(
4483 TranslationUnit Detached
4484 |-SimpleDeclaration
4485 | |-'int'
4486 | |-SimpleDeclarator SimpleDeclaration_declarator
4487 | | `-ParenDeclarator
4488 | |   |-'(' OpenParen
4489 | |   |-'a'
4490 | |   `-')' CloseParen
4491 | `-';'
4492 |-SimpleDeclaration
4493 | |-'int'
4494 | |-SimpleDeclarator SimpleDeclaration_declarator
4495 | | |-'*'
4496 | | `-ParenDeclarator
4497 | |   |-'(' OpenParen
4498 | |   |-'b'
4499 | |   `-')' CloseParen
4500 | `-';'
4501 |-SimpleDeclaration
4502 | |-'int'
4503 | |-SimpleDeclarator SimpleDeclaration_declarator
4504 | | |-ParenDeclarator
4505 | | | |-'(' OpenParen
4506 | | | |-'*'
4507 | | | |-'c'
4508 | | | `-')' CloseParen
4509 | | `-ParametersAndQualifiers
4510 | |   |-'(' OpenParen
4511 | |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4512 | |   | `-SimpleDeclaration List_element
4513 | |   |   `-'int'
4514 | |   `-')' CloseParen
4515 | `-';'
4516 `-SimpleDeclaration
4517   |-'int'
4518   |-SimpleDeclarator SimpleDeclaration_declarator
4519   | |-'*'
4520   | |-ParenDeclarator
4521   | | |-'(' OpenParen
4522   | | |-'d'
4523   | | `-')' CloseParen
4524   | `-ParametersAndQualifiers
4525   |   |-'(' OpenParen
4526   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4527   |   | `-SimpleDeclaration List_element
4528   |   |   `-'int'
4529   |   `-')' CloseParen
4530   `-';'
4531 )txt"));
4532 }
4533 
4534 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
4535   EXPECT_TRUE(treeDumpEqual(
4536       R"cpp(
4537 const int west = -1;
4538 int const east = 1;
4539 )cpp",
4540       R"txt(
4541 TranslationUnit Detached
4542 |-SimpleDeclaration
4543 | |-'const'
4544 | |-'int'
4545 | |-SimpleDeclarator SimpleDeclaration_declarator
4546 | | |-'west'
4547 | | |-'='
4548 | | `-PrefixUnaryOperatorExpression
4549 | |   |-'-' OperatorExpression_operatorToken
4550 | |   `-IntegerLiteralExpression UnaryOperatorExpression_operand
4551 | |     `-'1' LiteralToken
4552 | `-';'
4553 `-SimpleDeclaration
4554   |-'int'
4555   |-'const'
4556   |-SimpleDeclarator SimpleDeclaration_declarator
4557   | |-'east'
4558   | |-'='
4559   | `-IntegerLiteralExpression
4560   |   `-'1' LiteralToken
4561   `-';'
4562 )txt"));
4563 }
4564 
4565 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
4566   EXPECT_TRUE(treeDumpEqual(
4567       R"cpp(
4568 const int const universal = 0;
4569 )cpp",
4570       R"txt(
4571 TranslationUnit Detached
4572 `-SimpleDeclaration
4573   |-'const'
4574   |-'int'
4575   |-'const'
4576   |-SimpleDeclarator SimpleDeclaration_declarator
4577   | |-'universal'
4578   | |-'='
4579   | `-IntegerLiteralExpression
4580   |   `-'0' LiteralToken
4581   `-';'
4582 )txt"));
4583 }
4584 
4585 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
4586   EXPECT_TRUE(treeDumpEqual(
4587       R"cpp(
4588 const int const *const *volatile b;
4589 )cpp",
4590       R"txt(
4591 TranslationUnit Detached
4592 `-SimpleDeclaration
4593   |-'const'
4594   |-'int'
4595   |-'const'
4596   |-SimpleDeclarator SimpleDeclaration_declarator
4597   | |-'*'
4598   | |-'const'
4599   | |-'*'
4600   | |-'volatile'
4601   | `-'b'
4602   `-';'
4603 )txt"));
4604 }
4605 
4606 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
4607   if (!GetParam().isCXX11OrLater()) {
4608     return;
4609   }
4610   EXPECT_TRUE(treeDumpEqual(
4611       R"cpp(
4612 auto foo() -> auto(*)(int) -> double*;
4613 )cpp",
4614       R"txt(
4615 TranslationUnit Detached
4616 `-SimpleDeclaration
4617   |-'auto'
4618   |-SimpleDeclarator SimpleDeclaration_declarator
4619   | |-'foo'
4620   | `-ParametersAndQualifiers
4621   |   |-'(' OpenParen
4622   |   |-')' CloseParen
4623   |   `-TrailingReturnType ParametersAndQualifiers_trailingReturn
4624   |     |-'->' ArrowToken
4625   |     |-'auto'
4626   |     `-SimpleDeclarator TrailingReturnType_declarator
4627   |       |-ParenDeclarator
4628   |       | |-'(' OpenParen
4629   |       | |-'*'
4630   |       | `-')' CloseParen
4631   |       `-ParametersAndQualifiers
4632   |         |-'(' OpenParen
4633   |         |-ParameterDeclarationList ParametersAndQualifiers_parameters
4634   |         | `-SimpleDeclaration List_element
4635   |         |   `-'int'
4636   |         |-')' CloseParen
4637   |         `-TrailingReturnType ParametersAndQualifiers_trailingReturn
4638   |           |-'->' ArrowToken
4639   |           |-'double'
4640   |           `-SimpleDeclarator TrailingReturnType_declarator
4641   |             `-'*'
4642   `-';'
4643 )txt"));
4644 }
4645 
4646 TEST_P(SyntaxTreeTest, MemberPointers) {
4647   if (!GetParam().isCXX()) {
4648     return;
4649   }
4650   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4651       R"cpp(
4652 struct X {};
4653 [[int X::* a;]]
4654 [[const int X::* b;]]
4655 )cpp",
4656       {R"txt(
4657 SimpleDeclaration
4658 |-'int'
4659 |-SimpleDeclarator SimpleDeclaration_declarator
4660 | |-MemberPointer
4661 | | |-'X'
4662 | | |-'::'
4663 | | `-'*'
4664 | `-'a'
4665 `-';'
4666 )txt",
4667        R"txt(
4668 SimpleDeclaration
4669 |-'const'
4670 |-'int'
4671 |-SimpleDeclarator SimpleDeclaration_declarator
4672 | |-MemberPointer
4673 | | |-'X'
4674 | | |-'::'
4675 | | `-'*'
4676 | `-'b'
4677 `-';'
4678 )txt"}));
4679 }
4680 
4681 TEST_P(SyntaxTreeTest, MemberFunctionPointer) {
4682   if (!GetParam().isCXX()) {
4683     return;
4684   }
4685   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4686       R"cpp(
4687 struct X {
4688   struct Y {};
4689 };
4690 [[void (X::*xp)();]]
4691 [[void (X::**xpp)(const int*);]]
4692 // FIXME: Generate the right syntax tree for this type,
4693 // i.e. create a syntax node for the outer member pointer
4694 [[void (X::Y::*xyp)(const int*, char);]]
4695 )cpp",
4696       {R"txt(
4697 SimpleDeclaration
4698 |-'void'
4699 |-SimpleDeclarator SimpleDeclaration_declarator
4700 | |-ParenDeclarator
4701 | | |-'(' OpenParen
4702 | | |-MemberPointer
4703 | | | |-'X'
4704 | | | |-'::'
4705 | | | `-'*'
4706 | | |-'xp'
4707 | | `-')' CloseParen
4708 | `-ParametersAndQualifiers
4709 |   |-'(' OpenParen
4710 |   `-')' CloseParen
4711 `-';'
4712 )txt",
4713        R"txt(
4714 SimpleDeclaration
4715 |-'void'
4716 |-SimpleDeclarator SimpleDeclaration_declarator
4717 | |-ParenDeclarator
4718 | | |-'(' OpenParen
4719 | | |-MemberPointer
4720 | | | |-'X'
4721 | | | |-'::'
4722 | | | `-'*'
4723 | | |-'*'
4724 | | |-'xpp'
4725 | | `-')' CloseParen
4726 | `-ParametersAndQualifiers
4727 |   |-'(' OpenParen
4728 |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4729 |   | `-SimpleDeclaration List_element
4730 |   |   |-'const'
4731 |   |   |-'int'
4732 |   |   `-SimpleDeclarator SimpleDeclaration_declarator
4733 |   |     `-'*'
4734 |   `-')' CloseParen
4735 `-';'
4736 )txt",
4737        R"txt(
4738 SimpleDeclaration
4739 |-'void'
4740 |-SimpleDeclarator SimpleDeclaration_declarator
4741 | |-ParenDeclarator
4742 | | |-'(' OpenParen
4743 | | |-'X'
4744 | | |-'::'
4745 | | |-MemberPointer
4746 | | | |-'Y'
4747 | | | |-'::'
4748 | | | `-'*'
4749 | | |-'xyp'
4750 | | `-')' CloseParen
4751 | `-ParametersAndQualifiers
4752 |   |-'(' OpenParen
4753 |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4754 |   | |-SimpleDeclaration List_element
4755 |   | | |-'const'
4756 |   | | |-'int'
4757 |   | | `-SimpleDeclarator SimpleDeclaration_declarator
4758 |   | |   `-'*'
4759 |   | |-',' List_delimiter
4760 |   | `-SimpleDeclaration List_element
4761 |   |   `-'char'
4762 |   `-')' CloseParen
4763 `-';'
4764 )txt"}));
4765 }
4766 
4767 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
4768   EXPECT_TRUE(treeDumpEqual(
4769       R"cpp(
4770 void x(char a, short (*b)(int));
4771 )cpp",
4772       R"txt(
4773 TranslationUnit Detached
4774 `-SimpleDeclaration
4775   |-'void'
4776   |-SimpleDeclarator SimpleDeclaration_declarator
4777   | |-'x'
4778   | `-ParametersAndQualifiers
4779   |   |-'(' OpenParen
4780   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4781   |   | |-SimpleDeclaration List_element
4782   |   | | |-'char'
4783   |   | | `-SimpleDeclarator SimpleDeclaration_declarator
4784   |   | |   `-'a'
4785   |   | |-',' List_delimiter
4786   |   | `-SimpleDeclaration List_element
4787   |   |   |-'short'
4788   |   |   `-SimpleDeclarator SimpleDeclaration_declarator
4789   |   |     |-ParenDeclarator
4790   |   |     | |-'(' OpenParen
4791   |   |     | |-'*'
4792   |   |     | |-'b'
4793   |   |     | `-')' CloseParen
4794   |   |     `-ParametersAndQualifiers
4795   |   |       |-'(' OpenParen
4796   |   |       |-ParameterDeclarationList ParametersAndQualifiers_parameters
4797   |   |       | `-SimpleDeclaration List_element
4798   |   |       |   `-'int'
4799   |   |       `-')' CloseParen
4800   |   `-')' CloseParen
4801   `-';'
4802 )txt"));
4803 }
4804 
4805 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
4806   EXPECT_TRUE(treeDumpEqual(
4807       R"cpp(
4808 void x(char a, short (*b)(int), long (**c)(long long));
4809 )cpp",
4810       R"txt(
4811 TranslationUnit Detached
4812 `-SimpleDeclaration
4813   |-'void'
4814   |-SimpleDeclarator SimpleDeclaration_declarator
4815   | |-'x'
4816   | `-ParametersAndQualifiers
4817   |   |-'(' OpenParen
4818   |   |-ParameterDeclarationList ParametersAndQualifiers_parameters
4819   |   | |-SimpleDeclaration List_element
4820   |   | | |-'char'
4821   |   | | `-SimpleDeclarator SimpleDeclaration_declarator
4822   |   | |   `-'a'
4823   |   | |-',' List_delimiter
4824   |   | |-SimpleDeclaration List_element
4825   |   | | |-'short'
4826   |   | | `-SimpleDeclarator SimpleDeclaration_declarator
4827   |   | |   |-ParenDeclarator
4828   |   | |   | |-'(' OpenParen
4829   |   | |   | |-'*'
4830   |   | |   | |-'b'
4831   |   | |   | `-')' CloseParen
4832   |   | |   `-ParametersAndQualifiers
4833   |   | |     |-'(' OpenParen
4834   |   | |     |-ParameterDeclarationList ParametersAndQualifiers_parameters
4835   |   | |     | `-SimpleDeclaration List_element
4836   |   | |     |   `-'int'
4837   |   | |     `-')' CloseParen
4838   |   | |-',' List_delimiter
4839   |   | `-SimpleDeclaration List_element
4840   |   |   |-'long'
4841   |   |   `-SimpleDeclarator SimpleDeclaration_declarator
4842   |   |     |-ParenDeclarator
4843   |   |     | |-'(' OpenParen
4844   |   |     | |-'*'
4845   |   |     | |-'*'
4846   |   |     | |-'c'
4847   |   |     | `-')' CloseParen
4848   |   |     `-ParametersAndQualifiers
4849   |   |       |-'(' OpenParen
4850   |   |       |-ParameterDeclarationList ParametersAndQualifiers_parameters
4851   |   |       | `-SimpleDeclaration List_element
4852   |   |       |   |-'long'
4853   |   |       |   `-'long'
4854   |   |       `-')' CloseParen
4855   |   `-')' CloseParen
4856   `-';'
4857 )txt"));
4858 }
4859 
4860 } // namespace
4861