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