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