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