xref: /llvm-project/clang/unittests/Tooling/Syntax/BuildTreeTest.cpp (revision 3b75f65e6ba4862977fd193ddb4918c4fc380fa5)
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 )cpp",
2874       R"txt(
2875 TranslationUnit Detached
2876 `-NamespaceDefinition
2877   |-'namespace'
2878   |-'a'
2879   |-'{'
2880   |-NamespaceDefinition
2881   | |-'namespace'
2882   | |-'b'
2883   | |-'{'
2884   | `-'}'
2885   `-'}'
2886 )txt"));
2887 }
2888 
2889 TEST_P(SyntaxTreeTest, Namespace_NestedDefinition) {
2890   if (!GetParam().isCXX17OrLater()) {
2891     return;
2892   }
2893   EXPECT_TRUE(treeDumpEqual(
2894       R"cpp(
2895 namespace a::b {}
2896 )cpp",
2897       R"txt(
2898 TranslationUnit Detached
2899 `-NamespaceDefinition
2900   |-'namespace'
2901   |-'a'
2902   |-'::'
2903   |-'b'
2904   |-'{'
2905   `-'}'
2906 )txt"));
2907 }
2908 
2909 TEST_P(SyntaxTreeTest, Namespace_Unnamed) {
2910   if (!GetParam().isCXX()) {
2911     return;
2912   }
2913   EXPECT_TRUE(treeDumpEqual(
2914       R"cpp(
2915 namespace {}
2916 )cpp",
2917       R"txt(
2918 TranslationUnit Detached
2919 `-NamespaceDefinition
2920   |-'namespace'
2921   |-'{'
2922   `-'}'
2923 )txt"));
2924 }
2925 
2926 TEST_P(SyntaxTreeTest, Namespace_Alias) {
2927   if (!GetParam().isCXX()) {
2928     return;
2929   }
2930   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2931       R"cpp(
2932 namespace a {}
2933 [[namespace foo = a;]]
2934 )cpp",
2935       {R"txt(
2936 NamespaceAliasDefinition
2937 |-'namespace'
2938 |-'foo'
2939 |-'='
2940 |-'a'
2941 `-';'
2942 )txt"}));
2943 }
2944 
2945 TEST_P(SyntaxTreeTest, UsingDirective) {
2946   if (!GetParam().isCXX()) {
2947     return;
2948   }
2949   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2950       R"cpp(
2951 namespace ns {}
2952 [[using namespace ::ns;]]
2953 )cpp",
2954       {R"txt(
2955 UsingNamespaceDirective
2956 |-'using'
2957 |-'namespace'
2958 |-NestedNameSpecifier
2959 | `-'::' List_delimiter
2960 |-'ns'
2961 `-';'
2962 )txt"}));
2963 }
2964 
2965 TEST_P(SyntaxTreeTest, UsingDeclaration_Namespace) {
2966   if (!GetParam().isCXX()) {
2967     return;
2968   }
2969   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2970       R"cpp(
2971 namespace ns { int a; }
2972 [[using ns::a;]]
2973 )cpp",
2974       {R"txt(
2975 UsingDeclaration
2976 |-'using'
2977 |-NestedNameSpecifier
2978 | |-IdentifierNameSpecifier List_element
2979 | | `-'ns'
2980 | `-'::' List_delimiter
2981 |-'a'
2982 `-';'
2983 )txt"}));
2984 }
2985 
2986 TEST_P(SyntaxTreeTest, UsingDeclaration_ClassMember) {
2987   if (!GetParam().isCXX()) {
2988     return;
2989   }
2990   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2991       R"cpp(
2992 template <class T> struct X {
2993   [[using T::foo;]]
2994   [[using typename T::bar;]]
2995 };
2996 )cpp",
2997       {R"txt(
2998 UsingDeclaration
2999 |-'using'
3000 |-NestedNameSpecifier
3001 | |-IdentifierNameSpecifier List_element
3002 | | `-'T'
3003 | `-'::' List_delimiter
3004 |-'foo'
3005 `-';'
3006 )txt",
3007        R"txt(
3008 UsingDeclaration
3009 |-'using'
3010 |-'typename'
3011 |-NestedNameSpecifier
3012 | |-IdentifierNameSpecifier List_element
3013 | | `-'T'
3014 | `-'::' List_delimiter
3015 |-'bar'
3016 `-';'
3017 )txt"}));
3018 }
3019 
3020 TEST_P(SyntaxTreeTest, UsingTypeAlias) {
3021   if (!GetParam().isCXX11OrLater()) {
3022     return;
3023   }
3024   EXPECT_TRUE(treeDumpEqual(
3025       R"cpp(
3026 using type = int;
3027 )cpp",
3028       R"txt(
3029 TranslationUnit Detached
3030 `-TypeAliasDeclaration
3031   |-'using'
3032   |-'type'
3033   |-'='
3034   |-'int'
3035   `-';'
3036 )txt"));
3037 }
3038 
3039 TEST_P(SyntaxTreeTest, FreeStandingClass_ForwardDeclaration) {
3040   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3041       R"cpp(
3042 [[struct X;]]
3043 [[struct Y *y1;]]
3044 )cpp",
3045       {R"txt(
3046 SimpleDeclaration
3047 |-'struct'
3048 |-'X'
3049 `-';'
3050 )txt",
3051        R"txt(
3052 SimpleDeclaration
3053 |-'struct'
3054 |-'Y'
3055 |-SimpleDeclarator SimpleDeclaration_declarator
3056 | |-'*'
3057 | `-'y1'
3058 `-';'
3059 )txt"}));
3060 }
3061 
3062 TEST_P(SyntaxTreeTest, FreeStandingClasses_Definition) {
3063   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3064       R"cpp(
3065 [[struct X {};]]
3066 [[struct Y {} *y2;]]
3067 [[struct {} *a1;]]
3068 )cpp",
3069       {R"txt(
3070 SimpleDeclaration
3071 |-'struct'
3072 |-'X'
3073 |-'{'
3074 |-'}'
3075 `-';'
3076 )txt",
3077        R"txt(
3078 SimpleDeclaration
3079 |-'struct'
3080 |-'Y'
3081 |-'{'
3082 |-'}'
3083 |-SimpleDeclarator SimpleDeclaration_declarator
3084 | |-'*'
3085 | `-'y2'
3086 `-';'
3087 )txt",
3088        R"txt(
3089 SimpleDeclaration
3090 |-'struct'
3091 |-'{'
3092 |-'}'
3093 |-SimpleDeclarator SimpleDeclaration_declarator
3094 | |-'*'
3095 | `-'a1'
3096 `-';'
3097 )txt"}));
3098 }
3099 
3100 TEST_P(SyntaxTreeTest, StaticMemberFunction) {
3101   if (!GetParam().isCXX11OrLater()) {
3102     return;
3103   }
3104   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3105       R"cpp(
3106 struct S {
3107   [[static void f(){}]]
3108 };
3109 )cpp",
3110       {R"txt(
3111 SimpleDeclaration
3112 |-'static'
3113 |-'void'
3114 |-SimpleDeclarator SimpleDeclaration_declarator
3115 | |-'f'
3116 | `-ParametersAndQualifiers
3117 |   |-'(' OpenParen
3118 |   `-')' CloseParen
3119 `-CompoundStatement
3120   |-'{' OpenParen
3121   `-'}' CloseParen
3122 )txt"}));
3123 }
3124 
3125 TEST_P(SyntaxTreeTest, ConversionMemberFunction) {
3126   if (!GetParam().isCXX()) {
3127     return;
3128   }
3129   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3130       R"cpp(
3131 struct X {
3132   [[operator int();]]
3133 };
3134 )cpp",
3135       {R"txt(
3136 SimpleDeclaration
3137 |-SimpleDeclarator SimpleDeclaration_declarator
3138 | |-'operator'
3139 | |-'int'
3140 | `-ParametersAndQualifiers
3141 |   |-'(' OpenParen
3142 |   `-')' CloseParen
3143 `-';'
3144 )txt"}));
3145 }
3146 
3147 TEST_P(SyntaxTreeTest, LiteralOperatorDeclaration) {
3148   if (!GetParam().isCXX11OrLater()) {
3149     return;
3150   }
3151   EXPECT_TRUE(treeDumpEqual(
3152       R"cpp(
3153 unsigned operator "" _c(char);
3154     )cpp",
3155       R"txt(
3156 TranslationUnit Detached
3157 `-SimpleDeclaration
3158   |-'unsigned'
3159   |-SimpleDeclarator SimpleDeclaration_declarator
3160   | |-'operator'
3161   | |-'""'
3162   | |-'_c'
3163   | `-ParametersAndQualifiers
3164   |   |-'(' OpenParen
3165   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3166   |   | `-'char'
3167   |   `-')' CloseParen
3168   `-';'
3169 )txt"));
3170 }
3171 
3172 TEST_P(SyntaxTreeTest, NumericLiteralOperatorTemplateDeclaration) {
3173   if (!GetParam().isCXX11OrLater()) {
3174     return;
3175   }
3176   EXPECT_TRUE(treeDumpEqual(
3177       R"cpp(
3178 template <char...>
3179 unsigned operator "" _t();
3180     )cpp",
3181       R"txt(
3182 TranslationUnit Detached
3183 `-TemplateDeclaration TemplateDeclaration_declaration
3184   |-'template' IntroducerKeyword
3185   |-'<'
3186   |-SimpleDeclaration
3187   | `-'char'
3188   |-'...'
3189   |-'>'
3190   `-SimpleDeclaration
3191     |-'unsigned'
3192     |-SimpleDeclarator SimpleDeclaration_declarator
3193     | |-'operator'
3194     | |-'""'
3195     | |-'_t'
3196     | `-ParametersAndQualifiers
3197     |   |-'(' OpenParen
3198     |   `-')' CloseParen
3199     `-';'
3200 )txt"));
3201 }
3202 
3203 TEST_P(SyntaxTreeTest, OverloadedOperatorDeclaration) {
3204   if (!GetParam().isCXX()) {
3205     return;
3206   }
3207   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3208       R"cpp(
3209 struct X {
3210   [[X& operator=(const X&);]]
3211 };
3212 )cpp",
3213       {R"txt(
3214 SimpleDeclaration
3215 |-'X'
3216 |-SimpleDeclarator SimpleDeclaration_declarator
3217 | |-'&'
3218 | |-'operator'
3219 | |-'='
3220 | `-ParametersAndQualifiers
3221 |   |-'(' OpenParen
3222 |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3223 |   | |-'const'
3224 |   | |-'X'
3225 |   | `-SimpleDeclarator SimpleDeclaration_declarator
3226 |   |   `-'&'
3227 |   `-')' CloseParen
3228 `-';'
3229 )txt"}));
3230 }
3231 
3232 TEST_P(SyntaxTreeTest, OverloadedOperatorFriendDeclaration) {
3233   if (!GetParam().isCXX()) {
3234     return;
3235   }
3236   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3237       R"cpp(
3238 struct X {
3239   [[friend X operator+(X, const X&);]]
3240 };
3241 )cpp",
3242       {R"txt(
3243 UnknownDeclaration
3244 `-SimpleDeclaration
3245   |-'friend'
3246   |-'X'
3247   |-SimpleDeclarator SimpleDeclaration_declarator
3248   | |-'operator'
3249   | |-'+'
3250   | `-ParametersAndQualifiers
3251   |   |-'(' OpenParen
3252   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3253   |   | `-'X'
3254   |   |-','
3255   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3256   |   | |-'const'
3257   |   | |-'X'
3258   |   | `-SimpleDeclarator SimpleDeclaration_declarator
3259   |   |   `-'&'
3260   |   `-')' CloseParen
3261   `-';'
3262 )txt"}));
3263 }
3264 
3265 TEST_P(SyntaxTreeTest, ClassTemplateDeclaration) {
3266   if (!GetParam().isCXX()) {
3267     return;
3268   }
3269   EXPECT_TRUE(treeDumpEqual(
3270       R"cpp(
3271 template<typename T>
3272 struct ST {};
3273 )cpp",
3274       R"txt(
3275 TranslationUnit Detached
3276 `-TemplateDeclaration TemplateDeclaration_declaration
3277   |-'template' IntroducerKeyword
3278   |-'<'
3279   |-UnknownDeclaration
3280   | |-'typename'
3281   | `-'T'
3282   |-'>'
3283   `-SimpleDeclaration
3284     |-'struct'
3285     |-'ST'
3286     |-'{'
3287     |-'}'
3288     `-';'
3289 )txt"));
3290 }
3291 
3292 TEST_P(SyntaxTreeTest, FunctionTemplateDeclaration) {
3293   if (!GetParam().isCXX()) {
3294     return;
3295   }
3296   EXPECT_TRUE(treeDumpEqual(
3297       R"cpp(
3298 template<typename T>
3299 T f();
3300 )cpp",
3301       R"txt(
3302 TranslationUnit Detached
3303 `-TemplateDeclaration TemplateDeclaration_declaration
3304   |-'template' IntroducerKeyword
3305   |-'<'
3306   |-UnknownDeclaration
3307   | |-'typename'
3308   | `-'T'
3309   |-'>'
3310   `-SimpleDeclaration
3311     |-'T'
3312     |-SimpleDeclarator SimpleDeclaration_declarator
3313     | |-'f'
3314     | `-ParametersAndQualifiers
3315     |   |-'(' OpenParen
3316     |   `-')' CloseParen
3317     `-';'
3318 )txt"));
3319 }
3320 
3321 TEST_P(SyntaxTreeTest, VariableTemplateDeclaration) {
3322   if (!GetParam().isCXX14OrLater()) {
3323     return;
3324   }
3325   EXPECT_TRUE(treeDumpEqual(
3326       R"cpp(
3327 template <class T> T var = 10;
3328 )cpp",
3329       R"txt(
3330 TranslationUnit Detached
3331 `-TemplateDeclaration TemplateDeclaration_declaration
3332   |-'template' IntroducerKeyword
3333   |-'<'
3334   |-UnknownDeclaration
3335   | |-'class'
3336   | `-'T'
3337   |-'>'
3338   `-SimpleDeclaration
3339     |-'T'
3340     |-SimpleDeclarator SimpleDeclaration_declarator
3341     | |-'var'
3342     | |-'='
3343     | `-IntegerLiteralExpression
3344     |   `-'10' LiteralToken
3345     `-';'
3346 )txt"));
3347 }
3348 
3349 TEST_P(SyntaxTreeTest, StaticMemberFunctionTemplate) {
3350   if (!GetParam().isCXX()) {
3351     return;
3352   }
3353   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3354       R"cpp(
3355 struct S {
3356   [[template<typename U>
3357   static U f();]]
3358 };
3359 )cpp",
3360       {R"txt(
3361 TemplateDeclaration TemplateDeclaration_declaration
3362 |-'template' IntroducerKeyword
3363 |-'<'
3364 |-UnknownDeclaration
3365 | |-'typename'
3366 | `-'U'
3367 |-'>'
3368 `-SimpleDeclaration
3369   |-'static'
3370   |-'U'
3371   |-SimpleDeclarator SimpleDeclaration_declarator
3372   | |-'f'
3373   | `-ParametersAndQualifiers
3374   |   |-'(' OpenParen
3375   |   `-')' CloseParen
3376   `-';'
3377 )txt"}));
3378 }
3379 
3380 TEST_P(SyntaxTreeTest, NestedTemplates) {
3381   if (!GetParam().isCXX()) {
3382     return;
3383   }
3384   EXPECT_TRUE(treeDumpEqual(
3385       R"cpp(
3386 template <class T>
3387 struct X {
3388   template <class U>
3389   U foo();
3390 };
3391 )cpp",
3392       R"txt(
3393 TranslationUnit Detached
3394 `-TemplateDeclaration TemplateDeclaration_declaration
3395   |-'template' IntroducerKeyword
3396   |-'<'
3397   |-UnknownDeclaration
3398   | |-'class'
3399   | `-'T'
3400   |-'>'
3401   `-SimpleDeclaration
3402     |-'struct'
3403     |-'X'
3404     |-'{'
3405     |-TemplateDeclaration TemplateDeclaration_declaration
3406     | |-'template' IntroducerKeyword
3407     | |-'<'
3408     | |-UnknownDeclaration
3409     | | |-'class'
3410     | | `-'U'
3411     | |-'>'
3412     | `-SimpleDeclaration
3413     |   |-'U'
3414     |   |-SimpleDeclarator SimpleDeclaration_declarator
3415     |   | |-'foo'
3416     |   | `-ParametersAndQualifiers
3417     |   |   |-'(' OpenParen
3418     |   |   `-')' CloseParen
3419     |   `-';'
3420     |-'}'
3421     `-';'
3422 )txt"));
3423 }
3424 
3425 TEST_P(SyntaxTreeTest, NestedTemplatesInNamespace) {
3426   if (!GetParam().isCXX()) {
3427     return;
3428   }
3429   EXPECT_TRUE(treeDumpEqual(
3430       R"cpp(
3431 namespace n {
3432   template<typename T>
3433   struct ST {
3434     template<typename U>
3435     static U f();
3436   };
3437 }
3438 )cpp",
3439       R"txt(
3440 TranslationUnit Detached
3441 `-NamespaceDefinition
3442   |-'namespace'
3443   |-'n'
3444   |-'{'
3445   |-TemplateDeclaration TemplateDeclaration_declaration
3446   | |-'template' IntroducerKeyword
3447   | |-'<'
3448   | |-UnknownDeclaration
3449   | | |-'typename'
3450   | | `-'T'
3451   | |-'>'
3452   | `-SimpleDeclaration
3453   |   |-'struct'
3454   |   |-'ST'
3455   |   |-'{'
3456   |   |-TemplateDeclaration TemplateDeclaration_declaration
3457   |   | |-'template' IntroducerKeyword
3458   |   | |-'<'
3459   |   | |-UnknownDeclaration
3460   |   | | |-'typename'
3461   |   | | `-'U'
3462   |   | |-'>'
3463   |   | `-SimpleDeclaration
3464   |   |   |-'static'
3465   |   |   |-'U'
3466   |   |   |-SimpleDeclarator SimpleDeclaration_declarator
3467   |   |   | |-'f'
3468   |   |   | `-ParametersAndQualifiers
3469   |   |   |   |-'(' OpenParen
3470   |   |   |   `-')' CloseParen
3471   |   |   `-';'
3472   |   |-'}'
3473   |   `-';'
3474   `-'}'
3475 )txt"));
3476 }
3477 
3478 TEST_P(SyntaxTreeTest, ClassTemplate_MemberClassDefinition) {
3479   if (!GetParam().isCXX()) {
3480     return;
3481   }
3482   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3483       R"cpp(
3484 template <class T> struct X { struct Y; };
3485 [[template <class T> struct X<T>::Y {};]]
3486 )cpp",
3487       {R"txt(
3488 TemplateDeclaration TemplateDeclaration_declaration
3489 |-'template' IntroducerKeyword
3490 |-'<'
3491 |-UnknownDeclaration
3492 | |-'class'
3493 | `-'T'
3494 |-'>'
3495 `-SimpleDeclaration
3496   |-'struct'
3497   |-NestedNameSpecifier
3498   | |-SimpleTemplateNameSpecifier List_element
3499   | | |-'X'
3500   | | |-'<'
3501   | | |-'T'
3502   | | `-'>'
3503   | `-'::' List_delimiter
3504   |-'Y'
3505   |-'{'
3506   |-'}'
3507   `-';'
3508 )txt"}));
3509 }
3510 
3511 TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Definition) {
3512   if (!GetParam().isCXX()) {
3513     return;
3514   }
3515   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3516       R"cpp(
3517 template <class T> struct X {};
3518 [[template struct X<double>;]]
3519 )cpp",
3520       {R"txt(
3521 ExplicitTemplateInstantiation
3522 |-'template' IntroducerKeyword
3523 `-SimpleDeclaration ExplicitTemplateInstantiation_declaration
3524   |-'struct'
3525   |-'X'
3526   |-'<'
3527   |-'double'
3528   |-'>'
3529   `-';'
3530 )txt"}));
3531 }
3532 
3533 TEST_P(SyntaxTreeTest, ExplicitClassTemplateInstantation_Declaration) {
3534   if (!GetParam().isCXX()) {
3535     return;
3536   }
3537   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3538       R"cpp(
3539 template <class T> struct X {};
3540 [[extern template struct X<float>;]]
3541 )cpp",
3542       {R"txt(
3543 ExplicitTemplateInstantiation
3544 |-'extern' ExternKeyword
3545 |-'template' IntroducerKeyword
3546 `-SimpleDeclaration ExplicitTemplateInstantiation_declaration
3547   |-'struct'
3548   |-'X'
3549   |-'<'
3550   |-'float'
3551   |-'>'
3552   `-';'
3553 )txt"}));
3554 }
3555 
3556 TEST_P(SyntaxTreeTest, ClassTemplateSpecialization_Partial) {
3557   if (!GetParam().isCXX()) {
3558     return;
3559   }
3560   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3561       R"cpp(
3562 template <class T> struct X {};
3563 [[template <class T> struct X<T*> {};]]
3564 )cpp",
3565       {R"txt(
3566 TemplateDeclaration TemplateDeclaration_declaration
3567 |-'template' IntroducerKeyword
3568 |-'<'
3569 |-UnknownDeclaration
3570 | |-'class'
3571 | `-'T'
3572 |-'>'
3573 `-SimpleDeclaration
3574   |-'struct'
3575   |-'X'
3576   |-'<'
3577   |-'T'
3578   |-'*'
3579   |-'>'
3580   |-'{'
3581   |-'}'
3582   `-';'
3583 )txt"}));
3584 }
3585 
3586 TEST_P(SyntaxTreeTest, ClassTemplateSpecialization_Full) {
3587   if (!GetParam().isCXX()) {
3588     return;
3589   }
3590   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3591       R"cpp(
3592 template <class T> struct X {};
3593 [[template <> struct X<int> {};]]
3594 )cpp",
3595       {R"txt(
3596 TemplateDeclaration TemplateDeclaration_declaration
3597 |-'template' IntroducerKeyword
3598 |-'<'
3599 |-'>'
3600 `-SimpleDeclaration
3601   |-'struct'
3602   |-'X'
3603   |-'<'
3604   |-'int'
3605   |-'>'
3606   |-'{'
3607   |-'}'
3608   `-';'
3609 )txt"}));
3610 }
3611 
3612 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
3613   EXPECT_TRUE(treeDumpEqual(
3614       R"cpp(
3615 ;
3616 )cpp",
3617       R"txt(
3618 TranslationUnit Detached
3619 `-EmptyDeclaration
3620   `-';'
3621 )txt"));
3622 }
3623 
3624 TEST_P(SyntaxTreeTest, StaticAssert) {
3625   if (!GetParam().isCXX11OrLater()) {
3626     return;
3627   }
3628   EXPECT_TRUE(treeDumpEqual(
3629       R"cpp(
3630 static_assert(true, "message");
3631 )cpp",
3632       R"txt(
3633 TranslationUnit Detached
3634 `-StaticAssertDeclaration
3635   |-'static_assert'
3636   |-'('
3637   |-BoolLiteralExpression StaticAssertDeclaration_condition
3638   | `-'true' LiteralToken
3639   |-','
3640   |-StringLiteralExpression StaticAssertDeclaration_message
3641   | `-'"message"' LiteralToken
3642   |-')'
3643   `-';'
3644 )txt"));
3645 }
3646 
3647 TEST_P(SyntaxTreeTest, StaticAssert_WithoutMessage) {
3648   if (!GetParam().isCXX17OrLater()) {
3649     return;
3650   }
3651   EXPECT_TRUE(treeDumpEqual(
3652       R"cpp(
3653 static_assert(true);
3654 )cpp",
3655       R"txt(
3656 TranslationUnit Detached
3657 `-StaticAssertDeclaration
3658   |-'static_assert'
3659   |-'('
3660   |-BoolLiteralExpression StaticAssertDeclaration_condition
3661   | `-'true' LiteralToken
3662   |-')'
3663   `-';'
3664 )txt"));
3665 }
3666 
3667 TEST_P(SyntaxTreeTest, ExternC) {
3668   if (!GetParam().isCXX()) {
3669     return;
3670   }
3671   EXPECT_TRUE(treeDumpEqual(
3672       R"cpp(
3673 extern "C" int a;
3674 extern "C" { int b; int c; }
3675 )cpp",
3676       R"txt(
3677 TranslationUnit Detached
3678 |-LinkageSpecificationDeclaration
3679 | |-'extern'
3680 | |-'"C"'
3681 | `-SimpleDeclaration
3682 |   |-'int'
3683 |   |-SimpleDeclarator SimpleDeclaration_declarator
3684 |   | `-'a'
3685 |   `-';'
3686 `-LinkageSpecificationDeclaration
3687   |-'extern'
3688   |-'"C"'
3689   |-'{'
3690   |-SimpleDeclaration
3691   | |-'int'
3692   | |-SimpleDeclarator SimpleDeclaration_declarator
3693   | | `-'b'
3694   | `-';'
3695   |-SimpleDeclaration
3696   | |-'int'
3697   | |-SimpleDeclarator SimpleDeclaration_declarator
3698   | | `-'c'
3699   | `-';'
3700   `-'}'
3701 )txt"));
3702 }
3703 
3704 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
3705   // Some nodes are non-modifiable, they are marked with 'I:'.
3706   EXPECT_TRUE(treeDumpEqual(
3707       R"cpp(
3708 #define HALF_IF if (1+
3709 #define HALF_IF_2 1) {}
3710 void test() {
3711   HALF_IF HALF_IF_2 else {}
3712 })cpp",
3713       R"txt(
3714 TranslationUnit Detached
3715 `-SimpleDeclaration
3716   |-'void'
3717   |-SimpleDeclarator SimpleDeclaration_declarator
3718   | |-'test'
3719   | `-ParametersAndQualifiers
3720   |   |-'(' OpenParen
3721   |   `-')' CloseParen
3722   `-CompoundStatement
3723     |-'{' OpenParen
3724     |-IfStatement CompoundStatement_statement
3725     | |-'if' IntroducerKeyword unmodifiable
3726     | |-'(' unmodifiable
3727     | |-BinaryOperatorExpression unmodifiable
3728     | | |-IntegerLiteralExpression BinaryOperatorExpression_leftHandSide unmodifiable
3729     | | | `-'1' LiteralToken unmodifiable
3730     | | |-'+' OperatorExpression_operatorToken unmodifiable
3731     | | `-IntegerLiteralExpression BinaryOperatorExpression_rightHandSide unmodifiable
3732     | |   `-'1' LiteralToken unmodifiable
3733     | |-')' unmodifiable
3734     | |-CompoundStatement IfStatement_thenStatement unmodifiable
3735     | | |-'{' OpenParen unmodifiable
3736     | | `-'}' CloseParen unmodifiable
3737     | |-'else' IfStatement_elseKeyword
3738     | `-CompoundStatement IfStatement_elseStatement
3739     |   |-'{' OpenParen
3740     |   `-'}' CloseParen
3741     `-'}' CloseParen
3742 )txt"));
3743 }
3744 
3745 TEST_P(SyntaxTreeTest, ModifiableNodes) {
3746   // All nodes can be mutated.
3747   EXPECT_TRUE(treeDumpEqual(
3748       R"cpp(
3749 #define OPEN {
3750 #define CLOSE }
3751 
3752 void test() {
3753   OPEN
3754     1;
3755   CLOSE
3756 
3757   OPEN
3758     2;
3759   }
3760 }
3761 )cpp",
3762       R"txt(
3763 TranslationUnit Detached
3764 `-SimpleDeclaration
3765   |-'void'
3766   |-SimpleDeclarator SimpleDeclaration_declarator
3767   | |-'test'
3768   | `-ParametersAndQualifiers
3769   |   |-'(' OpenParen
3770   |   `-')' CloseParen
3771   `-CompoundStatement
3772     |-'{' OpenParen
3773     |-CompoundStatement CompoundStatement_statement
3774     | |-'{' OpenParen
3775     | |-ExpressionStatement CompoundStatement_statement
3776     | | |-IntegerLiteralExpression ExpressionStatement_expression
3777     | | | `-'1' LiteralToken
3778     | | `-';'
3779     | `-'}' CloseParen
3780     |-CompoundStatement CompoundStatement_statement
3781     | |-'{' OpenParen
3782     | |-ExpressionStatement CompoundStatement_statement
3783     | | |-IntegerLiteralExpression ExpressionStatement_expression
3784     | | | `-'2' LiteralToken
3785     | | `-';'
3786     | `-'}' CloseParen
3787     `-'}' CloseParen
3788 )txt"));
3789 }
3790 
3791 TEST_P(SyntaxTreeTest, ArrayDeclarator_Simple) {
3792   EXPECT_TRUE(treeDumpEqual(
3793       R"cpp(
3794 int a[10];
3795 )cpp",
3796       R"txt(
3797 TranslationUnit Detached
3798 `-SimpleDeclaration
3799   |-'int'
3800   |-SimpleDeclarator SimpleDeclaration_declarator
3801   | |-'a'
3802   | `-ArraySubscript
3803   |   |-'[' OpenParen
3804   |   |-IntegerLiteralExpression ArraySubscript_sizeExpression
3805   |   | `-'10' LiteralToken
3806   |   `-']' CloseParen
3807   `-';'
3808 )txt"));
3809 }
3810 
3811 TEST_P(SyntaxTreeTest, ArrayDeclarator_Multidimensional) {
3812   EXPECT_TRUE(treeDumpEqual(
3813       R"cpp(
3814 int b[1][2][3];
3815 )cpp",
3816       R"txt(
3817 TranslationUnit Detached
3818 `-SimpleDeclaration
3819   |-'int'
3820   |-SimpleDeclarator SimpleDeclaration_declarator
3821   | |-'b'
3822   | |-ArraySubscript
3823   | | |-'[' OpenParen
3824   | | |-IntegerLiteralExpression ArraySubscript_sizeExpression
3825   | | | `-'1' LiteralToken
3826   | | `-']' CloseParen
3827   | |-ArraySubscript
3828   | | |-'[' OpenParen
3829   | | |-IntegerLiteralExpression ArraySubscript_sizeExpression
3830   | | | `-'2' LiteralToken
3831   | | `-']' CloseParen
3832   | `-ArraySubscript
3833   |   |-'[' OpenParen
3834   |   |-IntegerLiteralExpression ArraySubscript_sizeExpression
3835   |   | `-'3' LiteralToken
3836   |   `-']' CloseParen
3837   `-';'
3838 )txt"));
3839 }
3840 
3841 TEST_P(SyntaxTreeTest, ArrayDeclarator_UnknownBound) {
3842   EXPECT_TRUE(treeDumpEqual(
3843       R"cpp(
3844 int c[] = {1,2,3};
3845 )cpp",
3846       R"txt(
3847 TranslationUnit Detached
3848 `-SimpleDeclaration
3849   |-'int'
3850   |-SimpleDeclarator SimpleDeclaration_declarator
3851   | |-'c'
3852   | |-ArraySubscript
3853   | | |-'[' OpenParen
3854   | | `-']' CloseParen
3855   | |-'='
3856   | `-UnknownExpression
3857   |   `-UnknownExpression
3858   |     |-'{'
3859   |     |-IntegerLiteralExpression
3860   |     | `-'1' LiteralToken
3861   |     |-','
3862   |     |-IntegerLiteralExpression
3863   |     | `-'2' LiteralToken
3864   |     |-','
3865   |     |-IntegerLiteralExpression
3866   |     | `-'3' LiteralToken
3867   |     `-'}'
3868   `-';'
3869 )txt"));
3870 }
3871 
3872 TEST_P(SyntaxTreeTest, ArrayDeclarator_Static) {
3873   if (!GetParam().isC99OrLater()) {
3874     return;
3875   }
3876   EXPECT_TRUE(treeDumpEqual(
3877       R"cpp(
3878 void f(int xs[static 10]);
3879 )cpp",
3880       R"txt(
3881 TranslationUnit Detached
3882 `-SimpleDeclaration
3883   |-'void'
3884   |-SimpleDeclarator SimpleDeclaration_declarator
3885   | |-'f'
3886   | `-ParametersAndQualifiers
3887   |   |-'(' OpenParen
3888   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3889   |   | |-'int'
3890   |   | `-SimpleDeclarator SimpleDeclaration_declarator
3891   |   |   |-'xs'
3892   |   |   `-ArraySubscript
3893   |   |     |-'[' OpenParen
3894   |   |     |-'static'
3895   |   |     |-IntegerLiteralExpression ArraySubscript_sizeExpression
3896   |   |     | `-'10' LiteralToken
3897   |   |     `-']' CloseParen
3898   |   `-')' CloseParen
3899   `-';'
3900 )txt"));
3901 }
3902 
3903 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) {
3904   EXPECT_TRUE(treeDumpEqual(
3905       R"cpp(
3906 int func();
3907 )cpp",
3908       R"txt(
3909 TranslationUnit Detached
3910 `-SimpleDeclaration
3911   |-'int'
3912   |-SimpleDeclarator SimpleDeclaration_declarator
3913   | |-'func'
3914   | `-ParametersAndQualifiers
3915   |   |-'(' OpenParen
3916   |   `-')' CloseParen
3917   `-';'
3918 )txt"));
3919 }
3920 
3921 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) {
3922   EXPECT_TRUE(treeDumpEqual(
3923       R"cpp(
3924 int func1(int a);
3925 int func2(int *ap);
3926 int func3(int a, float b);
3927 )cpp",
3928       R"txt(
3929 TranslationUnit Detached
3930 |-SimpleDeclaration
3931 | |-'int'
3932 | |-SimpleDeclarator SimpleDeclaration_declarator
3933 | | |-'func1'
3934 | | `-ParametersAndQualifiers
3935 | |   |-'(' OpenParen
3936 | |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3937 | |   | |-'int'
3938 | |   | `-SimpleDeclarator SimpleDeclaration_declarator
3939 | |   |   `-'a'
3940 | |   `-')' CloseParen
3941 | `-';'
3942 |-SimpleDeclaration
3943 | |-'int'
3944 | |-SimpleDeclarator SimpleDeclaration_declarator
3945 | | |-'func2'
3946 | | `-ParametersAndQualifiers
3947 | |   |-'(' OpenParen
3948 | |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3949 | |   | |-'int'
3950 | |   | `-SimpleDeclarator SimpleDeclaration_declarator
3951 | |   |   |-'*'
3952 | |   |   `-'ap'
3953 | |   `-')' CloseParen
3954 | `-';'
3955 `-SimpleDeclaration
3956   |-'int'
3957   |-SimpleDeclarator SimpleDeclaration_declarator
3958   | |-'func3'
3959   | `-ParametersAndQualifiers
3960   |   |-'(' OpenParen
3961   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3962   |   | |-'int'
3963   |   | `-SimpleDeclarator SimpleDeclaration_declarator
3964   |   |   `-'a'
3965   |   |-','
3966   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3967   |   | |-'float'
3968   |   | `-SimpleDeclarator SimpleDeclaration_declarator
3969   |   |   `-'b'
3970   |   `-')' CloseParen
3971   `-';'
3972 )txt"));
3973 }
3974 
3975 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
3976   EXPECT_TRUE(treeDumpEqual(
3977       R"cpp(
3978 int func1(int);
3979 int func2(int *);
3980 int func3(int, float);
3981 )cpp",
3982       R"txt(
3983 TranslationUnit Detached
3984 |-SimpleDeclaration
3985 | |-'int'
3986 | |-SimpleDeclarator SimpleDeclaration_declarator
3987 | | |-'func1'
3988 | | `-ParametersAndQualifiers
3989 | |   |-'(' OpenParen
3990 | |   |-SimpleDeclaration ParametersAndQualifiers_parameter
3991 | |   | `-'int'
3992 | |   `-')' CloseParen
3993 | `-';'
3994 |-SimpleDeclaration
3995 | |-'int'
3996 | |-SimpleDeclarator SimpleDeclaration_declarator
3997 | | |-'func2'
3998 | | `-ParametersAndQualifiers
3999 | |   |-'(' OpenParen
4000 | |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4001 | |   | |-'int'
4002 | |   | `-SimpleDeclarator SimpleDeclaration_declarator
4003 | |   |   `-'*'
4004 | |   `-')' CloseParen
4005 | `-';'
4006 `-SimpleDeclaration
4007   |-'int'
4008   |-SimpleDeclarator SimpleDeclaration_declarator
4009   | |-'func3'
4010   | `-ParametersAndQualifiers
4011   |   |-'(' OpenParen
4012   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4013   |   | `-'int'
4014   |   |-','
4015   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4016   |   | `-'float'
4017   |   `-')' CloseParen
4018   `-';'
4019 )txt"));
4020 }
4021 
4022 TEST_P(SyntaxTreeTest,
4023        ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
4024   if (!GetParam().isCXX()) {
4025     return;
4026   }
4027   EXPECT_TRUE(treeDumpEqual(
4028       R"cpp(
4029 int func(const int a, volatile int b, const volatile int c);
4030 )cpp",
4031       R"txt(
4032 TranslationUnit Detached
4033 `-SimpleDeclaration
4034   |-'int'
4035   |-SimpleDeclarator SimpleDeclaration_declarator
4036   | |-'func'
4037   | `-ParametersAndQualifiers
4038   |   |-'(' OpenParen
4039   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4040   |   | |-'const'
4041   |   | |-'int'
4042   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4043   |   |   `-'a'
4044   |   |-','
4045   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4046   |   | |-'volatile'
4047   |   | |-'int'
4048   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4049   |   |   `-'b'
4050   |   |-','
4051   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4052   |   | |-'const'
4053   |   | |-'volatile'
4054   |   | |-'int'
4055   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4056   |   |   `-'c'
4057   |   `-')' CloseParen
4058   `-';'
4059 )txt"));
4060 }
4061 
4062 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
4063   if (!GetParam().isCXX()) {
4064     return;
4065   }
4066   EXPECT_TRUE(treeDumpEqual(
4067       R"cpp(
4068 int func(int& a);
4069 )cpp",
4070       R"txt(
4071 TranslationUnit Detached
4072 `-SimpleDeclaration
4073   |-'int'
4074   |-SimpleDeclarator SimpleDeclaration_declarator
4075   | |-'func'
4076   | `-ParametersAndQualifiers
4077   |   |-'(' OpenParen
4078   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4079   |   | |-'int'
4080   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4081   |   |   |-'&'
4082   |   |   `-'a'
4083   |   `-')' CloseParen
4084   `-';'
4085 )txt"));
4086 }
4087 
4088 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
4089   if (!GetParam().isCXX11OrLater()) {
4090     return;
4091   }
4092   EXPECT_TRUE(treeDumpEqual(
4093       R"cpp(
4094 int func(int&& a);
4095 )cpp",
4096       R"txt(
4097 TranslationUnit Detached
4098 `-SimpleDeclaration
4099   |-'int'
4100   |-SimpleDeclarator SimpleDeclaration_declarator
4101   | |-'func'
4102   | `-ParametersAndQualifiers
4103   |   |-'(' OpenParen
4104   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4105   |   | |-'int'
4106   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4107   |   |   |-'&&'
4108   |   |   `-'a'
4109   |   `-')' CloseParen
4110   `-';'
4111 )txt"));
4112 }
4113 
4114 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
4115   if (!GetParam().isCXX()) {
4116     return;
4117   }
4118   EXPECT_TRUE(treeDumpEqual(
4119       R"cpp(
4120 struct Test {
4121   int a();
4122 };
4123 )cpp",
4124       R"txt(
4125 TranslationUnit Detached
4126 `-SimpleDeclaration
4127   |-'struct'
4128   |-'Test'
4129   |-'{'
4130   |-SimpleDeclaration
4131   | |-'int'
4132   | |-SimpleDeclarator SimpleDeclaration_declarator
4133   | | |-'a'
4134   | | `-ParametersAndQualifiers
4135   | |   |-'(' OpenParen
4136   | |   `-')' CloseParen
4137   | `-';'
4138   |-'}'
4139   `-';'
4140 )txt"));
4141 }
4142 
4143 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
4144   if (!GetParam().isCXX()) {
4145     return;
4146   }
4147   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4148       R"cpp(
4149 struct Test {
4150   [[int b() const;]]
4151   [[int c() volatile;]]
4152   [[int d() const volatile;]]
4153 };
4154 )cpp",
4155       {R"txt(
4156 SimpleDeclaration
4157 |-'int'
4158 |-SimpleDeclarator SimpleDeclaration_declarator
4159 | |-'b'
4160 | `-ParametersAndQualifiers
4161 |   |-'(' OpenParen
4162 |   |-')' CloseParen
4163 |   `-'const'
4164 `-';'
4165 )txt",
4166        R"txt(
4167 SimpleDeclaration
4168 |-'int'
4169 |-SimpleDeclarator SimpleDeclaration_declarator
4170 | |-'c'
4171 | `-ParametersAndQualifiers
4172 |   |-'(' OpenParen
4173 |   |-')' CloseParen
4174 |   `-'volatile'
4175 `-';'
4176 )txt",
4177        R"txt(
4178 SimpleDeclaration
4179 |-'int'
4180 |-SimpleDeclarator SimpleDeclaration_declarator
4181 | |-'d'
4182 | `-ParametersAndQualifiers
4183 |   |-'(' OpenParen
4184 |   |-')' CloseParen
4185 |   |-'const'
4186 |   `-'volatile'
4187 `-';'
4188 )txt"}));
4189 }
4190 
4191 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
4192   if (!GetParam().isCXX11OrLater()) {
4193     return;
4194   }
4195   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4196       R"cpp(
4197 struct Test {
4198   [[int e() &;]]
4199 };
4200 )cpp",
4201       {R"txt(
4202 SimpleDeclaration
4203 |-'int'
4204 |-SimpleDeclarator SimpleDeclaration_declarator
4205 | |-'e'
4206 | `-ParametersAndQualifiers
4207 |   |-'(' OpenParen
4208 |   |-')' CloseParen
4209 |   `-'&'
4210 `-';'
4211 )txt"}));
4212 }
4213 
4214 TEST_P(SyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
4215   if (!GetParam().isCXX11OrLater()) {
4216     return;
4217   }
4218   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4219       R"cpp(
4220 struct Test {
4221   [[int f() &&;]]
4222 };
4223 )cpp",
4224       {R"txt(
4225 SimpleDeclaration
4226 |-'int'
4227 |-SimpleDeclarator SimpleDeclaration_declarator
4228 | |-'f'
4229 | `-ParametersAndQualifiers
4230 |   |-'(' OpenParen
4231 |   |-')' CloseParen
4232 |   `-'&&'
4233 `-';'
4234 )txt"}));
4235 }
4236 
4237 TEST_P(SyntaxTreeTest, TrailingReturn) {
4238   if (!GetParam().isCXX11OrLater()) {
4239     return;
4240   }
4241   EXPECT_TRUE(treeDumpEqual(
4242       R"cpp(
4243 auto foo() -> int;
4244 )cpp",
4245       R"txt(
4246 TranslationUnit Detached
4247 `-SimpleDeclaration
4248   |-'auto'
4249   |-SimpleDeclarator SimpleDeclaration_declarator
4250   | |-'foo'
4251   | `-ParametersAndQualifiers
4252   |   |-'(' OpenParen
4253   |   |-')' CloseParen
4254   |   `-TrailingReturnType ParametersAndQualifiers_trailingReturn
4255   |     |-'->' ArrowToken
4256   |     `-'int'
4257   `-';'
4258 )txt"));
4259 }
4260 
4261 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
4262   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
4263     return;
4264   }
4265   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4266       R"cpp(
4267 struct MyException1 {};
4268 struct MyException2 {};
4269 [[int a() throw();]]
4270 [[int b() throw(...);]]
4271 [[int c() throw(MyException1);]]
4272 [[int d() throw(MyException1, MyException2);]]
4273 )cpp",
4274       {R"txt(
4275 SimpleDeclaration
4276 |-'int'
4277 |-SimpleDeclarator SimpleDeclaration_declarator
4278 | |-'a'
4279 | `-ParametersAndQualifiers
4280 |   |-'(' OpenParen
4281 |   |-')' CloseParen
4282 |   |-'throw'
4283 |   |-'('
4284 |   `-')'
4285 `-';'
4286 )txt",
4287        R"txt(
4288 SimpleDeclaration
4289 |-'int'
4290 |-SimpleDeclarator SimpleDeclaration_declarator
4291 | |-'b'
4292 | `-ParametersAndQualifiers
4293 |   |-'(' OpenParen
4294 |   |-')' CloseParen
4295 |   |-'throw'
4296 |   |-'('
4297 |   |-'...'
4298 |   `-')'
4299 `-';'
4300 )txt",
4301        R"txt(
4302 SimpleDeclaration
4303 |-'int'
4304 |-SimpleDeclarator SimpleDeclaration_declarator
4305 | |-'c'
4306 | `-ParametersAndQualifiers
4307 |   |-'(' OpenParen
4308 |   |-')' CloseParen
4309 |   |-'throw'
4310 |   |-'('
4311 |   |-'MyException1'
4312 |   `-')'
4313 `-';'
4314 )txt",
4315        R"txt(
4316 SimpleDeclaration
4317 |-'int'
4318 |-SimpleDeclarator SimpleDeclaration_declarator
4319 | |-'d'
4320 | `-ParametersAndQualifiers
4321 |   |-'(' OpenParen
4322 |   |-')' CloseParen
4323 |   |-'throw'
4324 |   |-'('
4325 |   |-'MyException1'
4326 |   |-','
4327 |   |-'MyException2'
4328 |   `-')'
4329 `-';'
4330 )txt"}));
4331 }
4332 
4333 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
4334   if (!GetParam().isCXX11OrLater()) {
4335     return;
4336   }
4337   EXPECT_TRUE(treeDumpEqual(
4338       R"cpp(
4339 int a() noexcept;
4340 int b() noexcept(true);
4341 )cpp",
4342       R"txt(
4343 TranslationUnit Detached
4344 |-SimpleDeclaration
4345 | |-'int'
4346 | |-SimpleDeclarator SimpleDeclaration_declarator
4347 | | |-'a'
4348 | | `-ParametersAndQualifiers
4349 | |   |-'(' OpenParen
4350 | |   |-')' CloseParen
4351 | |   `-'noexcept'
4352 | `-';'
4353 `-SimpleDeclaration
4354   |-'int'
4355   |-SimpleDeclarator SimpleDeclaration_declarator
4356   | |-'b'
4357   | `-ParametersAndQualifiers
4358   |   |-'(' OpenParen
4359   |   |-')' CloseParen
4360   |   |-'noexcept'
4361   |   |-'('
4362   |   |-BoolLiteralExpression
4363   |   | `-'true' LiteralToken
4364   |   `-')'
4365   `-';'
4366 )txt"));
4367 }
4368 
4369 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
4370   EXPECT_TRUE(treeDumpEqual(
4371       R"cpp(
4372 int (a);
4373 int *(b);
4374 int (*c)(int);
4375 int *(d)(int);
4376 )cpp",
4377       R"txt(
4378 TranslationUnit Detached
4379 |-SimpleDeclaration
4380 | |-'int'
4381 | |-SimpleDeclarator SimpleDeclaration_declarator
4382 | | `-ParenDeclarator
4383 | |   |-'(' OpenParen
4384 | |   |-'a'
4385 | |   `-')' CloseParen
4386 | `-';'
4387 |-SimpleDeclaration
4388 | |-'int'
4389 | |-SimpleDeclarator SimpleDeclaration_declarator
4390 | | |-'*'
4391 | | `-ParenDeclarator
4392 | |   |-'(' OpenParen
4393 | |   |-'b'
4394 | |   `-')' CloseParen
4395 | `-';'
4396 |-SimpleDeclaration
4397 | |-'int'
4398 | |-SimpleDeclarator SimpleDeclaration_declarator
4399 | | |-ParenDeclarator
4400 | | | |-'(' OpenParen
4401 | | | |-'*'
4402 | | | |-'c'
4403 | | | `-')' CloseParen
4404 | | `-ParametersAndQualifiers
4405 | |   |-'(' OpenParen
4406 | |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4407 | |   | `-'int'
4408 | |   `-')' CloseParen
4409 | `-';'
4410 `-SimpleDeclaration
4411   |-'int'
4412   |-SimpleDeclarator SimpleDeclaration_declarator
4413   | |-'*'
4414   | |-ParenDeclarator
4415   | | |-'(' OpenParen
4416   | | |-'d'
4417   | | `-')' CloseParen
4418   | `-ParametersAndQualifiers
4419   |   |-'(' OpenParen
4420   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4421   |   | `-'int'
4422   |   `-')' CloseParen
4423   `-';'
4424 )txt"));
4425 }
4426 
4427 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
4428   EXPECT_TRUE(treeDumpEqual(
4429       R"cpp(
4430 const int west = -1;
4431 int const east = 1;
4432 )cpp",
4433       R"txt(
4434 TranslationUnit Detached
4435 |-SimpleDeclaration
4436 | |-'const'
4437 | |-'int'
4438 | |-SimpleDeclarator SimpleDeclaration_declarator
4439 | | |-'west'
4440 | | |-'='
4441 | | `-PrefixUnaryOperatorExpression
4442 | |   |-'-' OperatorExpression_operatorToken
4443 | |   `-IntegerLiteralExpression UnaryOperatorExpression_operand
4444 | |     `-'1' LiteralToken
4445 | `-';'
4446 `-SimpleDeclaration
4447   |-'int'
4448   |-'const'
4449   |-SimpleDeclarator SimpleDeclaration_declarator
4450   | |-'east'
4451   | |-'='
4452   | `-IntegerLiteralExpression
4453   |   `-'1' LiteralToken
4454   `-';'
4455 )txt"));
4456 }
4457 
4458 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
4459   EXPECT_TRUE(treeDumpEqual(
4460       R"cpp(
4461 const int const universal = 0;
4462 )cpp",
4463       R"txt(
4464 TranslationUnit Detached
4465 `-SimpleDeclaration
4466   |-'const'
4467   |-'int'
4468   |-'const'
4469   |-SimpleDeclarator SimpleDeclaration_declarator
4470   | |-'universal'
4471   | |-'='
4472   | `-IntegerLiteralExpression
4473   |   `-'0' LiteralToken
4474   `-';'
4475 )txt"));
4476 }
4477 
4478 TEST_P(SyntaxTreeTest, Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
4479   EXPECT_TRUE(treeDumpEqual(
4480       R"cpp(
4481 const int const *const *volatile b;
4482 )cpp",
4483       R"txt(
4484 TranslationUnit Detached
4485 `-SimpleDeclaration
4486   |-'const'
4487   |-'int'
4488   |-'const'
4489   |-SimpleDeclarator SimpleDeclaration_declarator
4490   | |-'*'
4491   | |-'const'
4492   | |-'*'
4493   | |-'volatile'
4494   | `-'b'
4495   `-';'
4496 )txt"));
4497 }
4498 
4499 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
4500   if (!GetParam().isCXX11OrLater()) {
4501     return;
4502   }
4503   EXPECT_TRUE(treeDumpEqual(
4504       R"cpp(
4505 auto foo() -> auto(*)(int) -> double*;
4506 )cpp",
4507       R"txt(
4508 TranslationUnit Detached
4509 `-SimpleDeclaration
4510   |-'auto'
4511   |-SimpleDeclarator SimpleDeclaration_declarator
4512   | |-'foo'
4513   | `-ParametersAndQualifiers
4514   |   |-'(' OpenParen
4515   |   |-')' CloseParen
4516   |   `-TrailingReturnType ParametersAndQualifiers_trailingReturn
4517   |     |-'->' ArrowToken
4518   |     |-'auto'
4519   |     `-SimpleDeclarator TrailingReturnType_declarator
4520   |       |-ParenDeclarator
4521   |       | |-'(' OpenParen
4522   |       | |-'*'
4523   |       | `-')' CloseParen
4524   |       `-ParametersAndQualifiers
4525   |         |-'(' OpenParen
4526   |         |-SimpleDeclaration ParametersAndQualifiers_parameter
4527   |         | `-'int'
4528   |         |-')' CloseParen
4529   |         `-TrailingReturnType ParametersAndQualifiers_trailingReturn
4530   |           |-'->' ArrowToken
4531   |           |-'double'
4532   |           `-SimpleDeclarator TrailingReturnType_declarator
4533   |             `-'*'
4534   `-';'
4535 )txt"));
4536 }
4537 
4538 TEST_P(SyntaxTreeTest, MemberPointers) {
4539   if (!GetParam().isCXX()) {
4540     return;
4541   }
4542   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4543       R"cpp(
4544 struct X {};
4545 [[int X::* a;]]
4546 [[const int X::* b;]]
4547 )cpp",
4548       {R"txt(
4549 SimpleDeclaration
4550 |-'int'
4551 |-SimpleDeclarator SimpleDeclaration_declarator
4552 | |-MemberPointer
4553 | | |-'X'
4554 | | |-'::'
4555 | | `-'*'
4556 | `-'a'
4557 `-';'
4558 )txt",
4559        R"txt(
4560 SimpleDeclaration
4561 |-'const'
4562 |-'int'
4563 |-SimpleDeclarator SimpleDeclaration_declarator
4564 | |-MemberPointer
4565 | | |-'X'
4566 | | |-'::'
4567 | | `-'*'
4568 | `-'b'
4569 `-';'
4570 )txt"}));
4571 }
4572 
4573 TEST_P(SyntaxTreeTest, MemberFunctionPointer) {
4574   if (!GetParam().isCXX()) {
4575     return;
4576   }
4577   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4578       R"cpp(
4579 struct X {
4580   struct Y {};
4581 };
4582 [[void (X::*xp)();]]
4583 [[void (X::**xpp)(const int*);]]
4584 // FIXME: Generate the right syntax tree for this type,
4585 // i.e. create a syntax node for the outer member pointer
4586 [[void (X::Y::*xyp)(const int*, char);]]
4587 )cpp",
4588       {R"txt(
4589 SimpleDeclaration
4590 |-'void'
4591 |-SimpleDeclarator SimpleDeclaration_declarator
4592 | |-ParenDeclarator
4593 | | |-'(' OpenParen
4594 | | |-MemberPointer
4595 | | | |-'X'
4596 | | | |-'::'
4597 | | | `-'*'
4598 | | |-'xp'
4599 | | `-')' CloseParen
4600 | `-ParametersAndQualifiers
4601 |   |-'(' OpenParen
4602 |   `-')' CloseParen
4603 `-';'
4604 )txt",
4605        R"txt(
4606 SimpleDeclaration
4607 |-'void'
4608 |-SimpleDeclarator SimpleDeclaration_declarator
4609 | |-ParenDeclarator
4610 | | |-'(' OpenParen
4611 | | |-MemberPointer
4612 | | | |-'X'
4613 | | | |-'::'
4614 | | | `-'*'
4615 | | |-'*'
4616 | | |-'xpp'
4617 | | `-')' CloseParen
4618 | `-ParametersAndQualifiers
4619 |   |-'(' OpenParen
4620 |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4621 |   | |-'const'
4622 |   | |-'int'
4623 |   | `-SimpleDeclarator SimpleDeclaration_declarator
4624 |   |   `-'*'
4625 |   `-')' CloseParen
4626 `-';'
4627 )txt",
4628        R"txt(
4629 SimpleDeclaration
4630 |-'void'
4631 |-SimpleDeclarator SimpleDeclaration_declarator
4632 | |-ParenDeclarator
4633 | | |-'(' OpenParen
4634 | | |-'X'
4635 | | |-'::'
4636 | | |-MemberPointer
4637 | | | |-'Y'
4638 | | | |-'::'
4639 | | | `-'*'
4640 | | |-'xyp'
4641 | | `-')' CloseParen
4642 | `-ParametersAndQualifiers
4643 |   |-'(' OpenParen
4644 |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4645 |   | |-'const'
4646 |   | |-'int'
4647 |   | `-SimpleDeclarator SimpleDeclaration_declarator
4648 |   |   `-'*'
4649 |   |-','
4650 |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4651 |   | `-'char'
4652 |   `-')' CloseParen
4653 `-';'
4654 )txt"}));
4655 }
4656 
4657 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
4658   EXPECT_TRUE(treeDumpEqual(
4659       R"cpp(
4660 void x(char a, short (*b)(int));
4661 )cpp",
4662       R"txt(
4663 TranslationUnit Detached
4664 `-SimpleDeclaration
4665   |-'void'
4666   |-SimpleDeclarator SimpleDeclaration_declarator
4667   | |-'x'
4668   | `-ParametersAndQualifiers
4669   |   |-'(' OpenParen
4670   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4671   |   | |-'char'
4672   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4673   |   |   `-'a'
4674   |   |-','
4675   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4676   |   | |-'short'
4677   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4678   |   |   |-ParenDeclarator
4679   |   |   | |-'(' OpenParen
4680   |   |   | |-'*'
4681   |   |   | |-'b'
4682   |   |   | `-')' CloseParen
4683   |   |   `-ParametersAndQualifiers
4684   |   |     |-'(' OpenParen
4685   |   |     |-SimpleDeclaration ParametersAndQualifiers_parameter
4686   |   |     | `-'int'
4687   |   |     `-')' CloseParen
4688   |   `-')' CloseParen
4689   `-';'
4690 )txt"));
4691 }
4692 
4693 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
4694   EXPECT_TRUE(treeDumpEqual(
4695       R"cpp(
4696 void x(char a, short (*b)(int), long (**c)(long long));
4697 )cpp",
4698       R"txt(
4699 TranslationUnit Detached
4700 `-SimpleDeclaration
4701   |-'void'
4702   |-SimpleDeclarator SimpleDeclaration_declarator
4703   | |-'x'
4704   | `-ParametersAndQualifiers
4705   |   |-'(' OpenParen
4706   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4707   |   | |-'char'
4708   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4709   |   |   `-'a'
4710   |   |-','
4711   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4712   |   | |-'short'
4713   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4714   |   |   |-ParenDeclarator
4715   |   |   | |-'(' OpenParen
4716   |   |   | |-'*'
4717   |   |   | |-'b'
4718   |   |   | `-')' CloseParen
4719   |   |   `-ParametersAndQualifiers
4720   |   |     |-'(' OpenParen
4721   |   |     |-SimpleDeclaration ParametersAndQualifiers_parameter
4722   |   |     | `-'int'
4723   |   |     `-')' CloseParen
4724   |   |-','
4725   |   |-SimpleDeclaration ParametersAndQualifiers_parameter
4726   |   | |-'long'
4727   |   | `-SimpleDeclarator SimpleDeclaration_declarator
4728   |   |   |-ParenDeclarator
4729   |   |   | |-'(' OpenParen
4730   |   |   | |-'*'
4731   |   |   | |-'*'
4732   |   |   | |-'c'
4733   |   |   | `-')' CloseParen
4734   |   |   `-ParametersAndQualifiers
4735   |   |     |-'(' OpenParen
4736   |   |     |-SimpleDeclaration ParametersAndQualifiers_parameter
4737   |   |     | |-'long'
4738   |   |     | `-'long'
4739   |   |     `-')' CloseParen
4740   |   `-')' CloseParen
4741   `-';'
4742 )txt"));
4743 }
4744 
4745 } // namespace
4746