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(treeDumpEqualOnAnnotations(
106       R"cpp(
107 void test() {
108   [[if (1) {}]]
109   [[if (1) {} else if (0) {}]]
110 }
111 )cpp",
112       {R"txt(
113 IfStatement
114 |-if
115 |-(
116 |-IntegerLiteralExpression
117 | `-1
118 |-)
119 `-CompoundStatement
120   |-{
121   `-}
122   )txt",
123        R"txt(
124 IfStatement
125 |-if
126 |-(
127 |-IntegerLiteralExpression
128 | `-1
129 |-)
130 |-CompoundStatement
131 | |-{
132 | `-}
133 |-else
134 `-IfStatement
135   |-if
136   |-(
137   |-IntegerLiteralExpression
138   | `-0
139   |-)
140   `-CompoundStatement
141     |-{
142     `-}
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
155 |-for
156 |-(
157 |-;
158 |-;
159 |-)
160 `-CompoundStatement
161   |-{
162   `-}
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
180 |-for
181 |-(
182 |-SimpleDeclaration
183 | |-int
184 | |-SimpleDeclarator
185 | | `-x
186 | `-:
187 |-IdExpression
188 | `-UnqualifiedId
189 |   `-a
190 |-)
191 `-EmptyStatement
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
205 |-SimpleDeclaration
206 | |-int
207 | `-SimpleDeclarator
208 |   |-a
209 |   |-=
210 |   `-IntegerLiteralExpression
211 |     `-10
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
228 |-switch
229 |-(
230 |-IntegerLiteralExpression
231 | `-1
232 |-)
233 `-CompoundStatement
234   |-{
235   |-CaseStatement
236   | |-case
237   | |-IntegerLiteralExpression
238   | | `-0
239   | |-:
240   | `-DefaultStatement
241   |   |-default
242   |   |-:
243   |   `-EmptyStatement
244   |     `-;
245   `-}
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
258 |-while
259 |-(
260 |-IntegerLiteralExpression
261 | `-1
262 |-)
263 `-CompoundStatement
264   |-{
265   |-ContinueStatement
266   | |-continue
267   | `-;
268   |-BreakStatement
269   | |-break
270   | `-;
271   `-}
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
287 |-foo
288 |-:
289 `-ReturnStatement
290   |-return
291   |-IntegerLiteralExpression
292   | `-100
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
309 `-SimpleDeclaration
310   |-void
311   |-SimpleDeclarator
312   | |-test
313   | `-ParametersAndQualifiers
314   |   |-(
315   |   `-)
316   `-CompoundStatement
317     |-{
318     |-ExpressionStatement
319     | |-UnknownExpression
320     | | |-IdExpression
321     | | | `-UnqualifiedId
322     | | |   `-test
323     | | |-(
324     | | `-)
325     | `-;
326     |-IfStatement
327     | |-if
328     | |-(
329     | |-IntegerLiteralExpression
330     | | `-1
331     | |-)
332     | |-ExpressionStatement
333     | | |-UnknownExpression
334     | | | |-IdExpression
335     | | | | `-UnqualifiedId
336     | | | |   `-test
337     | | | |-(
338     | | | `-)
339     | | `-;
340     | |-else
341     | `-ExpressionStatement
342     |   |-UnknownExpression
343     |   | |-IdExpression
344     |   | | `-UnqualifiedId
345     |   | |   `-test
346     |   | |-(
347     |   | `-)
348     |   `-;
349     `-}
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
362 `-UnqualifiedId
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
382 |-IdExpression
383 | `-UnqualifiedId
384 |   |-operator
385 |   `-+
386 |-(
387 |-IdExpression
388 | `-UnqualifiedId
389 |   `-x
390 |-,
391 |-IdExpression
392 | `-UnqualifiedId
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
413 |-MemberExpression
414 | |-IdExpression
415 | | `-UnqualifiedId
416 | |   `-x
417 | |-.
418 | `-IdExpression
419 |   `-UnqualifiedId
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
440 |-IdExpression
441 | `-UnqualifiedId
442 |   |-operator
443 |   |-""
444 |   `-_w
445 |-(
446 |-CharacterLiteralExpression
447 | `-'1'
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
465 |-MemberExpression
466 | |-IdExpression
467 | | `-UnqualifiedId
468 | |   `-x
469 | |-.
470 | `-IdExpression
471 |   `-UnqualifiedId
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
496 |-MemberExpression
497 | |-IdExpression
498 | | `-UnqualifiedId
499 | |   `-x
500 | |-.
501 | `-IdExpression
502 |   `-UnqualifiedId
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
527 |-IdExpression
528 | `-UnqualifiedId
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 | |-::
559 | |-IdentifierNameSpecifier
560 | | `-n
561 | `-::
562 |-S
563 `-SimpleDeclarator
564   `-UnknownExpression
565     `-s1
566 )txt",
567        R"txt(
568 SimpleDeclaration
569 |-NestedNameSpecifier
570 | |-IdentifierNameSpecifier
571 | | `-n
572 | `-::
573 |-S
574 `-SimpleDeclarator
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 | |-::
599 | |-SimpleTemplateNameSpecifier
600 | | |-template
601 | | |-ST
602 | | |-<
603 | | |-int
604 | | `->
605 | `-::
606 |-S
607 `-SimpleDeclarator
608   `-UnknownExpression
609     `-s1
610 )txt",
611        R"txt(
612 SimpleDeclaration
613 |-NestedNameSpecifier
614 | |-::
615 | |-SimpleTemplateNameSpecifier
616 | | |-ST
617 | | |-<
618 | | |-int
619 | | `->
620 | `-::
621 |-S
622 `-SimpleDeclarator
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
643 |-IdExpression
644 | |-NestedNameSpecifier
645 | | |-DecltypeNameSpecifier
646 | | | |-decltype
647 | | | |-(
648 | | | |-IdExpression
649 | | | | `-UnqualifiedId
650 | | | |   `-s
651 | | | `-)
652 | | `-::
653 | `-UnqualifiedId
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
677 |-IdExpression
678 | |-NestedNameSpecifier
679 | | |-IdentifierNameSpecifier
680 | | | `-S
681 | | `-::
682 | `-UnqualifiedId
683 |   |-f
684 |   |-<
685 |   |-int
686 |   `->
687 |-(
688 `-)
689 )txt",
690        R"txt(
691 UnknownExpression
692 |-IdExpression
693 | |-NestedNameSpecifier
694 | | |-IdentifierNameSpecifier
695 | | | `-S
696 | | `-::
697 | |-template
698 | `-UnqualifiedId
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
727 |-IdExpression
728 | |-NestedNameSpecifier
729 | | |-::
730 | | |-IdentifierNameSpecifier
731 | | | `-n
732 | | |-::
733 | | |-SimpleTemplateNameSpecifier
734 | | | |-template
735 | | | |-ST
736 | | | |-<
737 | | | |-int
738 | | | `->
739 | | `-::
740 | |-template
741 | `-UnqualifiedId
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
771 |-IdExpression
772 | |-NestedNameSpecifier
773 | | |-IdentifierNameSpecifier
774 | | | `-T
775 | | |-::
776 | | |-SimpleTemplateNameSpecifier
777 | | | |-template
778 | | | |-U
779 | | | |-<
780 | | | |-int
781 | | | `->
782 | | `-::
783 | `-UnqualifiedId
784 |   `-f
785 |-(
786 `-)
787 )txt",
788        R"txt(
789 UnknownExpression
790 |-IdExpression
791 | |-NestedNameSpecifier
792 | | |-IdentifierNameSpecifier
793 | | | `-T
794 | | |-::
795 | | |-IdentifierNameSpecifier
796 | | | `-U
797 | | `-::
798 | `-UnqualifiedId
799 |   `-f
800 |-(
801 `-)
802 )txt",
803        R"txt(
804 UnknownExpression
805 |-IdExpression
806 | |-NestedNameSpecifier
807 | | |-IdentifierNameSpecifier
808 | | | `-T
809 | | `-::
810 | |-template
811 | `-UnqualifiedId
812 |   |-f
813 |   |-<
814 |   |-IntegerLiteralExpression
815 |   | `-0
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
836 `-this
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
855 |-ThisExpression
856 | `-this
857 |-->
858 `-IdExpression
859   `-UnqualifiedId
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
879 `-UnqualifiedId
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
895 |-(
896 |-IntegerLiteralExpression
897 | `-1
898 `-)
899 )txt",
900        R"txt(
901 ParenExpression
902 |-(
903 |-ParenExpression
904 | |-(
905 | |-IntegerLiteralExpression
906 | | `-1
907 | `-)
908 `-)
909 )txt",
910        R"txt(
911 ParenExpression
912 |-(
913 |-BinaryOperatorExpression
914 | |-IntegerLiteralExpression
915 | | `-1
916 | |-+
917 | `-ParenExpression
918 |   |-(
919 |   |-IntegerLiteralExpression
920 |   | `-2
921 |   `-)
922 `-)
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
939 `-'2'_c
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
959 `-"12"_s
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
982 `-12_i
983 )txt",
984        R"txt(
985 IntegerUserDefinedLiteralExpression
986 `-12_r
987 )txt",
988        R"txt(
989 IntegerUserDefinedLiteralExpression
990 `-12_t
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
1013 `-1.2_f
1014 )txt",
1015        R"txt(
1016 FloatUserDefinedLiteralExpression
1017 `-1.2_r
1018 )txt",
1019        R"txt(
1020 FloatUserDefinedLiteralExpression
1021 `-1.2_t
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
1038 `-12ll
1039 )txt",
1040        R"txt(
1041 IntegerLiteralExpression
1042 `-12ull
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
1058 `-0b1100
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
1074 `-1'2'0ull
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
1092 `-'a'
1093 )txt",
1094        R"txt(
1095 CharacterLiteralExpression
1096 `-'\n'
1097 )txt",
1098        R"txt(
1099 CharacterLiteralExpression
1100 `-'\x20'
1101 )txt",
1102        R"txt(
1103 CharacterLiteralExpression
1104 `-'\0'
1105 )txt",
1106        R"txt(
1107 CharacterLiteralExpression
1108 `-L'a'
1109 )txt",
1110        R"txt(
1111 CharacterLiteralExpression
1112 `-L'α'
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
1131 `-u'a'
1132 )txt",
1133        R"txt(
1134 CharacterLiteralExpression
1135 `-u'構'
1136 )txt",
1137        R"txt(
1138 CharacterLiteralExpression
1139 `-U'a'
1140 )txt",
1141        R"txt(
1142 CharacterLiteralExpression
1143 `-U'��'
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
1160 `-u8'a'
1161 )txt",
1162        R"txt(
1163 CharacterLiteralExpression
1164 `-u8'\x7f'
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
1180 `-1e-2
1181 )txt",
1182        R"txt(
1183 FloatingLiteralExpression
1184 `-2.
1185 )txt",
1186        R"txt(
1187 FloatingLiteralExpression
1188 `-.2
1189 )txt",
1190        R"txt(
1191 FloatingLiteralExpression
1192 `-2.f
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
1211 `-0xfp1
1212 )txt",
1213        R"txt(
1214 FloatingLiteralExpression
1215 `-0xf.p1
1216 )txt",
1217        R"txt(
1218 FloatingLiteralExpression
1219 `-0x.fp1
1220 )txt",
1221        R"txt(
1222 FloatingLiteralExpression
1223 `-0xf.fp1f
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
1237 `-"a\n\0\x20"
1238 )txt",
1239        R"txt(
1240 StringLiteralExpression
1241 `-L"αβ"
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
1259 `-u8"a\x1f\x05"
1260 )txt",
1261        R"txt(
1262 StringLiteralExpression
1263 `-u"C++抽象構文木"
1264 )txt",
1265        R"txt(
1266 StringLiteralExpression
1267 `-U"����\n"
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\n"
1286       "`-SimpleDeclaration\n"
1287       "  |-void\n"
1288       "  |-SimpleDeclarator\n"
1289       "  | |-test\n"
1290       "  | `-ParametersAndQualifiers\n"
1291       "  |   |-(\n"
1292       "  |   `-)\n"
1293       "  `-CompoundStatement\n"
1294       "    |-{\n"
1295       "    |-ExpressionStatement\n"
1296       "    | |-StringLiteralExpression\n"
1297       "    | | `-R\"SyntaxTree(\n"
1298       "  Hello \"Syntax\" \\\"\n"
1299       "  )SyntaxTree\"\n"
1300       "    | `-;\n"
1301       "    `-}\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
1317 `-true
1318 )txt",
1319        R"txt(
1320 BoolLiteralExpression
1321 `-false
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
1337 `-nullptr
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
1351 |-IdExpression
1352 | `-UnqualifiedId
1353 |   `-a
1354 `-++
1355 )txt",
1356        R"txt(
1357 PostfixUnaryOperatorExpression
1358 |-IdExpression
1359 | `-UnqualifiedId
1360 |   `-a
1361 `---
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
1381 |---
1382 `-IdExpression
1383   `-UnqualifiedId
1384     `-a
1385 )txt",
1386        R"txt(
1387 PrefixUnaryOperatorExpression
1388 |-++
1389 `-IdExpression
1390   `-UnqualifiedId
1391     `-a
1392 )txt",
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     `-ap
1427 )txt",
1428        R"txt(
1429 PrefixUnaryOperatorExpression
1430 |-!
1431 `-IdExpression
1432   `-UnqualifiedId
1433     `-a
1434 )txt",
1435        R"txt(
1436 PrefixUnaryOperatorExpression
1437 |-__real
1438 `-IdExpression
1439   `-UnqualifiedId
1440     `-a
1441 )txt",
1442        R"txt(
1443 PrefixUnaryOperatorExpression
1444 |-__imag
1445 `-IdExpression
1446   `-UnqualifiedId
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
1464 |-compl
1465 `-IdExpression
1466   `-UnqualifiedId
1467     `-a
1468 )txt",
1469        R"txt(
1470 PrefixUnaryOperatorExpression
1471 |-not
1472 `-IdExpression
1473   `-UnqualifiedId
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
1493 |-IntegerLiteralExpression
1494 | `-1
1495 |--
1496 `-IntegerLiteralExpression
1497   `-2
1498 )txt",
1499        R"txt(
1500 BinaryOperatorExpression
1501 |-IntegerLiteralExpression
1502 | `-1
1503 |-==
1504 `-IntegerLiteralExpression
1505   `-2
1506 )txt",
1507        R"txt(
1508 BinaryOperatorExpression
1509 |-IdExpression
1510 | `-UnqualifiedId
1511 |   `-a
1512 |-=
1513 `-IntegerLiteralExpression
1514   `-1
1515 )txt",
1516        R"txt(
1517 BinaryOperatorExpression
1518 |-IdExpression
1519 | `-UnqualifiedId
1520 |   `-a
1521 |-<<=
1522 `-IntegerLiteralExpression
1523   `-1
1524 )txt",
1525        R"txt(
1526 BinaryOperatorExpression
1527 |-IntegerLiteralExpression
1528 | `-1
1529 |-||
1530 `-IntegerLiteralExpression
1531   `-0
1532 )txt",
1533        R"txt(
1534 BinaryOperatorExpression
1535 |-IntegerLiteralExpression
1536 | `-1
1537 |-&
1538 `-IntegerLiteralExpression
1539   `-2
1540 )txt",
1541        R"txt(
1542 BinaryOperatorExpression
1543 |-IdExpression
1544 | `-UnqualifiedId
1545 |   `-a
1546 |-!=
1547 `-IntegerLiteralExpression
1548   `-3
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
1567 |-BoolLiteralExpression
1568 | `-true
1569 |-||
1570 `-BoolLiteralExpression
1571   `-false
1572 )txt",
1573        R"txt(
1574 BinaryOperatorExpression
1575 |-BoolLiteralExpression
1576 | `-true
1577 |-or
1578 `-BoolLiteralExpression
1579   `-false
1580 )txt",
1581        R"txt(
1582 BinaryOperatorExpression
1583 |-IntegerLiteralExpression
1584 | `-1
1585 |-bitand
1586 `-IntegerLiteralExpression
1587   `-2
1588 )txt",
1589        R"txt(
1590 BinaryOperatorExpression
1591 |-IdExpression
1592 | `-UnqualifiedId
1593 |   `-a
1594 |-xor_eq
1595 `-IntegerLiteralExpression
1596   `-3
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
1609 |-ParenExpression
1610 | |-(
1611 | |-BinaryOperatorExpression
1612 | | |-IntegerLiteralExpression
1613 | | | `-1
1614 | | |-+
1615 | | `-IntegerLiteralExpression
1616 | |   `-2
1617 | `-)
1618 |-*
1619 `-ParenExpression
1620   |-(
1621   |-BinaryOperatorExpression
1622   | |-IntegerLiteralExpression
1623   | | `-4
1624   | |-/
1625   | `-IntegerLiteralExpression
1626   |   `-2
1627   `-)
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
1641 |-BinaryOperatorExpression
1642 | |-IdExpression
1643 | | `-UnqualifiedId
1644 | |   `-a
1645 | |-+
1646 | `-IdExpression
1647 |   `-UnqualifiedId
1648 |     `-b
1649 |-+
1650 `-IntegerLiteralExpression
1651   `-42
1652 )txt",
1653        R"txt(
1654 BinaryOperatorExpression
1655 |-IdExpression
1656 | `-UnqualifiedId
1657 |   `-a
1658 |-=
1659 `-BinaryOperatorExpression
1660   |-IdExpression
1661   | `-UnqualifiedId
1662   |   `-b
1663   |-=
1664   `-IntegerLiteralExpression
1665     `-42
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
1679 |-BinaryOperatorExpression
1680 | |-IntegerLiteralExpression
1681 | | `-1
1682 | |-+
1683 | `-BinaryOperatorExpression
1684 |   |-IntegerLiteralExpression
1685 |   | `-2
1686 |   |-*
1687 |   `-IntegerLiteralExpression
1688 |     `-3
1689 |-+
1690 `-IntegerLiteralExpression
1691   `-4
1692 )txt",
1693        R"txt(
1694 BinaryOperatorExpression
1695 |-BinaryOperatorExpression
1696 | |-IntegerLiteralExpression
1697 | | `-1
1698 | |-%
1699 | `-IntegerLiteralExpression
1700 |   `-2
1701 |-+
1702 `-BinaryOperatorExpression
1703   |-IntegerLiteralExpression
1704   | `-3
1705   |-*
1706   `-IntegerLiteralExpression
1707     `-4
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
1726 |-IdExpression
1727 | `-UnqualifiedId
1728 |   `-x
1729 |-=
1730 `-IdExpression
1731   `-UnqualifiedId
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
1754 |-UnknownExpression
1755 | `-IdExpression
1756 |   `-UnqualifiedId
1757 |     `-x
1758 |-+
1759 `-IdExpression
1760   `-UnqualifiedId
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
1780 |-IdExpression
1781 | `-UnqualifiedId
1782 |   `-x
1783 |-<
1784 `-IdExpression
1785   `-UnqualifiedId
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
1805 |-IdExpression
1806 | `-UnqualifiedId
1807 |   `-x
1808 |-<<
1809 `-IdExpression
1810   `-UnqualifiedId
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
1830 |-IdExpression
1831 | `-UnqualifiedId
1832 |   `-x
1833 |-,
1834 `-IdExpression
1835   `-UnqualifiedId
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
1855 |-IdExpression
1856 | `-UnqualifiedId
1857 |   `-xp
1858 |-->*
1859 `-IdExpression
1860   `-UnqualifiedId
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
1880 |-!
1881 `-IdExpression
1882   `-UnqualifiedId
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
1902 |-&
1903 `-IdExpression
1904   `-UnqualifiedId
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
1924 |-++
1925 `-IdExpression
1926   `-UnqualifiedId
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
1946 |-IdExpression
1947 | `-UnqualifiedId
1948 |   `-x
1949 `-++
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
1965 |-IdExpression
1966 | `-UnqualifiedId
1967 |   `-s
1968 |-.
1969 `-IdExpression
1970   `-UnqualifiedId
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
1990 |-IdExpression
1991 | `-UnqualifiedId
1992 |   `-s
1993 |-.
1994 `-IdExpression
1995   `-UnqualifiedId
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
2012 |-IdExpression
2013 | `-UnqualifiedId
2014 |   `-sp
2015 |-->
2016 `-IdExpression
2017   `-UnqualifiedId
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
2034 |-MemberExpression
2035 | |-IdExpression
2036 | | `-UnqualifiedId
2037 | |   `-s
2038 | |-.
2039 | `-IdExpression
2040 |   `-UnqualifiedId
2041 |     `-next
2042 |-->
2043 `-IdExpression
2044   `-UnqualifiedId
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
2064 |-MemberExpression
2065 | |-IdExpression
2066 | | `-UnqualifiedId
2067 | |   `-s
2068 | |-.
2069 | `-IdExpression
2070 |   `-UnqualifiedId
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 |-{
2097 |-ExpressionStatement
2098 | `-MemberExpression
2099 |   |-IdExpression
2100 |   | `-UnqualifiedId
2101 |   |   `-s
2102 |   |-.
2103 |   `-IdExpression
2104 |     `-UnqualifiedId
2105 |       `-x
2106 |-<
2107 |-int
2108 |->
2109 |-;
2110 `-}
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
2130 |-MemberExpression
2131 | |-IdExpression
2132 | | `-UnqualifiedId
2133 | |   `-sp
2134 | |-->
2135 | `-IdExpression
2136 |   `-UnqualifiedId
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
2162 |-MemberExpression
2163 | |-IdExpression
2164 | | `-UnqualifiedId
2165 | |   `-s
2166 | |-.
2167 | |-template
2168 | `-IdExpression
2169 |   `-UnqualifiedId
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
2196 |-MemberExpression
2197 | |-IdExpression
2198 | | `-UnqualifiedId
2199 | |   `-s
2200 | |-.
2201 | `-IdExpression
2202 |   |-NestedNameSpecifier
2203 |   | |-IdentifierNameSpecifier
2204 |   | | `-Base
2205 |   | `-::
2206 |   `-UnqualifiedId
2207 |     `-f
2208 |-(
2209 `-)
2210       )txt",
2211        R"txt(
2212 UnknownExpression
2213 |-MemberExpression
2214 | |-IdExpression
2215 | | `-UnqualifiedId
2216 | |   `-s
2217 | |-.
2218 | `-IdExpression
2219 |   |-NestedNameSpecifier
2220 |   | |-::
2221 |   | |-IdentifierNameSpecifier
2222 |   | | `-S
2223 |   | `-::
2224 |   `-UnqualifiedId
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
2257 |-MemberExpression
2258 | |-UnknownExpression
2259 | | |-MemberExpression
2260 | | | |-IdExpression
2261 | | | | `-UnqualifiedId
2262 | | | |   `-sp
2263 | | | |-->
2264 | | | `-IdExpression
2265 | | |   `-UnqualifiedId
2266 | | |     `-getU
2267 | | |-(
2268 | | `-)
2269 | |-.
2270 | `-IdExpression
2271 |   |-NestedNameSpecifier
2272 |   | |-SimpleTemplateNameSpecifier
2273 |   | | |-template
2274 |   | | |-U
2275 |   | | |-<
2276 |   | | |-int
2277 |   | | `->
2278 |   | `-::
2279 |   |-template
2280 |   `-UnqualifiedId
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
2298 |-SimpleDeclaration
2299 | |-int
2300 | |-SimpleDeclarator
2301 | | |-*
2302 | | `-a
2303 | |-,
2304 | |-SimpleDeclarator
2305 | | `-b
2306 | `-;
2307 `-SimpleDeclaration
2308   |-int
2309   |-SimpleDeclarator
2310   | |-*
2311   | `-c
2312   |-,
2313   |-SimpleDeclarator
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
2326 `-SimpleDeclaration
2327   |-typedef
2328   |-int
2329   |-SimpleDeclarator
2330   | |-*
2331   | `-a
2332   |-,
2333   |-SimpleDeclarator
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
2349 `-SimpleDeclaration
2350   |-void
2351   |-SimpleDeclarator
2352   | |-foo
2353   | `-ParametersAndQualifiers
2354   |   |-(
2355   |   `-)
2356   `-CompoundStatement
2357     |-{
2358     |-DeclarationStatement
2359     | |-SimpleDeclaration
2360     | | |-int
2361     | | |-SimpleDeclarator
2362     | | | |-*
2363     | | | `-a
2364     | | |-,
2365     | | `-SimpleDeclarator
2366     | |   `-b
2367     | `-;
2368     |-DeclarationStatement
2369     | |-SimpleDeclaration
2370     | | |-typedef
2371     | | |-int
2372     | | |-SimpleDeclarator
2373     | | | |-*
2374     | | | `-ta
2375     | | |-,
2376     | | `-SimpleDeclarator
2377     | |   `-tb
2378     | `-;
2379     `-}
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
2393 `-SimpleDeclaration
2394   |-typedef
2395   |-decltype
2396   |-(
2397   |-UnknownExpression
2398   | |-sizeof
2399   | |-(
2400   | |-void
2401   | |-*
2402   | `-)
2403   |-)
2404   |-SimpleDeclarator
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
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
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 | `-::
2492 |-ns
2493 `-;
2494 )txt"}));
2495 }
2496 
2497 TEST_P(SyntaxTreeTest, UsingDeclaration) {
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
2511 | | `-ns
2512 | `-::
2513 |-a
2514 `-;
2515 )txt"}));
2516 }
2517 
2518 TEST_P(SyntaxTreeTest, FreeStandingClasses) {
2519   // Free-standing classes, must live inside a SimpleDeclaration.
2520   EXPECT_TRUE(treeDumpEqual(
2521       R"cpp(
2522 struct X;
2523 struct X {};
2524 
2525 struct Y *y1;
2526 struct Y {} *y2;
2527 
2528 struct {} *a1;
2529 )cpp",
2530       R"txt(
2531 *: TranslationUnit
2532 |-SimpleDeclaration
2533 | |-struct
2534 | |-X
2535 | `-;
2536 |-SimpleDeclaration
2537 | |-struct
2538 | |-X
2539 | |-{
2540 | |-}
2541 | `-;
2542 |-SimpleDeclaration
2543 | |-struct
2544 | |-Y
2545 | |-SimpleDeclarator
2546 | | |-*
2547 | | `-y1
2548 | `-;
2549 |-SimpleDeclaration
2550 | |-struct
2551 | |-Y
2552 | |-{
2553 | |-}
2554 | |-SimpleDeclarator
2555 | | |-*
2556 | | `-y2
2557 | `-;
2558 `-SimpleDeclaration
2559   |-struct
2560   |-{
2561   |-}
2562   |-SimpleDeclarator
2563   | |-*
2564   | `-a1
2565   `-;
2566 )txt"));
2567 }
2568 
2569 TEST_P(SyntaxTreeTest, StaticMemberFunction) {
2570   if (!GetParam().isCXX11OrLater()) {
2571     return;
2572   }
2573   EXPECT_TRUE(treeDumpEqual(
2574       R"cpp(
2575 struct S {
2576   static void f(){}
2577 };
2578 )cpp",
2579       R"txt(
2580 *: TranslationUnit
2581 `-SimpleDeclaration
2582   |-struct
2583   |-S
2584   |-{
2585   |-SimpleDeclaration
2586   | |-static
2587   | |-void
2588   | |-SimpleDeclarator
2589   | | |-f
2590   | | `-ParametersAndQualifiers
2591   | |   |-(
2592   | |   `-)
2593   | `-CompoundStatement
2594   |   |-{
2595   |   `-}
2596   |-}
2597   `-;
2598 )txt"));
2599 }
2600 
2601 TEST_P(SyntaxTreeTest, ConversionMemberFunction) {
2602   if (!GetParam().isCXX()) {
2603     return;
2604   }
2605   EXPECT_TRUE(treeDumpEqual(
2606       R"cpp(
2607 struct X {
2608   operator int();
2609 };
2610 )cpp",
2611       R"txt(
2612 *: TranslationUnit
2613 `-SimpleDeclaration
2614   |-struct
2615   |-X
2616   |-{
2617   |-SimpleDeclaration
2618   | |-SimpleDeclarator
2619   | | |-operator
2620   | | |-int
2621   | | `-ParametersAndQualifiers
2622   | |   |-(
2623   | |   `-)
2624   | `-;
2625   |-}
2626   `-;
2627 )txt"));
2628 }
2629 
2630 TEST_P(SyntaxTreeTest, LiteralOperatorDeclaration) {
2631   if (!GetParam().isCXX11OrLater()) {
2632     return;
2633   }
2634   EXPECT_TRUE(treeDumpEqual(
2635       R"cpp(
2636 unsigned operator "" _c(char);
2637     )cpp",
2638       R"txt(
2639 *: TranslationUnit
2640 `-SimpleDeclaration
2641   |-unsigned
2642   |-SimpleDeclarator
2643   | |-operator
2644   | |-""
2645   | |-_c
2646   | `-ParametersAndQualifiers
2647   |   |-(
2648   |   |-SimpleDeclaration
2649   |   | `-char
2650   |   `-)
2651   `-;
2652 )txt"));
2653 }
2654 
2655 TEST_P(SyntaxTreeTest, NumericLiteralOperatorTemplateDeclaration) {
2656   if (!GetParam().isCXX11OrLater()) {
2657     return;
2658   }
2659   EXPECT_TRUE(treeDumpEqual(
2660       R"cpp(
2661 template <char...>
2662 unsigned operator "" _t();
2663     )cpp",
2664       R"txt(
2665 *: TranslationUnit
2666 `-TemplateDeclaration
2667   |-template
2668   |-<
2669   |-SimpleDeclaration
2670   | `-char
2671   |-...
2672   |->
2673   `-SimpleDeclaration
2674     |-unsigned
2675     |-SimpleDeclarator
2676     | |-operator
2677     | |-""
2678     | |-_t
2679     | `-ParametersAndQualifiers
2680     |   |-(
2681     |   `-)
2682     `-;
2683 )txt"));
2684 }
2685 
2686 TEST_P(SyntaxTreeTest, OverloadedOperatorDeclaration) {
2687   if (!GetParam().isCXX()) {
2688     return;
2689   }
2690   EXPECT_TRUE(treeDumpEqual(
2691       R"cpp(
2692 struct X {
2693   X& operator=(const X&);
2694 };
2695 )cpp",
2696       R"txt(
2697 *: TranslationUnit
2698 `-SimpleDeclaration
2699   |-struct
2700   |-X
2701   |-{
2702   |-SimpleDeclaration
2703   | |-X
2704   | |-SimpleDeclarator
2705   | | |-&
2706   | | |-operator
2707   | | |-=
2708   | | `-ParametersAndQualifiers
2709   | |   |-(
2710   | |   |-SimpleDeclaration
2711   | |   | |-const
2712   | |   | |-X
2713   | |   | `-SimpleDeclarator
2714   | |   |   `-&
2715   | |   `-)
2716   | `-;
2717   |-}
2718   `-;
2719 )txt"));
2720 }
2721 
2722 TEST_P(SyntaxTreeTest, OverloadedOperatorFriendDeclarataion) {
2723   if (!GetParam().isCXX()) {
2724     return;
2725   }
2726   EXPECT_TRUE(treeDumpEqual(
2727       R"cpp(
2728 struct X {
2729   friend X operator+(X, const X&);
2730 };
2731 )cpp",
2732       R"txt(
2733 *: TranslationUnit
2734 `-SimpleDeclaration
2735   |-struct
2736   |-X
2737   |-{
2738   |-UnknownDeclaration
2739   | `-SimpleDeclaration
2740   |   |-friend
2741   |   |-X
2742   |   |-SimpleDeclarator
2743   |   | |-operator
2744   |   | |-+
2745   |   | `-ParametersAndQualifiers
2746   |   |   |-(
2747   |   |   |-SimpleDeclaration
2748   |   |   | `-X
2749   |   |   |-,
2750   |   |   |-SimpleDeclaration
2751   |   |   | |-const
2752   |   |   | |-X
2753   |   |   | `-SimpleDeclarator
2754   |   |   |   `-&
2755   |   |   `-)
2756   |   `-;
2757   |-}
2758   `-;
2759 )txt"));
2760 }
2761 
2762 TEST_P(SyntaxTreeTest, ClassTemplateDeclaration) {
2763   if (!GetParam().isCXX()) {
2764     return;
2765   }
2766   EXPECT_TRUE(treeDumpEqual(
2767       R"cpp(
2768 template<typename T>
2769 struct ST {};
2770 )cpp",
2771       R"txt(
2772 *: TranslationUnit
2773 `-TemplateDeclaration
2774   |-template
2775   |-<
2776   |-UnknownDeclaration
2777   | |-typename
2778   | `-T
2779   |->
2780   `-SimpleDeclaration
2781     |-struct
2782     |-ST
2783     |-{
2784     |-}
2785     `-;
2786 )txt"));
2787 }
2788 
2789 TEST_P(SyntaxTreeTest, FunctionTemplateDeclaration) {
2790   if (!GetParam().isCXX()) {
2791     return;
2792   }
2793   EXPECT_TRUE(treeDumpEqual(
2794       R"cpp(
2795 template<typename T>
2796 T f();
2797 )cpp",
2798       R"txt(
2799 *: TranslationUnit
2800 `-TemplateDeclaration
2801   |-template
2802   |-<
2803   |-UnknownDeclaration
2804   | |-typename
2805   | `-T
2806   |->
2807   `-SimpleDeclaration
2808     |-T
2809     |-SimpleDeclarator
2810     | |-f
2811     | `-ParametersAndQualifiers
2812     |   |-(
2813     |   `-)
2814     `-;
2815 )txt"));
2816 }
2817 
2818 TEST_P(SyntaxTreeTest, VariableTemplateDeclaration) {
2819   if (!GetParam().isCXX()) {
2820     return;
2821   }
2822   EXPECT_TRUE(treeDumpEqual(
2823       R"cpp(
2824 template <class T> T var = 10;
2825 )cpp",
2826       R"txt(
2827 *: TranslationUnit
2828 `-TemplateDeclaration
2829   |-template
2830   |-<
2831   |-UnknownDeclaration
2832   | |-class
2833   | `-T
2834   |->
2835   `-SimpleDeclaration
2836     |-T
2837     |-SimpleDeclarator
2838     | |-var
2839     | |-=
2840     | `-IntegerLiteralExpression
2841     |   `-10
2842     `-;
2843 )txt"));
2844 }
2845 
2846 TEST_P(SyntaxTreeTest, StaticMemberFunctionTemplate) {
2847   if (!GetParam().isCXX()) {
2848     return;
2849   }
2850   EXPECT_TRUE(treeDumpEqual(
2851       R"cpp(
2852 struct S {
2853   template<typename U>
2854   static U f();
2855 };
2856 )cpp",
2857       R"txt(
2858 *: TranslationUnit
2859 `-SimpleDeclaration
2860   |-struct
2861   |-S
2862   |-{
2863   |-TemplateDeclaration
2864   | |-template
2865   | |-<
2866   | |-UnknownDeclaration
2867   | | |-typename
2868   | | `-U
2869   | |->
2870   | `-SimpleDeclaration
2871   |   |-static
2872   |   |-U
2873   |   |-SimpleDeclarator
2874   |   | |-f
2875   |   | `-ParametersAndQualifiers
2876   |   |   |-(
2877   |   |   `-)
2878   |   `-;
2879   |-}
2880   `-;
2881 )txt"));
2882 }
2883 
2884 TEST_P(SyntaxTreeTest, NestedTemplates) {
2885   if (!GetParam().isCXX()) {
2886     return;
2887   }
2888   EXPECT_TRUE(treeDumpEqual(
2889       R"cpp(
2890 template <class T>
2891 struct X {
2892   template <class U>
2893   U foo();
2894 };
2895 )cpp",
2896       R"txt(
2897 *: TranslationUnit
2898 `-TemplateDeclaration
2899   |-template
2900   |-<
2901   |-UnknownDeclaration
2902   | |-class
2903   | `-T
2904   |->
2905   `-SimpleDeclaration
2906     |-struct
2907     |-X
2908     |-{
2909     |-TemplateDeclaration
2910     | |-template
2911     | |-<
2912     | |-UnknownDeclaration
2913     | | |-class
2914     | | `-U
2915     | |->
2916     | `-SimpleDeclaration
2917     |   |-U
2918     |   |-SimpleDeclarator
2919     |   | |-foo
2920     |   | `-ParametersAndQualifiers
2921     |   |   |-(
2922     |   |   `-)
2923     |   `-;
2924     |-}
2925     `-;
2926 )txt"));
2927 }
2928 
2929 TEST_P(SyntaxTreeTest, NestedTemplatesInNamespace) {
2930   if (!GetParam().isCXX()) {
2931     return;
2932   }
2933   EXPECT_TRUE(treeDumpEqual(
2934       R"cpp(
2935 namespace n {
2936   template<typename T>
2937   struct ST {
2938     template<typename U>
2939     static U f();
2940   };
2941 }
2942 )cpp",
2943       R"txt(
2944 *: TranslationUnit
2945 `-NamespaceDefinition
2946   |-namespace
2947   |-n
2948   |-{
2949   |-TemplateDeclaration
2950   | |-template
2951   | |-<
2952   | |-UnknownDeclaration
2953   | | |-typename
2954   | | `-T
2955   | |->
2956   | `-SimpleDeclaration
2957   |   |-struct
2958   |   |-ST
2959   |   |-{
2960   |   |-TemplateDeclaration
2961   |   | |-template
2962   |   | |-<
2963   |   | |-UnknownDeclaration
2964   |   | | |-typename
2965   |   | | `-U
2966   |   | |->
2967   |   | `-SimpleDeclaration
2968   |   |   |-static
2969   |   |   |-U
2970   |   |   |-SimpleDeclarator
2971   |   |   | |-f
2972   |   |   | `-ParametersAndQualifiers
2973   |   |   |   |-(
2974   |   |   |   `-)
2975   |   |   `-;
2976   |   |-}
2977   |   `-;
2978   `-}
2979 )txt"));
2980 }
2981 
2982 TEST_P(SyntaxTreeTest, Templates2) {
2983   if (!GetParam().isCXX()) {
2984     return;
2985   }
2986   EXPECT_TRUE(treeDumpEqual(
2987       R"cpp(
2988 template <class T> struct X { struct Y; };
2989 template <class T> struct X<T>::Y {};
2990 )cpp",
2991       R"txt(
2992 *: TranslationUnit
2993 |-TemplateDeclaration
2994 | |-template
2995 | |-<
2996 | |-UnknownDeclaration
2997 | | |-class
2998 | | `-T
2999 | |->
3000 | `-SimpleDeclaration
3001 |   |-struct
3002 |   |-X
3003 |   |-{
3004 |   |-SimpleDeclaration
3005 |   | |-struct
3006 |   | |-Y
3007 |   | `-;
3008 |   |-}
3009 |   `-;
3010 `-TemplateDeclaration
3011   |-template
3012   |-<
3013   |-UnknownDeclaration
3014   | |-class
3015   | `-T
3016   |->
3017   `-SimpleDeclaration
3018     |-struct
3019     |-NestedNameSpecifier
3020     | |-SimpleTemplateNameSpecifier
3021     | | |-X
3022     | | |-<
3023     | | |-T
3024     | | `->
3025     | `-::
3026     |-Y
3027     |-{
3028     |-}
3029     `-;
3030 )txt"));
3031 }
3032 
3033 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) {
3034   if (!GetParam().isCXX()) {
3035     return;
3036   }
3037   EXPECT_TRUE(treeDumpEqual(
3038       R"cpp(
3039 template <class T> struct X {
3040   using T::foo;
3041   using typename T::bar;
3042 };
3043 )cpp",
3044       R"txt(
3045 *: TranslationUnit
3046 `-TemplateDeclaration
3047   |-template
3048   |-<
3049   |-UnknownDeclaration
3050   | |-class
3051   | `-T
3052   |->
3053   `-SimpleDeclaration
3054     |-struct
3055     |-X
3056     |-{
3057     |-UsingDeclaration
3058     | |-using
3059     | |-NestedNameSpecifier
3060     | | |-IdentifierNameSpecifier
3061     | | | `-T
3062     | | `-::
3063     | |-foo
3064     | `-;
3065     |-UsingDeclaration
3066     | |-using
3067     | |-typename
3068     | |-NestedNameSpecifier
3069     | | |-IdentifierNameSpecifier
3070     | | | `-T
3071     | | `-::
3072     | |-bar
3073     | `-;
3074     |-}
3075     `-;
3076 )txt"));
3077 }
3078 
3079 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) {
3080   if (!GetParam().isCXX()) {
3081     return;
3082   }
3083   EXPECT_TRUE(treeDumpEqual(
3084       R"cpp(
3085 template <class T> struct X {};
3086 template <class T> struct X<T*> {};
3087 template <> struct X<int> {};
3088 
3089 template struct X<double>;
3090 extern template struct X<float>;
3091 )cpp",
3092       R"txt(
3093 *: TranslationUnit
3094 |-TemplateDeclaration
3095 | |-template
3096 | |-<
3097 | |-UnknownDeclaration
3098 | | |-class
3099 | | `-T
3100 | |->
3101 | `-SimpleDeclaration
3102 |   |-struct
3103 |   |-X
3104 |   |-{
3105 |   |-}
3106 |   `-;
3107 |-TemplateDeclaration
3108 | |-template
3109 | |-<
3110 | |-UnknownDeclaration
3111 | | |-class
3112 | | `-T
3113 | |->
3114 | `-SimpleDeclaration
3115 |   |-struct
3116 |   |-X
3117 |   |-<
3118 |   |-T
3119 |   |-*
3120 |   |->
3121 |   |-{
3122 |   |-}
3123 |   `-;
3124 |-TemplateDeclaration
3125 | |-template
3126 | |-<
3127 | |->
3128 | `-SimpleDeclaration
3129 |   |-struct
3130 |   |-X
3131 |   |-<
3132 |   |-int
3133 |   |->
3134 |   |-{
3135 |   |-}
3136 |   `-;
3137 |-ExplicitTemplateInstantiation
3138 | |-template
3139 | `-SimpleDeclaration
3140 |   |-struct
3141 |   |-X
3142 |   |-<
3143 |   |-double
3144 |   |->
3145 |   `-;
3146 `-ExplicitTemplateInstantiation
3147   |-extern
3148   |-template
3149   `-SimpleDeclaration
3150     |-struct
3151     |-X
3152     |-<
3153     |-float
3154     |->
3155     `-;
3156 )txt"));
3157 }
3158 
3159 TEST_P(SyntaxTreeTest, UsingType) {
3160   if (!GetParam().isCXX()) {
3161     return;
3162   }
3163   EXPECT_TRUE(treeDumpEqual(
3164       R"cpp(
3165 using type = int;
3166 )cpp",
3167       R"txt(
3168 *: TranslationUnit
3169 `-TypeAliasDeclaration
3170   |-using
3171   |-type
3172   |-=
3173   |-int
3174   `-;
3175 )txt"));
3176 }
3177 
3178 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
3179   EXPECT_TRUE(treeDumpEqual(
3180       R"cpp(
3181 ;
3182 )cpp",
3183       R"txt(
3184 *: TranslationUnit
3185 `-EmptyDeclaration
3186   `-;
3187 )txt"));
3188 }
3189 
3190 TEST_P(SyntaxTreeTest, StaticAssert) {
3191   if (!GetParam().isCXX11OrLater()) {
3192     return;
3193   }
3194   EXPECT_TRUE(treeDumpEqual(
3195       R"cpp(
3196 static_assert(true, "message");
3197 static_assert(true);
3198 )cpp",
3199       R"txt(
3200 *: TranslationUnit
3201 |-StaticAssertDeclaration
3202 | |-static_assert
3203 | |-(
3204 | |-BoolLiteralExpression
3205 | | `-true
3206 | |-,
3207 | |-StringLiteralExpression
3208 | | `-"message"
3209 | |-)
3210 | `-;
3211 `-StaticAssertDeclaration
3212   |-static_assert
3213   |-(
3214   |-BoolLiteralExpression
3215   | `-true
3216   |-)
3217   `-;
3218 )txt"));
3219 }
3220 
3221 TEST_P(SyntaxTreeTest, ExternC) {
3222   if (!GetParam().isCXX()) {
3223     return;
3224   }
3225   EXPECT_TRUE(treeDumpEqual(
3226       R"cpp(
3227 extern "C" int a;
3228 extern "C" { int b; int c; }
3229 )cpp",
3230       R"txt(
3231 *: TranslationUnit
3232 |-LinkageSpecificationDeclaration
3233 | |-extern
3234 | |-"C"
3235 | `-SimpleDeclaration
3236 |   |-int
3237 |   |-SimpleDeclarator
3238 |   | `-a
3239 |   `-;
3240 `-LinkageSpecificationDeclaration
3241   |-extern
3242   |-"C"
3243   |-{
3244   |-SimpleDeclaration
3245   | |-int
3246   | |-SimpleDeclarator
3247   | | `-b
3248   | `-;
3249   |-SimpleDeclaration
3250   | |-int
3251   | |-SimpleDeclarator
3252   | | `-c
3253   | `-;
3254   `-}
3255 )txt"));
3256 }
3257 
3258 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
3259   // Some nodes are non-modifiable, they are marked with 'I:'.
3260   EXPECT_TRUE(treeDumpEqual(
3261       R"cpp(
3262 #define HALF_IF if (1+
3263 #define HALF_IF_2 1) {}
3264 void test() {
3265   HALF_IF HALF_IF_2 else {}
3266 })cpp",
3267       R"txt(
3268 *: TranslationUnit
3269 `-SimpleDeclaration
3270   |-void
3271   |-SimpleDeclarator
3272   | |-test
3273   | `-ParametersAndQualifiers
3274   |   |-(
3275   |   `-)
3276   `-CompoundStatement
3277     |-{
3278     |-IfStatement
3279     | |-I: if
3280     | |-I: (
3281     | |-I: BinaryOperatorExpression
3282     | | |-I: IntegerLiteralExpression
3283     | | | `-I: 1
3284     | | |-I: +
3285     | | `-I: IntegerLiteralExpression
3286     | |   `-I: 1
3287     | |-I: )
3288     | |-I: CompoundStatement
3289     | | |-I: {
3290     | | `-I: }
3291     | |-else
3292     | `-CompoundStatement
3293     |   |-{
3294     |   `-}
3295     `-}
3296 )txt"));
3297 }
3298 
3299 TEST_P(SyntaxTreeTest, ModifiableNodes) {
3300   // All nodes can be mutated.
3301   EXPECT_TRUE(treeDumpEqual(
3302       R"cpp(
3303 #define OPEN {
3304 #define CLOSE }
3305 
3306 void test() {
3307   OPEN
3308     1;
3309   CLOSE
3310 
3311   OPEN
3312     2;
3313   }
3314 }
3315 )cpp",
3316       R"txt(
3317 *: TranslationUnit
3318 `-SimpleDeclaration
3319   |-void
3320   |-SimpleDeclarator
3321   | |-test
3322   | `-ParametersAndQualifiers
3323   |   |-(
3324   |   `-)
3325   `-CompoundStatement
3326     |-{
3327     |-CompoundStatement
3328     | |-{
3329     | |-ExpressionStatement
3330     | | |-IntegerLiteralExpression
3331     | | | `-1
3332     | | `-;
3333     | `-}
3334     |-CompoundStatement
3335     | |-{
3336     | |-ExpressionStatement
3337     | | |-IntegerLiteralExpression
3338     | | | `-2
3339     | | `-;
3340     | `-}
3341     `-}
3342 )txt"));
3343 }
3344 
3345 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) {
3346   EXPECT_TRUE(treeDumpEqual(
3347       R"cpp(
3348 int a[10];
3349 int b[1][2][3];
3350 int c[] = {1,2,3};
3351 )cpp",
3352       R"txt(
3353 *: TranslationUnit
3354 |-SimpleDeclaration
3355 | |-int
3356 | |-SimpleDeclarator
3357 | | |-a
3358 | | `-ArraySubscript
3359 | |   |-[
3360 | |   |-IntegerLiteralExpression
3361 | |   | `-10
3362 | |   `-]
3363 | `-;
3364 |-SimpleDeclaration
3365 | |-int
3366 | |-SimpleDeclarator
3367 | | |-b
3368 | | |-ArraySubscript
3369 | | | |-[
3370 | | | |-IntegerLiteralExpression
3371 | | | | `-1
3372 | | | `-]
3373 | | |-ArraySubscript
3374 | | | |-[
3375 | | | |-IntegerLiteralExpression
3376 | | | | `-2
3377 | | | `-]
3378 | | `-ArraySubscript
3379 | |   |-[
3380 | |   |-IntegerLiteralExpression
3381 | |   | `-3
3382 | |   `-]
3383 | `-;
3384 `-SimpleDeclaration
3385   |-int
3386   |-SimpleDeclarator
3387   | |-c
3388   | |-ArraySubscript
3389   | | |-[
3390   | | `-]
3391   | |-=
3392   | `-UnknownExpression
3393   |   `-UnknownExpression
3394   |     |-{
3395   |     |-IntegerLiteralExpression
3396   |     | `-1
3397   |     |-,
3398   |     |-IntegerLiteralExpression
3399   |     | `-2
3400   |     |-,
3401   |     |-IntegerLiteralExpression
3402   |     | `-3
3403   |     `-}
3404   `-;
3405 )txt"));
3406 }
3407 
3408 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) {
3409   if (!GetParam().isC99OrLater()) {
3410     return;
3411   }
3412   EXPECT_TRUE(treeDumpEqual(
3413       R"cpp(
3414 void f(int xs[static 10]);
3415 )cpp",
3416       R"txt(
3417 *: TranslationUnit
3418 `-SimpleDeclaration
3419   |-void
3420   |-SimpleDeclarator
3421   | |-f
3422   | `-ParametersAndQualifiers
3423   |   |-(
3424   |   |-SimpleDeclaration
3425   |   | |-int
3426   |   | `-SimpleDeclarator
3427   |   |   |-xs
3428   |   |   `-ArraySubscript
3429   |   |     |-[
3430   |   |     |-static
3431   |   |     |-IntegerLiteralExpression
3432   |   |     | `-10
3433   |   |     `-]
3434   |   `-)
3435   `-;
3436 )txt"));
3437 }
3438 
3439 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) {
3440   if (!GetParam().isCXX()) {
3441     return;
3442   }
3443   EXPECT_TRUE(treeDumpEqual(
3444       R"cpp(
3445 int func1();
3446 int func2a(int a);
3447 int func2b(int);
3448 int func3a(int *ap);
3449 int func3b(int *);
3450 int func4a(int a, float b);
3451 int func4b(int, float);
3452 )cpp",
3453       R"txt(
3454 *: TranslationUnit
3455 |-SimpleDeclaration
3456 | |-int
3457 | |-SimpleDeclarator
3458 | | |-func1
3459 | | `-ParametersAndQualifiers
3460 | |   |-(
3461 | |   `-)
3462 | `-;
3463 |-SimpleDeclaration
3464 | |-int
3465 | |-SimpleDeclarator
3466 | | |-func2a
3467 | | `-ParametersAndQualifiers
3468 | |   |-(
3469 | |   |-SimpleDeclaration
3470 | |   | |-int
3471 | |   | `-SimpleDeclarator
3472 | |   |   `-a
3473 | |   `-)
3474 | `-;
3475 |-SimpleDeclaration
3476 | |-int
3477 | |-SimpleDeclarator
3478 | | |-func2b
3479 | | `-ParametersAndQualifiers
3480 | |   |-(
3481 | |   |-SimpleDeclaration
3482 | |   | `-int
3483 | |   `-)
3484 | `-;
3485 |-SimpleDeclaration
3486 | |-int
3487 | |-SimpleDeclarator
3488 | | |-func3a
3489 | | `-ParametersAndQualifiers
3490 | |   |-(
3491 | |   |-SimpleDeclaration
3492 | |   | |-int
3493 | |   | `-SimpleDeclarator
3494 | |   |   |-*
3495 | |   |   `-ap
3496 | |   `-)
3497 | `-;
3498 |-SimpleDeclaration
3499 | |-int
3500 | |-SimpleDeclarator
3501 | | |-func3b
3502 | | `-ParametersAndQualifiers
3503 | |   |-(
3504 | |   |-SimpleDeclaration
3505 | |   | |-int
3506 | |   | `-SimpleDeclarator
3507 | |   |   `-*
3508 | |   `-)
3509 | `-;
3510 |-SimpleDeclaration
3511 | |-int
3512 | |-SimpleDeclarator
3513 | | |-func4a
3514 | | `-ParametersAndQualifiers
3515 | |   |-(
3516 | |   |-SimpleDeclaration
3517 | |   | |-int
3518 | |   | `-SimpleDeclarator
3519 | |   |   `-a
3520 | |   |-,
3521 | |   |-SimpleDeclaration
3522 | |   | |-float
3523 | |   | `-SimpleDeclarator
3524 | |   |   `-b
3525 | |   `-)
3526 | `-;
3527 `-SimpleDeclaration
3528   |-int
3529   |-SimpleDeclarator
3530   | |-func4b
3531   | `-ParametersAndQualifiers
3532   |   |-(
3533   |   |-SimpleDeclaration
3534   |   | `-int
3535   |   |-,
3536   |   |-SimpleDeclaration
3537   |   | `-float
3538   |   `-)
3539   `-;
3540 )txt"));
3541 }
3542 
3543 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) {
3544   if (!GetParam().isCXX()) {
3545     return;
3546   }
3547   EXPECT_TRUE(treeDumpEqual(
3548       R"cpp(
3549 int func1(const int a, volatile int b, const volatile int c);
3550 int func2(int& a);
3551 )cpp",
3552       R"txt(
3553 *: TranslationUnit
3554 |-SimpleDeclaration
3555 | |-int
3556 | |-SimpleDeclarator
3557 | | |-func1
3558 | | `-ParametersAndQualifiers
3559 | |   |-(
3560 | |   |-SimpleDeclaration
3561 | |   | |-const
3562 | |   | |-int
3563 | |   | `-SimpleDeclarator
3564 | |   |   `-a
3565 | |   |-,
3566 | |   |-SimpleDeclaration
3567 | |   | |-volatile
3568 | |   | |-int
3569 | |   | `-SimpleDeclarator
3570 | |   |   `-b
3571 | |   |-,
3572 | |   |-SimpleDeclaration
3573 | |   | |-const
3574 | |   | |-volatile
3575 | |   | |-int
3576 | |   | `-SimpleDeclarator
3577 | |   |   `-c
3578 | |   `-)
3579 | `-;
3580 `-SimpleDeclaration
3581   |-int
3582   |-SimpleDeclarator
3583   | |-func2
3584   | `-ParametersAndQualifiers
3585   |   |-(
3586   |   |-SimpleDeclaration
3587   |   | |-int
3588   |   | `-SimpleDeclarator
3589   |   |   |-&
3590   |   |   `-a
3591   |   `-)
3592   `-;
3593 )txt"));
3594 }
3595 
3596 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) {
3597   if (!GetParam().isCXX11OrLater()) {
3598     return;
3599   }
3600   EXPECT_TRUE(treeDumpEqual(
3601       R"cpp(
3602 int func1(int&& a);
3603 )cpp",
3604       R"txt(
3605 *: TranslationUnit
3606 `-SimpleDeclaration
3607   |-int
3608   |-SimpleDeclarator
3609   | |-func1
3610   | `-ParametersAndQualifiers
3611   |   |-(
3612   |   |-SimpleDeclaration
3613   |   | |-int
3614   |   | `-SimpleDeclarator
3615   |   |   |-&&
3616   |   |   `-a
3617   |   `-)
3618   `-;
3619 )txt"));
3620 }
3621 
3622 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) {
3623   if (!GetParam().isCXX()) {
3624     return;
3625   }
3626   EXPECT_TRUE(treeDumpEqual(
3627       R"cpp(
3628 struct Test {
3629   int a();
3630   int b() const;
3631   int c() volatile;
3632   int d() const volatile;
3633   int e() &;
3634   int f() &&;
3635 };
3636 )cpp",
3637       R"txt(
3638 *: TranslationUnit
3639 `-SimpleDeclaration
3640   |-struct
3641   |-Test
3642   |-{
3643   |-SimpleDeclaration
3644   | |-int
3645   | |-SimpleDeclarator
3646   | | |-a
3647   | | `-ParametersAndQualifiers
3648   | |   |-(
3649   | |   `-)
3650   | `-;
3651   |-SimpleDeclaration
3652   | |-int
3653   | |-SimpleDeclarator
3654   | | |-b
3655   | | `-ParametersAndQualifiers
3656   | |   |-(
3657   | |   |-)
3658   | |   `-const
3659   | `-;
3660   |-SimpleDeclaration
3661   | |-int
3662   | |-SimpleDeclarator
3663   | | |-c
3664   | | `-ParametersAndQualifiers
3665   | |   |-(
3666   | |   |-)
3667   | |   `-volatile
3668   | `-;
3669   |-SimpleDeclaration
3670   | |-int
3671   | |-SimpleDeclarator
3672   | | |-d
3673   | | `-ParametersAndQualifiers
3674   | |   |-(
3675   | |   |-)
3676   | |   |-const
3677   | |   `-volatile
3678   | `-;
3679   |-SimpleDeclaration
3680   | |-int
3681   | |-SimpleDeclarator
3682   | | |-e
3683   | | `-ParametersAndQualifiers
3684   | |   |-(
3685   | |   |-)
3686   | |   `-&
3687   | `-;
3688   |-SimpleDeclaration
3689   | |-int
3690   | |-SimpleDeclarator
3691   | | |-f
3692   | | `-ParametersAndQualifiers
3693   | |   |-(
3694   | |   |-)
3695   | |   `-&&
3696   | `-;
3697   |-}
3698   `-;
3699 )txt"));
3700 }
3701 
3702 TEST_P(SyntaxTreeTest, TrailingReturn) {
3703   if (!GetParam().isCXX11OrLater()) {
3704     return;
3705   }
3706   EXPECT_TRUE(treeDumpEqual(
3707       R"cpp(
3708 auto foo() -> int;
3709 )cpp",
3710       R"txt(
3711 *: TranslationUnit
3712 `-SimpleDeclaration
3713   |-auto
3714   |-SimpleDeclarator
3715   | |-foo
3716   | `-ParametersAndQualifiers
3717   |   |-(
3718   |   |-)
3719   |   `-TrailingReturnType
3720   |     |-->
3721   |     `-int
3722   `-;
3723 )txt"));
3724 }
3725 
3726 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
3727   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
3728     return;
3729   }
3730   EXPECT_TRUE(treeDumpEqual(
3731       R"cpp(
3732 struct MyException1 {};
3733 struct MyException2 {};
3734 int a() throw();
3735 int b() throw(...);
3736 int c() throw(MyException1);
3737 int d() throw(MyException1, MyException2);
3738 )cpp",
3739       R"txt(
3740 *: TranslationUnit
3741 |-SimpleDeclaration
3742 | |-struct
3743 | |-MyException1
3744 | |-{
3745 | |-}
3746 | `-;
3747 |-SimpleDeclaration
3748 | |-struct
3749 | |-MyException2
3750 | |-{
3751 | |-}
3752 | `-;
3753 |-SimpleDeclaration
3754 | |-int
3755 | |-SimpleDeclarator
3756 | | |-a
3757 | | `-ParametersAndQualifiers
3758 | |   |-(
3759 | |   |-)
3760 | |   |-throw
3761 | |   |-(
3762 | |   `-)
3763 | `-;
3764 |-SimpleDeclaration
3765 | |-int
3766 | |-SimpleDeclarator
3767 | | |-b
3768 | | `-ParametersAndQualifiers
3769 | |   |-(
3770 | |   |-)
3771 | |   |-throw
3772 | |   |-(
3773 | |   |-...
3774 | |   `-)
3775 | `-;
3776 |-SimpleDeclaration
3777 | |-int
3778 | |-SimpleDeclarator
3779 | | |-c
3780 | | `-ParametersAndQualifiers
3781 | |   |-(
3782 | |   |-)
3783 | |   |-throw
3784 | |   |-(
3785 | |   |-MyException1
3786 | |   `-)
3787 | `-;
3788 `-SimpleDeclaration
3789   |-int
3790   |-SimpleDeclarator
3791   | |-d
3792   | `-ParametersAndQualifiers
3793   |   |-(
3794   |   |-)
3795   |   |-throw
3796   |   |-(
3797   |   |-MyException1
3798   |   |-,
3799   |   |-MyException2
3800   |   `-)
3801   `-;
3802 )txt"));
3803 }
3804 
3805 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
3806   if (!GetParam().isCXX11OrLater()) {
3807     return;
3808   }
3809   EXPECT_TRUE(treeDumpEqual(
3810       R"cpp(
3811 int a() noexcept;
3812 int b() noexcept(true);
3813 )cpp",
3814       R"txt(
3815 *: TranslationUnit
3816 |-SimpleDeclaration
3817 | |-int
3818 | |-SimpleDeclarator
3819 | | |-a
3820 | | `-ParametersAndQualifiers
3821 | |   |-(
3822 | |   |-)
3823 | |   `-noexcept
3824 | `-;
3825 `-SimpleDeclaration
3826   |-int
3827   |-SimpleDeclarator
3828   | |-b
3829   | `-ParametersAndQualifiers
3830   |   |-(
3831   |   |-)
3832   |   |-noexcept
3833   |   |-(
3834   |   |-BoolLiteralExpression
3835   |   | `-true
3836   |   `-)
3837   `-;
3838 )txt"));
3839 }
3840 
3841 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
3842   EXPECT_TRUE(treeDumpEqual(
3843       R"cpp(
3844 int (a);
3845 int *(b);
3846 int (*c)(int);
3847 int *(d)(int);
3848 )cpp",
3849       R"txt(
3850 *: TranslationUnit
3851 |-SimpleDeclaration
3852 | |-int
3853 | |-SimpleDeclarator
3854 | | `-ParenDeclarator
3855 | |   |-(
3856 | |   |-a
3857 | |   `-)
3858 | `-;
3859 |-SimpleDeclaration
3860 | |-int
3861 | |-SimpleDeclarator
3862 | | |-*
3863 | | `-ParenDeclarator
3864 | |   |-(
3865 | |   |-b
3866 | |   `-)
3867 | `-;
3868 |-SimpleDeclaration
3869 | |-int
3870 | |-SimpleDeclarator
3871 | | |-ParenDeclarator
3872 | | | |-(
3873 | | | |-*
3874 | | | |-c
3875 | | | `-)
3876 | | `-ParametersAndQualifiers
3877 | |   |-(
3878 | |   |-SimpleDeclaration
3879 | |   | `-int
3880 | |   `-)
3881 | `-;
3882 `-SimpleDeclaration
3883   |-int
3884   |-SimpleDeclarator
3885   | |-*
3886   | |-ParenDeclarator
3887   | | |-(
3888   | | |-d
3889   | | `-)
3890   | `-ParametersAndQualifiers
3891   |   |-(
3892   |   |-SimpleDeclaration
3893   |   | `-int
3894   |   `-)
3895   `-;
3896 )txt"));
3897 }
3898 
3899 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) {
3900   EXPECT_TRUE(treeDumpEqual(
3901       R"cpp(
3902 const int west = -1;
3903 int const east = 1;
3904 const int const universal = 0;
3905 const int const *const *volatile b;
3906 )cpp",
3907       R"txt(
3908 *: TranslationUnit
3909 |-SimpleDeclaration
3910 | |-const
3911 | |-int
3912 | |-SimpleDeclarator
3913 | | |-west
3914 | | |-=
3915 | | `-PrefixUnaryOperatorExpression
3916 | |   |--
3917 | |   `-IntegerLiteralExpression
3918 | |     `-1
3919 | `-;
3920 |-SimpleDeclaration
3921 | |-int
3922 | |-const
3923 | |-SimpleDeclarator
3924 | | |-east
3925 | | |-=
3926 | | `-IntegerLiteralExpression
3927 | |   `-1
3928 | `-;
3929 |-SimpleDeclaration
3930 | |-const
3931 | |-int
3932 | |-const
3933 | |-SimpleDeclarator
3934 | | |-universal
3935 | | |-=
3936 | | `-IntegerLiteralExpression
3937 | |   `-0
3938 | `-;
3939 `-SimpleDeclaration
3940   |-const
3941   |-int
3942   |-const
3943   |-SimpleDeclarator
3944   | |-*
3945   | |-const
3946   | |-*
3947   | |-volatile
3948   | `-b
3949   `-;
3950 )txt"));
3951 }
3952 
3953 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
3954   if (!GetParam().isCXX11OrLater()) {
3955     return;
3956   }
3957   EXPECT_TRUE(treeDumpEqual(
3958       R"cpp(
3959 auto foo() -> auto(*)(int) -> double*;
3960 )cpp",
3961       R"txt(
3962 *: TranslationUnit
3963 `-SimpleDeclaration
3964   |-auto
3965   |-SimpleDeclarator
3966   | |-foo
3967   | `-ParametersAndQualifiers
3968   |   |-(
3969   |   |-)
3970   |   `-TrailingReturnType
3971   |     |-->
3972   |     |-auto
3973   |     `-SimpleDeclarator
3974   |       |-ParenDeclarator
3975   |       | |-(
3976   |       | |-*
3977   |       | `-)
3978   |       `-ParametersAndQualifiers
3979   |         |-(
3980   |         |-SimpleDeclaration
3981   |         | `-int
3982   |         |-)
3983   |         `-TrailingReturnType
3984   |           |-->
3985   |           |-double
3986   |           `-SimpleDeclarator
3987   |             `-*
3988   `-;
3989 )txt"));
3990 }
3991 
3992 TEST_P(SyntaxTreeTest, MemberPointers) {
3993   if (!GetParam().isCXX()) {
3994     return;
3995   }
3996   EXPECT_TRUE(treeDumpEqual(
3997       R"cpp(
3998 struct X {};
3999 int X::* a;
4000 const int X::* b;
4001 )cpp",
4002       R"txt(
4003 *: TranslationUnit
4004 |-SimpleDeclaration
4005 | |-struct
4006 | |-X
4007 | |-{
4008 | |-}
4009 | `-;
4010 |-SimpleDeclaration
4011 | |-int
4012 | |-SimpleDeclarator
4013 | | |-MemberPointer
4014 | | | |-X
4015 | | | |-::
4016 | | | `-*
4017 | | `-a
4018 | `-;
4019 `-SimpleDeclaration
4020   |-const
4021   |-int
4022   |-SimpleDeclarator
4023   | |-MemberPointer
4024   | | |-X
4025   | | |-::
4026   | | `-*
4027   | `-b
4028   `-;
4029 )txt"));
4030 }
4031 
4032 TEST_P(SyntaxTreeTest, MemberFunctionPointer) {
4033   if (!GetParam().isCXX()) {
4034     return;
4035   }
4036   EXPECT_TRUE(treeDumpEqual(
4037       R"cpp(
4038 struct X {
4039   struct Y {};
4040 };
4041 void (X::*xp)();
4042 void (X::**xpp)(const int*);
4043 // FIXME: Generate the right syntax tree for this type,
4044 // i.e. create a syntax node for the outer member pointer
4045 void (X::Y::*xyp)(const int*, char);
4046 )cpp",
4047       R"txt(
4048 *: TranslationUnit
4049 |-SimpleDeclaration
4050 | |-struct
4051 | |-X
4052 | |-{
4053 | |-SimpleDeclaration
4054 | | |-struct
4055 | | |-Y
4056 | | |-{
4057 | | |-}
4058 | | `-;
4059 | |-}
4060 | `-;
4061 |-SimpleDeclaration
4062 | |-void
4063 | |-SimpleDeclarator
4064 | | |-ParenDeclarator
4065 | | | |-(
4066 | | | |-MemberPointer
4067 | | | | |-X
4068 | | | | |-::
4069 | | | | `-*
4070 | | | |-xp
4071 | | | `-)
4072 | | `-ParametersAndQualifiers
4073 | |   |-(
4074 | |   `-)
4075 | `-;
4076 |-SimpleDeclaration
4077 | |-void
4078 | |-SimpleDeclarator
4079 | | |-ParenDeclarator
4080 | | | |-(
4081 | | | |-MemberPointer
4082 | | | | |-X
4083 | | | | |-::
4084 | | | | `-*
4085 | | | |-*
4086 | | | |-xpp
4087 | | | `-)
4088 | | `-ParametersAndQualifiers
4089 | |   |-(
4090 | |   |-SimpleDeclaration
4091 | |   | |-const
4092 | |   | |-int
4093 | |   | `-SimpleDeclarator
4094 | |   |   `-*
4095 | |   `-)
4096 | `-;
4097 `-SimpleDeclaration
4098   |-void
4099   |-SimpleDeclarator
4100   | |-ParenDeclarator
4101   | | |-(
4102   | | |-X
4103   | | |-::
4104   | | |-MemberPointer
4105   | | | |-Y
4106   | | | |-::
4107   | | | `-*
4108   | | |-xyp
4109   | | `-)
4110   | `-ParametersAndQualifiers
4111   |   |-(
4112   |   |-SimpleDeclaration
4113   |   | |-const
4114   |   | |-int
4115   |   | `-SimpleDeclarator
4116   |   |   `-*
4117   |   |-,
4118   |   |-SimpleDeclaration
4119   |   | `-char
4120   |   `-)
4121   `-;
4122 )txt"));
4123 }
4124 
4125 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
4126   EXPECT_TRUE(treeDumpEqual(
4127       R"cpp(
4128 void x(char a, short (*b)(int));
4129 )cpp",
4130       R"txt(
4131 *: TranslationUnit
4132 `-SimpleDeclaration
4133   |-void
4134   |-SimpleDeclarator
4135   | |-x
4136   | `-ParametersAndQualifiers
4137   |   |-(
4138   |   |-SimpleDeclaration
4139   |   | |-char
4140   |   | `-SimpleDeclarator
4141   |   |   `-a
4142   |   |-,
4143   |   |-SimpleDeclaration
4144   |   | |-short
4145   |   | `-SimpleDeclarator
4146   |   |   |-ParenDeclarator
4147   |   |   | |-(
4148   |   |   | |-*
4149   |   |   | |-b
4150   |   |   | `-)
4151   |   |   `-ParametersAndQualifiers
4152   |   |     |-(
4153   |   |     |-SimpleDeclaration
4154   |   |     | `-int
4155   |   |     `-)
4156   |   `-)
4157   `-;
4158 )txt"));
4159 }
4160 
4161 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
4162   EXPECT_TRUE(treeDumpEqual(
4163       R"cpp(
4164 void x(char a, short (*b)(int), long (**c)(long long));
4165 )cpp",
4166       R"txt(
4167 *: TranslationUnit
4168 `-SimpleDeclaration
4169   |-void
4170   |-SimpleDeclarator
4171   | |-x
4172   | `-ParametersAndQualifiers
4173   |   |-(
4174   |   |-SimpleDeclaration
4175   |   | |-char
4176   |   | `-SimpleDeclarator
4177   |   |   `-a
4178   |   |-,
4179   |   |-SimpleDeclaration
4180   |   | |-short
4181   |   | `-SimpleDeclarator
4182   |   |   |-ParenDeclarator
4183   |   |   | |-(
4184   |   |   | |-*
4185   |   |   | |-b
4186   |   |   | `-)
4187   |   |   `-ParametersAndQualifiers
4188   |   |     |-(
4189   |   |     |-SimpleDeclaration
4190   |   |     | `-int
4191   |   |     `-)
4192   |   |-,
4193   |   |-SimpleDeclaration
4194   |   | |-long
4195   |   | `-SimpleDeclarator
4196   |   |   |-ParenDeclarator
4197   |   |   | |-(
4198   |   |   | |-*
4199   |   |   | |-*
4200   |   |   | |-c
4201   |   |   | `-)
4202   |   |   `-ParametersAndQualifiers
4203   |   |     |-(
4204   |   |     |-SimpleDeclaration
4205   |   |     | |-long
4206   |   |     | `-long
4207   |   |     `-)
4208   |   `-)
4209   `-;
4210 )txt"));
4211 }
4212 
4213 } // namespace
4214