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 class BuildSyntaxTreeTest : public SyntaxTreeTest {
21 protected:
22   ::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree) {
23     SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
24 
25     auto *Root = buildTree(Code, GetParam());
26     if (Diags->getClient()->getNumErrors() != 0) {
27       return ::testing::AssertionFailure()
28              << "Source file has syntax errors, they were printed to the test "
29                 "log";
30     }
31     auto Actual = StringRef(Root->dump(Arena->getSourceManager())).trim().str();
32     // EXPECT_EQ shows the diff between the two strings if they are different.
33     EXPECT_EQ(Tree.trim().str(), Actual);
34     if (Actual != Tree.trim().str()) {
35       return ::testing::AssertionFailure();
36     }
37     return ::testing::AssertionSuccess();
38   }
39 
40   ::testing::AssertionResult
41   treeDumpEqualOnAnnotations(StringRef CodeWithAnnotations,
42                              ArrayRef<StringRef> TreeDumps) {
43     SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
44 
45     auto AnnotatedCode = llvm::Annotations(CodeWithAnnotations);
46     auto *Root = buildTree(AnnotatedCode.code(), GetParam());
47 
48     if (Diags->getClient()->getNumErrors() != 0) {
49       return ::testing::AssertionFailure()
50              << "Source file has syntax errors, they were printed to the test "
51                 "log";
52     }
53 
54     auto AnnotatedRanges = AnnotatedCode.ranges();
55     if (AnnotatedRanges.size() != TreeDumps.size()) {
56       return ::testing::AssertionFailure()
57              << "The number of annotated ranges in the source code is "
58                 "different "
59                 "to the number of their corresponding tree dumps.";
60     }
61     bool Failed = false;
62     for (unsigned i = 0; i < AnnotatedRanges.size(); i++) {
63       auto *AnnotatedNode = nodeByRange(AnnotatedRanges[i], Root);
64       assert(AnnotatedNode);
65       auto AnnotatedNodeDump =
66           StringRef(AnnotatedNode->dump(Arena->getSourceManager()))
67               .trim()
68               .str();
69       // EXPECT_EQ shows the diff between the two strings if they are different.
70       EXPECT_EQ(TreeDumps[i].trim().str(), AnnotatedNodeDump)
71           << "Dumps diverged for the code:\n"
72           << AnnotatedCode.code().slice(AnnotatedRanges[i].Begin,
73                                         AnnotatedRanges[i].End);
74       if (AnnotatedNodeDump != TreeDumps[i].trim().str())
75         Failed = true;
76     }
77     return Failed ? ::testing::AssertionFailure()
78                   : ::testing::AssertionSuccess();
79   }
80 };
81 
82 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, BuildSyntaxTreeTest,
83                         testing::ValuesIn(allTestClangConfigs()), );
84 
85 TEST_P(BuildSyntaxTreeTest, Simple) {
86   EXPECT_TRUE(treeDumpEqual(
87       R"cpp(
88 int main() {}
89 void foo() {}
90 )cpp",
91       R"txt(
92 TranslationUnit Detached
93 |-SimpleDeclaration
94 | |-'int'
95 | |-DeclaratorList Declarators
96 | | `-SimpleDeclarator ListElement
97 | |   |-'main'
98 | |   `-ParametersAndQualifiers
99 | |     |-'(' OpenParen
100 | |     `-')' CloseParen
101 | `-CompoundStatement
102 |   |-'{' OpenParen
103 |   `-'}' CloseParen
104 `-SimpleDeclaration
105   |-'void'
106   |-DeclaratorList Declarators
107   | `-SimpleDeclarator ListElement
108   |   |-'foo'
109   |   `-ParametersAndQualifiers
110   |     |-'(' OpenParen
111   |     `-')' CloseParen
112   `-CompoundStatement
113     |-'{' OpenParen
114     `-'}' CloseParen
115 )txt"));
116 }
117 
118 TEST_P(BuildSyntaxTreeTest, SimpleVariable) {
119   EXPECT_TRUE(treeDumpEqual(
120       R"cpp(
121 int a;
122 int b = 42;
123 )cpp",
124       R"txt(
125 TranslationUnit Detached
126 |-SimpleDeclaration
127 | |-'int'
128 | |-DeclaratorList Declarators
129 | | `-SimpleDeclarator ListElement
130 | |   `-'a'
131 | `-';'
132 `-SimpleDeclaration
133   |-'int'
134   |-DeclaratorList Declarators
135   | `-SimpleDeclarator ListElement
136   |   |-'b'
137   |   |-'='
138   |   `-IntegerLiteralExpression
139   |     `-'42' LiteralToken
140   `-';'
141 )txt"));
142 }
143 
144 TEST_P(BuildSyntaxTreeTest, SimpleFunction) {
145   EXPECT_TRUE(treeDumpEqual(
146       R"cpp(
147 void foo(int a, int b) {}
148 )cpp",
149       R"txt(
150 TranslationUnit Detached
151 `-SimpleDeclaration
152   |-'void'
153   |-DeclaratorList Declarators
154   | `-SimpleDeclarator ListElement
155   |   |-'foo'
156   |   `-ParametersAndQualifiers
157   |     |-'(' OpenParen
158   |     |-ParameterDeclarationList Parameters
159   |     | |-SimpleDeclaration ListElement
160   |     | | |-'int'
161   |     | | `-DeclaratorList Declarators
162   |     | |   `-SimpleDeclarator ListElement
163   |     | |     `-'a'
164   |     | |-',' ListDelimiter
165   |     | `-SimpleDeclaration ListElement
166   |     |   |-'int'
167   |     |   `-DeclaratorList Declarators
168   |     |     `-SimpleDeclarator ListElement
169   |     |       `-'b'
170   |     `-')' CloseParen
171   `-CompoundStatement
172     |-'{' OpenParen
173     `-'}' CloseParen
174 )txt"));
175 }
176 
177 TEST_P(BuildSyntaxTreeTest, Simple_BackslashInsideToken) {
178   EXPECT_TRUE(treeDumpEqual(
179       R"cpp(
180 in\
181 t a;
182 )cpp",
183       R"txt(
184 TranslationUnit Detached
185 `-SimpleDeclaration
186   |-'in\
187 t'
188   |-DeclaratorList Declarators
189   | `-SimpleDeclarator ListElement
190   |   `-'a'
191   `-';'
192 )txt"));
193 }
194 
195 TEST_P(BuildSyntaxTreeTest, If) {
196   EXPECT_TRUE(treeDumpEqualOnAnnotations(
197       R"cpp(
198 void test() {
199   [[if (1) {}]]
200   [[if (1) {} else if (0) {}]]
201 }
202 )cpp",
203       {R"txt(
204 IfStatement Statement
205 |-'if' IntroducerKeyword
206 |-'('
207 |-ExpressionStatement Condition
208 | `-IntegerLiteralExpression Expression
209 |   `-'1' LiteralToken
210 |-')'
211 `-CompoundStatement ThenStatement
212   |-'{' OpenParen
213   `-'}' CloseParen
214   )txt",
215        R"txt(
216 IfStatement Statement
217 |-'if' IntroducerKeyword
218 |-'('
219 |-ExpressionStatement Condition
220 | `-IntegerLiteralExpression Expression
221 |   `-'1' LiteralToken
222 |-')'
223 |-CompoundStatement ThenStatement
224 | |-'{' OpenParen
225 | `-'}' CloseParen
226 |-'else' ElseKeyword
227 `-IfStatement ElseStatement
228   |-'if' IntroducerKeyword
229   |-'('
230   |-ExpressionStatement Condition
231   | `-IntegerLiteralExpression Expression
232   |   `-'0' LiteralToken
233   |-')'
234   `-CompoundStatement ThenStatement
235     |-'{' OpenParen
236     `-'}' CloseParen
237 )txt"}));
238 }
239 
240 TEST_P(BuildSyntaxTreeTest, IfDecl) {
241   if (!GetParam().isCXX17OrLater()) {
242     return;
243   }
244   EXPECT_TRUE(treeDumpEqualOnAnnotations(
245       R"cpp(
246 void test() {
247   [[if (int a = 5) {}]]
248   [[if (int a; a == 5) {}]]
249 }
250 )cpp",
251       {R"txt(
252 IfStatement Statement
253 |-'if' IntroducerKeyword
254 |-'('
255 |-DeclarationStatement Condition
256 | `-SimpleDeclaration
257 |   |-'int'
258 |   `-DeclaratorList Declarators
259 |     `-SimpleDeclarator ListElement
260 |       |-'a'
261 |       |-'='
262 |       `-IntegerLiteralExpression
263 |         `-'5' LiteralToken
264 |-')'
265 `-CompoundStatement ThenStatement
266   |-'{' OpenParen
267   `-'}' CloseParen
268       )txt",
269        R"txt(
270 IfStatement Statement
271 |-'if' IntroducerKeyword
272 |-'('
273 |-DeclarationStatement
274 | |-SimpleDeclaration
275 | | |-'int'
276 | | `-DeclaratorList Declarators
277 | |   `-SimpleDeclarator ListElement
278 | |     `-'a'
279 | `-';'
280 |-ExpressionStatement Condition
281 | `-BinaryOperatorExpression Expression
282 |   |-IdExpression LeftHandSide
283 |   | `-UnqualifiedId UnqualifiedId
284 |   |   `-'a'
285 |   |-'==' OperatorToken
286 |   `-IntegerLiteralExpression RightHandSide
287 |     `-'5' LiteralToken
288 |-')'
289 `-CompoundStatement ThenStatement
290   |-'{' OpenParen
291   `-'}' CloseParen
292 )txt"}));
293 }
294 
295 TEST_P(BuildSyntaxTreeTest, For) {
296   EXPECT_TRUE(treeDumpEqualOnAnnotations(
297       R"cpp(
298 void test() {
299   [[for (;;)  {}]]
300 }
301 )cpp",
302       {R"txt(
303 ForStatement Statement
304 |-'for' IntroducerKeyword
305 |-'('
306 |-';'
307 |-';'
308 |-')'
309 `-CompoundStatement BodyStatement
310   |-'{' OpenParen
311   `-'}' CloseParen
312 )txt"}));
313 }
314 
315 TEST_P(BuildSyntaxTreeTest, RangeBasedFor) {
316   if (!GetParam().isCXX11OrLater()) {
317     return;
318   }
319   EXPECT_TRUE(treeDumpEqualOnAnnotations(
320       R"cpp(
321 void test() {
322   int a[3];
323   [[for (int x : a)
324     ;]]
325 }
326 )cpp",
327       {R"txt(
328 RangeBasedForStatement Statement
329 |-'for' IntroducerKeyword
330 |-'('
331 |-SimpleDeclaration
332 | |-'int'
333 | |-DeclaratorList Declarators
334 | | `-SimpleDeclarator ListElement
335 | |   `-'x'
336 | `-':'
337 |-IdExpression
338 | `-UnqualifiedId UnqualifiedId
339 |   `-'a'
340 |-')'
341 `-EmptyStatement BodyStatement
342   `-';'
343 )txt"}));
344 }
345 
346 TEST_P(BuildSyntaxTreeTest, DeclarationStatement) {
347   EXPECT_TRUE(treeDumpEqualOnAnnotations(
348       R"cpp(
349 void test() {
350   [[int a = 10;]]
351 }
352 )cpp",
353       {R"txt(
354 DeclarationStatement Statement
355 |-SimpleDeclaration
356 | |-'int'
357 | `-DeclaratorList Declarators
358 |   `-SimpleDeclarator ListElement
359 |     |-'a'
360 |     |-'='
361 |     `-IntegerLiteralExpression
362 |       `-'10' LiteralToken
363 `-';'
364 )txt"}));
365 }
366 
367 TEST_P(BuildSyntaxTreeTest, Switch) {
368   EXPECT_TRUE(treeDumpEqualOnAnnotations(
369       R"cpp(
370 void test() {
371   [[switch (1) {
372     case 0:
373     default:;
374   }]]
375 }
376 )cpp",
377       {R"txt(
378 SwitchStatement Statement
379 |-'switch' IntroducerKeyword
380 |-'('
381 |-IntegerLiteralExpression
382 | `-'1' LiteralToken
383 |-')'
384 `-CompoundStatement BodyStatement
385   |-'{' OpenParen
386   |-CaseStatement Statement
387   | |-'case' IntroducerKeyword
388   | |-IntegerLiteralExpression CaseValue
389   | | `-'0' LiteralToken
390   | |-':'
391   | `-DefaultStatement BodyStatement
392   |   |-'default' IntroducerKeyword
393   |   |-':'
394   |   `-EmptyStatement BodyStatement
395   |     `-';'
396   `-'}' CloseParen
397 )txt"}));
398 }
399 
400 TEST_P(BuildSyntaxTreeTest, While) {
401   EXPECT_TRUE(treeDumpEqualOnAnnotations(
402       R"cpp(
403 void test() {
404   [[while (1) { continue; break; }]]
405 }
406 )cpp",
407       {R"txt(
408 WhileStatement Statement
409 |-'while' IntroducerKeyword
410 |-'('
411 |-IntegerLiteralExpression
412 | `-'1' LiteralToken
413 |-')'
414 `-CompoundStatement BodyStatement
415   |-'{' OpenParen
416   |-ContinueStatement Statement
417   | |-'continue' IntroducerKeyword
418   | `-';'
419   |-BreakStatement Statement
420   | |-'break' IntroducerKeyword
421   | `-';'
422   `-'}' CloseParen
423 )txt"}));
424 }
425 
426 TEST_P(BuildSyntaxTreeTest, UnhandledStatement) {
427   // Unhandled statements should end up as 'unknown statement'.
428   // This example uses a 'label statement', which does not yet have a syntax
429   // counterpart.
430   EXPECT_TRUE(treeDumpEqualOnAnnotations(
431       R"cpp(
432 int test() {
433   [[foo: return 100;]]
434 }
435 )cpp",
436       {R"txt(
437 UnknownStatement Statement
438 |-'foo'
439 |-':'
440 `-ReturnStatement
441   |-'return' IntroducerKeyword
442   |-IntegerLiteralExpression ReturnValue
443   | `-'100' LiteralToken
444   `-';'
445 )txt"}));
446 }
447 
448 TEST_P(BuildSyntaxTreeTest, Expressions) {
449   // expressions should be wrapped in 'ExpressionStatement' when they appear
450   // in a statement position.
451   EXPECT_TRUE(treeDumpEqual(
452       R"cpp(
453 void test() {
454   test();
455   if (1) test(); else test();
456 }
457 )cpp",
458       R"txt(
459 TranslationUnit Detached
460 `-SimpleDeclaration
461   |-'void'
462   |-DeclaratorList Declarators
463   | `-SimpleDeclarator ListElement
464   |   |-'test'
465   |   `-ParametersAndQualifiers
466   |     |-'(' OpenParen
467   |     `-')' CloseParen
468   `-CompoundStatement
469     |-'{' OpenParen
470     |-ExpressionStatement Statement
471     | |-CallExpression Expression
472     | | |-IdExpression Callee
473     | | | `-UnqualifiedId UnqualifiedId
474     | | |   `-'test'
475     | | |-'(' OpenParen
476     | | `-')' CloseParen
477     | `-';'
478     |-IfStatement Statement
479     | |-'if' IntroducerKeyword
480     | |-'('
481     | |-ExpressionStatement Condition
482     | | `-IntegerLiteralExpression Expression
483     | |   `-'1' LiteralToken
484     | |-')'
485     | |-ExpressionStatement ThenStatement
486     | | |-CallExpression Expression
487     | | | |-IdExpression Callee
488     | | | | `-UnqualifiedId UnqualifiedId
489     | | | |   `-'test'
490     | | | |-'(' OpenParen
491     | | | `-')' CloseParen
492     | | `-';'
493     | |-'else' ElseKeyword
494     | `-ExpressionStatement ElseStatement
495     |   |-CallExpression Expression
496     |   | |-IdExpression Callee
497     |   | | `-UnqualifiedId UnqualifiedId
498     |   | |   `-'test'
499     |   | |-'(' OpenParen
500     |   | `-')' CloseParen
501     |   `-';'
502     `-'}' CloseParen
503 )txt"));
504 }
505 
506 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_Identifier) {
507   EXPECT_TRUE(treeDumpEqualOnAnnotations(
508       R"cpp(
509 void test(int a) {
510   [[a]];
511 }
512 )cpp",
513       {R"txt(
514 IdExpression Expression
515 `-UnqualifiedId UnqualifiedId
516   `-'a'
517 )txt"}));
518 }
519 
520 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_OperatorFunctionId) {
521   if (!GetParam().isCXX()) {
522     return;
523   }
524   EXPECT_TRUE(treeDumpEqualOnAnnotations(
525       R"cpp(
526 struct X {
527   friend X operator+(const X&, const X&);
528 };
529 void test(X x) {
530   [[operator+(x, x)]];
531 }
532 )cpp",
533       {R"txt(
534 CallExpression Expression
535 |-IdExpression Callee
536 | `-UnqualifiedId UnqualifiedId
537 |   |-'operator'
538 |   `-'+'
539 |-'(' OpenParen
540 |-CallArguments Arguments
541 | |-IdExpression ListElement
542 | | `-UnqualifiedId UnqualifiedId
543 | |   `-'x'
544 | |-',' ListDelimiter
545 | `-IdExpression ListElement
546 |   `-UnqualifiedId UnqualifiedId
547 |     `-'x'
548 `-')' CloseParen
549 )txt"}));
550 }
551 
552 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_ConversionFunctionId) {
553   if (!GetParam().isCXX()) {
554     return;
555   }
556   EXPECT_TRUE(treeDumpEqualOnAnnotations(
557       R"cpp(
558 struct X {
559   operator int();
560 };
561 void test(X x) {
562   [[x.operator int()]];
563 }
564 )cpp",
565       {R"txt(
566 CallExpression Expression
567 |-MemberExpression Callee
568 | |-IdExpression Object
569 | | `-UnqualifiedId UnqualifiedId
570 | |   `-'x'
571 | |-'.' AccessToken
572 | `-IdExpression Member
573 |   `-UnqualifiedId UnqualifiedId
574 |     |-'operator'
575 |     `-'int'
576 |-'(' OpenParen
577 `-')' CloseParen
578 )txt"}));
579 }
580 
581 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_LiteralOperatorId) {
582   if (!GetParam().isCXX11OrLater()) {
583     return;
584   }
585   EXPECT_TRUE(treeDumpEqualOnAnnotations(
586       R"cpp(
587 unsigned operator "" _w(char);
588 void test() {
589   [[operator "" _w('1')]];
590 }
591 )cpp",
592       {R"txt(
593 CallExpression Expression
594 |-IdExpression Callee
595 | `-UnqualifiedId UnqualifiedId
596 |   |-'operator'
597 |   |-'""'
598 |   `-'_w'
599 |-'(' OpenParen
600 |-CallArguments Arguments
601 | `-CharacterLiteralExpression ListElement
602 |   `-''1'' LiteralToken
603 `-')' CloseParen
604 )txt"}));
605 }
606 
607 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_Destructor) {
608   if (!GetParam().isCXX()) {
609     return;
610   }
611   EXPECT_TRUE(treeDumpEqualOnAnnotations(
612       R"cpp(
613 struct X { };
614 void test(X x) {
615   [[x.~X()]];
616 }
617 )cpp",
618       {R"txt(
619 CallExpression Expression
620 |-MemberExpression Callee
621 | |-IdExpression Object
622 | | `-UnqualifiedId UnqualifiedId
623 | |   `-'x'
624 | |-'.' AccessToken
625 | `-IdExpression Member
626 |   `-UnqualifiedId UnqualifiedId
627 |     |-'~'
628 |     `-'X'
629 |-'(' OpenParen
630 `-')' CloseParen
631 )txt"}));
632 }
633 
634 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_DecltypeDestructor) {
635   if (!GetParam().isCXX11OrLater()) {
636     return;
637   }
638   EXPECT_TRUE(treeDumpEqualOnAnnotations(
639       R"cpp(
640 struct X { };
641 void test(X x) {
642   // FIXME: Make `decltype(x)` a child of `MemberExpression`. It is currently
643   // not because `Expr::getSourceRange()` returns the range of `x.~` for the
644   // `MemberExpr` instead of the expected `x.~decltype(x)`, this is a bug in
645   // clang.
646   [[x.~decltype(x)()]];
647 }
648 )cpp",
649       {R"txt(
650 CallExpression Expression
651 |-MemberExpression Callee
652 | |-IdExpression Object
653 | | `-UnqualifiedId UnqualifiedId
654 | |   `-'x'
655 | |-'.' AccessToken
656 | `-IdExpression Member
657 |   `-UnqualifiedId UnqualifiedId
658 |     `-'~'
659 |-'decltype'
660 |-'('
661 |-'x'
662 |-')'
663 |-'('
664 `-')' CloseParen
665 )txt"}));
666 }
667 
668 TEST_P(BuildSyntaxTreeTest, UnqualifiedId_TemplateId) {
669   if (!GetParam().isCXX()) {
670     return;
671   }
672   EXPECT_TRUE(treeDumpEqualOnAnnotations(
673       R"cpp(
674 template<typename T>
675 T f();
676 void test() {
677   [[f<int>()]];
678 }
679 )cpp",
680       {R"txt(
681 CallExpression Expression
682 |-IdExpression Callee
683 | `-UnqualifiedId UnqualifiedId
684 |   |-'f'
685 |   |-'<'
686 |   |-'int'
687 |   `-'>'
688 |-'(' OpenParen
689 `-')' CloseParen
690 )txt"}));
691 }
692 
693 TEST_P(BuildSyntaxTreeTest, QualifiedId_NamespaceSpecifier) {
694   if (!GetParam().isCXX()) {
695     return;
696   }
697   EXPECT_TRUE(treeDumpEqualOnAnnotations(
698       R"cpp(
699 namespace n {
700   struct S { };
701 }
702 void test() {
703   [[::n::S s1]];
704   [[n::S s2]];
705 }
706 )cpp",
707       {R"txt(
708 SimpleDeclaration
709 |-NestedNameSpecifier
710 | |-'::' ListDelimiter
711 | |-IdentifierNameSpecifier ListElement
712 | | `-'n'
713 | `-'::' ListDelimiter
714 |-'S'
715 `-DeclaratorList Declarators
716   `-SimpleDeclarator ListElement
717     `-'s1'
718 )txt",
719        R"txt(
720 SimpleDeclaration
721 |-NestedNameSpecifier
722 | |-IdentifierNameSpecifier ListElement
723 | | `-'n'
724 | `-'::' ListDelimiter
725 |-'S'
726 `-DeclaratorList Declarators
727   `-SimpleDeclarator ListElement
728     `-'s2'
729 )txt"}));
730 }
731 
732 TEST_P(BuildSyntaxTreeTest, QualifiedId_TemplateSpecifier) {
733   if (!GetParam().isCXX()) {
734     return;
735   }
736   EXPECT_TRUE(treeDumpEqualOnAnnotations(
737       R"cpp(
738 template<typename T>
739 struct ST {
740   struct S { };
741 };
742 void test() {
743   [[::template ST<int>::S s1]];
744   [[::ST<int>::S s2]];
745 }
746 )cpp",
747       {R"txt(
748 SimpleDeclaration
749 |-NestedNameSpecifier
750 | |-'::' ListDelimiter
751 | |-SimpleTemplateNameSpecifier ListElement
752 | | |-'template'
753 | | |-'ST'
754 | | |-'<'
755 | | |-'int'
756 | | `-'>'
757 | `-'::' ListDelimiter
758 |-'S'
759 `-DeclaratorList Declarators
760   `-SimpleDeclarator ListElement
761     `-'s1'
762 )txt",
763        R"txt(
764 SimpleDeclaration
765 |-NestedNameSpecifier
766 | |-'::' ListDelimiter
767 | |-SimpleTemplateNameSpecifier ListElement
768 | | |-'ST'
769 | | |-'<'
770 | | |-'int'
771 | | `-'>'
772 | `-'::' ListDelimiter
773 |-'S'
774 `-DeclaratorList Declarators
775   `-SimpleDeclarator ListElement
776     `-'s2'
777 )txt"}));
778 }
779 
780 TEST_P(BuildSyntaxTreeTest, QualifiedId_DecltypeSpecifier) {
781   if (!GetParam().isCXX11OrLater()) {
782     return;
783   }
784   EXPECT_TRUE(treeDumpEqualOnAnnotations(
785       R"cpp(
786 struct S {
787   static void f(){}
788 };
789 void test(S s) {
790   [[decltype(s)::f()]];
791 }
792 )cpp",
793       {R"txt(
794 CallExpression Expression
795 |-IdExpression Callee
796 | |-NestedNameSpecifier Qualifier
797 | | |-DecltypeNameSpecifier ListElement
798 | | | |-'decltype'
799 | | | |-'('
800 | | | |-IdExpression
801 | | | | `-UnqualifiedId UnqualifiedId
802 | | | |   `-'s'
803 | | | `-')'
804 | | `-'::' ListDelimiter
805 | `-UnqualifiedId UnqualifiedId
806 |   `-'f'
807 |-'(' OpenParen
808 `-')' CloseParen
809 )txt"}));
810 }
811 
812 TEST_P(BuildSyntaxTreeTest, QualifiedId_OptionalTemplateKw) {
813   if (!GetParam().isCXX()) {
814     return;
815   }
816   EXPECT_TRUE(treeDumpEqualOnAnnotations(
817       R"cpp(
818 struct S {
819   template<typename U>
820   static U f();
821 };
822 void test() {
823   [[S::f<int>()]];
824   [[S::template f<int>()]];
825 }
826 )cpp",
827       {R"txt(
828 CallExpression Expression
829 |-IdExpression Callee
830 | |-NestedNameSpecifier Qualifier
831 | | |-IdentifierNameSpecifier ListElement
832 | | | `-'S'
833 | | `-'::' ListDelimiter
834 | `-UnqualifiedId UnqualifiedId
835 |   |-'f'
836 |   |-'<'
837 |   |-'int'
838 |   `-'>'
839 |-'(' OpenParen
840 `-')' CloseParen
841 )txt",
842        R"txt(
843 CallExpression Expression
844 |-IdExpression Callee
845 | |-NestedNameSpecifier Qualifier
846 | | |-IdentifierNameSpecifier ListElement
847 | | | `-'S'
848 | | `-'::' ListDelimiter
849 | |-'template' TemplateKeyword
850 | `-UnqualifiedId UnqualifiedId
851 |   |-'f'
852 |   |-'<'
853 |   |-'int'
854 |   `-'>'
855 |-'(' OpenParen
856 `-')' CloseParen
857 )txt"}));
858 }
859 
860 TEST_P(BuildSyntaxTreeTest, QualifiedId_Complex) {
861   if (!GetParam().isCXX()) {
862     return;
863   }
864   EXPECT_TRUE(treeDumpEqualOnAnnotations(
865       R"cpp(
866 namespace n {
867   template<typename T>
868   struct ST {
869     template<typename U>
870     static U f();
871   };
872 }
873 void test() {
874   [[::n::template ST<int>::template f<int>()]];
875 }
876 )cpp",
877       {R"txt(
878 CallExpression Expression
879 |-IdExpression Callee
880 | |-NestedNameSpecifier Qualifier
881 | | |-'::' ListDelimiter
882 | | |-IdentifierNameSpecifier ListElement
883 | | | `-'n'
884 | | |-'::' ListDelimiter
885 | | |-SimpleTemplateNameSpecifier ListElement
886 | | | |-'template'
887 | | | |-'ST'
888 | | | |-'<'
889 | | | |-'int'
890 | | | `-'>'
891 | | `-'::' ListDelimiter
892 | |-'template' TemplateKeyword
893 | `-UnqualifiedId UnqualifiedId
894 |   |-'f'
895 |   |-'<'
896 |   |-'int'
897 |   `-'>'
898 |-'(' OpenParen
899 `-')' CloseParen
900 )txt"}));
901 }
902 
903 TEST_P(BuildSyntaxTreeTest, QualifiedId_DependentType) {
904   if (!GetParam().isCXX()) {
905     return;
906   }
907   if (GetParam().hasDelayedTemplateParsing()) {
908     // FIXME: Make this test work on Windows by generating the expected syntax
909     // tree when `-fdelayed-template-parsing` is active.
910     return;
911   }
912   EXPECT_TRUE(treeDumpEqualOnAnnotations(
913       R"cpp(
914 template <typename T>
915 void test() {
916   [[T::template U<int>::f()]];
917   [[T::U::f()]];
918   [[T::template f<0>()]];
919 }
920 )cpp",
921       {R"txt(
922 CallExpression Expression
923 |-IdExpression Callee
924 | |-NestedNameSpecifier Qualifier
925 | | |-IdentifierNameSpecifier ListElement
926 | | | `-'T'
927 | | |-'::' ListDelimiter
928 | | |-SimpleTemplateNameSpecifier ListElement
929 | | | |-'template'
930 | | | |-'U'
931 | | | |-'<'
932 | | | |-'int'
933 | | | `-'>'
934 | | `-'::' ListDelimiter
935 | `-UnqualifiedId UnqualifiedId
936 |   `-'f'
937 |-'(' OpenParen
938 `-')' CloseParen
939 )txt",
940        R"txt(
941 CallExpression Expression
942 |-IdExpression Callee
943 | |-NestedNameSpecifier Qualifier
944 | | |-IdentifierNameSpecifier ListElement
945 | | | `-'T'
946 | | |-'::' ListDelimiter
947 | | |-IdentifierNameSpecifier ListElement
948 | | | `-'U'
949 | | `-'::' ListDelimiter
950 | `-UnqualifiedId UnqualifiedId
951 |   `-'f'
952 |-'(' OpenParen
953 `-')' CloseParen
954 )txt",
955        R"txt(
956 CallExpression Expression
957 |-IdExpression Callee
958 | |-NestedNameSpecifier Qualifier
959 | | |-IdentifierNameSpecifier ListElement
960 | | | `-'T'
961 | | `-'::' ListDelimiter
962 | |-'template' TemplateKeyword
963 | `-UnqualifiedId UnqualifiedId
964 |   |-'f'
965 |   |-'<'
966 |   |-IntegerLiteralExpression
967 |   | `-'0' LiteralToken
968 |   `-'>'
969 |-'(' OpenParen
970 `-')' CloseParen
971 )txt"}));
972 }
973 
974 TEST_P(BuildSyntaxTreeTest, This_Simple) {
975   if (!GetParam().isCXX()) {
976     return;
977   }
978   EXPECT_TRUE(treeDumpEqualOnAnnotations(
979       R"cpp(
980 struct S {
981   S* test(){
982     return [[this]];
983   }
984 };
985 )cpp",
986       {R"txt(
987 ThisExpression ReturnValue
988 `-'this' IntroducerKeyword
989 )txt"}));
990 }
991 
992 TEST_P(BuildSyntaxTreeTest, This_ExplicitMemberAccess) {
993   if (!GetParam().isCXX()) {
994     return;
995   }
996   EXPECT_TRUE(treeDumpEqualOnAnnotations(
997       R"cpp(
998 struct S {
999   int a;
1000   void test(){
1001     [[this->a]];
1002   }
1003 };
1004 )cpp",
1005       {R"txt(
1006 MemberExpression Expression
1007 |-ThisExpression Object
1008 | `-'this' IntroducerKeyword
1009 |-'->' AccessToken
1010 `-IdExpression Member
1011   `-UnqualifiedId UnqualifiedId
1012     `-'a'
1013 )txt"}));
1014 }
1015 
1016 TEST_P(BuildSyntaxTreeTest, This_ImplicitMemberAccess) {
1017   if (!GetParam().isCXX()) {
1018     return;
1019   }
1020   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1021       R"cpp(
1022 struct S {
1023   int a;
1024   void test(){
1025     [[a]];
1026   }
1027 };
1028 )cpp",
1029       {R"txt(
1030 IdExpression Expression
1031 `-UnqualifiedId UnqualifiedId
1032   `-'a'
1033 )txt"}));
1034 }
1035 
1036 TEST_P(BuildSyntaxTreeTest, ParenExpr) {
1037   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1038       R"cpp(
1039 void test() {
1040   [[(1)]];
1041   [[((1))]];
1042   [[(1 + (2))]];
1043 }
1044 )cpp",
1045       {R"txt(
1046 ParenExpression Expression
1047 |-'(' OpenParen
1048 |-IntegerLiteralExpression SubExpression
1049 | `-'1' LiteralToken
1050 `-')' CloseParen
1051 )txt",
1052        R"txt(
1053 ParenExpression Expression
1054 |-'(' OpenParen
1055 |-ParenExpression SubExpression
1056 | |-'(' OpenParen
1057 | |-IntegerLiteralExpression SubExpression
1058 | | `-'1' LiteralToken
1059 | `-')' CloseParen
1060 `-')' CloseParen
1061 )txt",
1062        R"txt(
1063 ParenExpression Expression
1064 |-'(' OpenParen
1065 |-BinaryOperatorExpression SubExpression
1066 | |-IntegerLiteralExpression LeftHandSide
1067 | | `-'1' LiteralToken
1068 | |-'+' OperatorToken
1069 | `-ParenExpression RightHandSide
1070 |   |-'(' OpenParen
1071 |   |-IntegerLiteralExpression SubExpression
1072 |   | `-'2' LiteralToken
1073 |   `-')' CloseParen
1074 `-')' CloseParen
1075 )txt"}));
1076 }
1077 
1078 TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Char) {
1079   if (!GetParam().isCXX11OrLater()) {
1080     return;
1081   }
1082   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1083       R"cpp(
1084 unsigned operator "" _c(char);
1085 void test() {
1086   [['2'_c]];
1087 }
1088     )cpp",
1089       {R"txt(
1090 CharUserDefinedLiteralExpression Expression
1091 `-''2'_c' LiteralToken
1092 )txt"}));
1093 }
1094 
1095 TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_String) {
1096   if (!GetParam().isCXX11OrLater()) {
1097     return;
1098   }
1099   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1100       R"cpp(
1101 typedef decltype(sizeof(void *)) size_t;
1102 
1103 unsigned operator "" _s(const char*, size_t);
1104 
1105 void test() {
1106   [["12"_s]];
1107 }
1108     )cpp",
1109       {R"txt(
1110 StringUserDefinedLiteralExpression Expression
1111 `-'"12"_s' LiteralToken
1112 )txt"}));
1113 }
1114 
1115 TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Integer) {
1116   if (!GetParam().isCXX11OrLater()) {
1117     return;
1118   }
1119   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1120       R"cpp(
1121 unsigned operator "" _i(unsigned long long);
1122 unsigned operator "" _r(const char*);
1123 template <char...>
1124 unsigned operator "" _t();
1125 
1126 void test() {
1127   [[12_i]];
1128   [[12_r]];
1129   [[12_t]];
1130 }
1131     )cpp",
1132       {R"txt(
1133 IntegerUserDefinedLiteralExpression Expression
1134 `-'12_i' LiteralToken
1135 )txt",
1136        R"txt(
1137 IntegerUserDefinedLiteralExpression Expression
1138 `-'12_r' LiteralToken
1139 )txt",
1140        R"txt(
1141 IntegerUserDefinedLiteralExpression Expression
1142 `-'12_t' LiteralToken
1143 )txt"}));
1144 }
1145 
1146 TEST_P(BuildSyntaxTreeTest, UserDefinedLiteral_Float) {
1147   if (!GetParam().isCXX11OrLater()) {
1148     return;
1149   }
1150   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1151       R"cpp(
1152 unsigned operator "" _f(long double);
1153 unsigned operator "" _r(const char*);
1154 template <char...>
1155 unsigned operator "" _t();
1156 
1157 void test() {
1158   [[1.2_f]];
1159   [[1.2_r]];
1160   [[1.2_t]];
1161 }
1162     )cpp",
1163       {R"txt(
1164 FloatUserDefinedLiteralExpression Expression
1165 `-'1.2_f' LiteralToken
1166 )txt",
1167        R"txt(
1168 FloatUserDefinedLiteralExpression Expression
1169 `-'1.2_r' LiteralToken
1170 )txt",
1171        R"txt(
1172 FloatUserDefinedLiteralExpression Expression
1173 `-'1.2_t' LiteralToken
1174 )txt"}));
1175 }
1176 
1177 TEST_P(BuildSyntaxTreeTest, IntegerLiteral_LongLong) {
1178   if (!GetParam().isCXX11OrLater()) {
1179     return;
1180   }
1181   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1182       R"cpp(
1183 void test() {
1184   [[12ll]];
1185   [[12ull]];
1186 }
1187 )cpp",
1188       {R"txt(
1189 IntegerLiteralExpression Expression
1190 `-'12ll' LiteralToken
1191 )txt",
1192        R"txt(
1193 IntegerLiteralExpression Expression
1194 `-'12ull' LiteralToken
1195 )txt"}));
1196 }
1197 
1198 TEST_P(BuildSyntaxTreeTest, IntegerLiteral_Binary) {
1199   if (!GetParam().isCXX14OrLater()) {
1200     return;
1201   }
1202   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1203       R"cpp(
1204 void test() {
1205   [[0b1100]];
1206 }
1207 )cpp",
1208       {R"txt(
1209 IntegerLiteralExpression Expression
1210 `-'0b1100' LiteralToken
1211 )txt"}));
1212 }
1213 
1214 TEST_P(BuildSyntaxTreeTest, IntegerLiteral_WithDigitSeparators) {
1215   if (!GetParam().isCXX14OrLater()) {
1216     return;
1217   }
1218   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1219       R"cpp(
1220 void test() {
1221   [[1'2'0ull]];
1222 }
1223 )cpp",
1224       {R"txt(
1225 IntegerLiteralExpression Expression
1226 `-'1'2'0ull' LiteralToken
1227 )txt"}));
1228 }
1229 
1230 TEST_P(BuildSyntaxTreeTest, CharacterLiteral) {
1231   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1232       R"cpp(
1233 void test() {
1234   [['a']];
1235   [['\n']];
1236   [['\x20']];
1237   [['\0']];
1238   [[L'a']];
1239   [[L'α']];
1240 }
1241 )cpp",
1242       {R"txt(
1243 CharacterLiteralExpression Expression
1244 `-''a'' LiteralToken
1245 )txt",
1246        R"txt(
1247 CharacterLiteralExpression Expression
1248 `-''\n'' LiteralToken
1249 )txt",
1250        R"txt(
1251 CharacterLiteralExpression Expression
1252 `-''\x20'' LiteralToken
1253 )txt",
1254        R"txt(
1255 CharacterLiteralExpression Expression
1256 `-''\0'' LiteralToken
1257 )txt",
1258        R"txt(
1259 CharacterLiteralExpression Expression
1260 `-'L'a'' LiteralToken
1261 )txt",
1262        R"txt(
1263 CharacterLiteralExpression Expression
1264 `-'L'α'' LiteralToken
1265 )txt"}));
1266 }
1267 
1268 TEST_P(BuildSyntaxTreeTest, CharacterLiteral_Utf) {
1269   if (!GetParam().isCXX11OrLater()) {
1270     return;
1271   }
1272   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1273       R"cpp(
1274 void test() {
1275   [[u'a']];
1276   [[u'構']];
1277   [[U'a']];
1278   [[U'��']];
1279 }
1280 )cpp",
1281       {R"txt(
1282 CharacterLiteralExpression Expression
1283 `-'u'a'' LiteralToken
1284 )txt",
1285        R"txt(
1286 CharacterLiteralExpression Expression
1287 `-'u'構'' LiteralToken
1288 )txt",
1289        R"txt(
1290 CharacterLiteralExpression Expression
1291 `-'U'a'' LiteralToken
1292 )txt",
1293        R"txt(
1294 CharacterLiteralExpression Expression
1295 `-'U'��'' LiteralToken
1296 )txt"}));
1297 }
1298 
1299 TEST_P(BuildSyntaxTreeTest, CharacterLiteral_Utf8) {
1300   if (!GetParam().isCXX17OrLater()) {
1301     return;
1302   }
1303   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1304       R"cpp(
1305 void test() {
1306   [[u8'a']];
1307   [[u8'\x7f']];
1308 }
1309 )cpp",
1310       {R"txt(
1311 CharacterLiteralExpression Expression
1312 `-'u8'a'' LiteralToken
1313 )txt",
1314        R"txt(
1315 CharacterLiteralExpression Expression
1316 `-'u8'\x7f'' LiteralToken
1317 )txt"}));
1318 }
1319 
1320 TEST_P(BuildSyntaxTreeTest, FloatingLiteral) {
1321   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1322       R"cpp(
1323 void test() {
1324   [[1e-2]];
1325   [[2.]];
1326   [[.2]];
1327   [[2.f]];
1328 }
1329 )cpp",
1330       {R"txt(
1331 FloatingLiteralExpression Expression
1332 `-'1e-2' LiteralToken
1333 )txt",
1334        R"txt(
1335 FloatingLiteralExpression Expression
1336 `-'2.' LiteralToken
1337 )txt",
1338        R"txt(
1339 FloatingLiteralExpression Expression
1340 `-'.2' LiteralToken
1341 )txt",
1342        R"txt(
1343 FloatingLiteralExpression Expression
1344 `-'2.f' LiteralToken
1345 )txt"}));
1346 }
1347 
1348 TEST_P(BuildSyntaxTreeTest, FloatingLiteral_Hexadecimal) {
1349   if (!GetParam().isCXX17OrLater()) {
1350     return;
1351   }
1352   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1353       R"cpp(
1354 void test() {
1355   [[0xfp1]];
1356   [[0xf.p1]];
1357   [[0x.fp1]];
1358   [[0xf.fp1f]];
1359 }
1360 )cpp",
1361       {R"txt(
1362 FloatingLiteralExpression Expression
1363 `-'0xfp1' LiteralToken
1364 )txt",
1365        R"txt(
1366 FloatingLiteralExpression Expression
1367 `-'0xf.p1' LiteralToken
1368 )txt",
1369        R"txt(
1370 FloatingLiteralExpression Expression
1371 `-'0x.fp1' LiteralToken
1372 )txt",
1373        R"txt(
1374 FloatingLiteralExpression Expression
1375 `-'0xf.fp1f' LiteralToken
1376 )txt"}));
1377 }
1378 
1379 TEST_P(BuildSyntaxTreeTest, StringLiteral) {
1380   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1381       R"cpp(
1382 void test() {
1383   [["a\n\0\x20"]];
1384   [[L"αβ"]];
1385 }
1386 )cpp",
1387       {R"txt(
1388 StringLiteralExpression Expression
1389 `-'"a\n\0\x20"' LiteralToken
1390 )txt",
1391        R"txt(
1392 StringLiteralExpression Expression
1393 `-'L"αβ"' LiteralToken
1394 )txt"}));
1395 }
1396 
1397 TEST_P(BuildSyntaxTreeTest, StringLiteral_Utf) {
1398   if (!GetParam().isCXX11OrLater()) {
1399     return;
1400   }
1401   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1402       R"cpp(
1403 void test() {
1404   [[u8"a\x1f\x05"]];
1405   [[u"C++抽象構文木"]];
1406   [[U"����\n"]];
1407 }
1408 )cpp",
1409       {R"txt(
1410 StringLiteralExpression Expression
1411 `-'u8"a\x1f\x05"' LiteralToken
1412 )txt",
1413        R"txt(
1414 StringLiteralExpression Expression
1415 `-'u"C++抽象構文木"' LiteralToken
1416 )txt",
1417        R"txt(
1418 StringLiteralExpression Expression
1419 `-'U"����\n"' LiteralToken
1420 )txt"}));
1421 }
1422 
1423 TEST_P(BuildSyntaxTreeTest, StringLiteral_Raw) {
1424   if (!GetParam().isCXX11OrLater()) {
1425     return;
1426   }
1427   // This test uses regular string literals instead of raw string literals to
1428   // hold source code and expected output because of a bug in MSVC up to MSVC
1429   // 2019 16.2:
1430   // https://developercommunity.visualstudio.com/content/problem/67300/stringifying-raw-string-literal.html
1431   EXPECT_TRUE(treeDumpEqual( //
1432       "void test() {\n"
1433       "  R\"SyntaxTree(\n"
1434       "  Hello \"Syntax\" \\\"\n"
1435       "  )SyntaxTree\";\n"
1436       "}\n",
1437       "TranslationUnit Detached\n"
1438       "`-SimpleDeclaration\n"
1439       "  |-'void'\n"
1440       "  |-DeclaratorList Declarators\n"
1441       "  | `-SimpleDeclarator ListElement\n"
1442       "  |   |-'test'\n"
1443       "  |   `-ParametersAndQualifiers\n"
1444       "  |     |-'(' OpenParen\n"
1445       "  |     `-')' CloseParen\n"
1446       "  `-CompoundStatement\n"
1447       "    |-'{' OpenParen\n"
1448       "    |-ExpressionStatement Statement\n"
1449       "    | |-StringLiteralExpression Expression\n"
1450       "    | | `-'R\"SyntaxTree(\n"
1451       "  Hello \"Syntax\" \\\"\n"
1452       "  )SyntaxTree\"' LiteralToken\n"
1453       "    | `-';'\n"
1454       "    `-'}' CloseParen\n"));
1455 }
1456 
1457 TEST_P(BuildSyntaxTreeTest, BoolLiteral) {
1458   if (GetParam().isC()) {
1459     return;
1460   }
1461   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1462       R"cpp(
1463 void test() {
1464   [[true]];
1465   [[false]];
1466 }
1467 )cpp",
1468       {R"txt(
1469 BoolLiteralExpression Expression
1470 `-'true' LiteralToken
1471 )txt",
1472        R"txt(
1473 BoolLiteralExpression Expression
1474 `-'false' LiteralToken
1475 )txt"}));
1476 }
1477 
1478 TEST_P(BuildSyntaxTreeTest, CxxNullPtrLiteral) {
1479   if (!GetParam().isCXX11OrLater()) {
1480     return;
1481   }
1482   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1483       R"cpp(
1484 void test() {
1485   [[nullptr]];
1486 }
1487 )cpp",
1488       {R"txt(
1489 CxxNullPtrExpression Expression
1490 `-'nullptr' LiteralToken
1491 )txt"}));
1492 }
1493 
1494 TEST_P(BuildSyntaxTreeTest, PostfixUnaryOperator) {
1495   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1496       R"cpp(
1497 void test(int a) {
1498   [[a++]];
1499   [[a--]];
1500 }
1501 )cpp",
1502       {R"txt(
1503 PostfixUnaryOperatorExpression Expression
1504 |-IdExpression Operand
1505 | `-UnqualifiedId UnqualifiedId
1506 |   `-'a'
1507 `-'++' OperatorToken
1508 )txt",
1509        R"txt(
1510 PostfixUnaryOperatorExpression Expression
1511 |-IdExpression Operand
1512 | `-UnqualifiedId UnqualifiedId
1513 |   `-'a'
1514 `-'--' OperatorToken
1515 )txt"}));
1516 }
1517 
1518 TEST_P(BuildSyntaxTreeTest, PrefixUnaryOperator) {
1519   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1520       R"cpp(
1521 void test(int a, int *ap) {
1522   [[--a]]; [[++a]];
1523   [[~a]];
1524   [[-a]];
1525   [[+a]];
1526   [[&a]];
1527   [[*ap]];
1528   [[!a]];
1529   [[__real a]]; [[__imag a]];
1530 }
1531 )cpp",
1532       {R"txt(
1533 PrefixUnaryOperatorExpression Expression
1534 |-'--' OperatorToken
1535 `-IdExpression Operand
1536   `-UnqualifiedId UnqualifiedId
1537     `-'a'
1538 )txt",
1539        R"txt(
1540 PrefixUnaryOperatorExpression Expression
1541 |-'++' OperatorToken
1542 `-IdExpression Operand
1543   `-UnqualifiedId UnqualifiedId
1544     `-'a'
1545 )txt",
1546        R"txt(
1547 PrefixUnaryOperatorExpression Expression
1548 |-'~' OperatorToken
1549 `-IdExpression Operand
1550   `-UnqualifiedId UnqualifiedId
1551     `-'a'
1552 )txt",
1553        R"txt(
1554 PrefixUnaryOperatorExpression Expression
1555 |-'-' OperatorToken
1556 `-IdExpression Operand
1557   `-UnqualifiedId UnqualifiedId
1558     `-'a'
1559 )txt",
1560        R"txt(
1561 PrefixUnaryOperatorExpression Expression
1562 |-'+' OperatorToken
1563 `-IdExpression Operand
1564   `-UnqualifiedId UnqualifiedId
1565     `-'a'
1566 )txt",
1567        R"txt(
1568 PrefixUnaryOperatorExpression Expression
1569 |-'&' OperatorToken
1570 `-IdExpression Operand
1571   `-UnqualifiedId UnqualifiedId
1572     `-'a'
1573 )txt",
1574        R"txt(
1575 PrefixUnaryOperatorExpression Expression
1576 |-'*' OperatorToken
1577 `-IdExpression Operand
1578   `-UnqualifiedId UnqualifiedId
1579     `-'ap'
1580 )txt",
1581        R"txt(
1582 PrefixUnaryOperatorExpression Expression
1583 |-'!' OperatorToken
1584 `-IdExpression Operand
1585   `-UnqualifiedId UnqualifiedId
1586     `-'a'
1587 )txt",
1588        R"txt(
1589 PrefixUnaryOperatorExpression Expression
1590 |-'__real' OperatorToken
1591 `-IdExpression Operand
1592   `-UnqualifiedId UnqualifiedId
1593     `-'a'
1594 )txt",
1595        R"txt(
1596 PrefixUnaryOperatorExpression Expression
1597 |-'__imag' OperatorToken
1598 `-IdExpression Operand
1599   `-UnqualifiedId UnqualifiedId
1600     `-'a'
1601 )txt"}));
1602 }
1603 
1604 TEST_P(BuildSyntaxTreeTest, PrefixUnaryOperatorCxx) {
1605   if (!GetParam().isCXX()) {
1606     return;
1607   }
1608   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1609       R"cpp(
1610 void test(int a, bool b) {
1611   [[compl a]];
1612   [[not b]];
1613 }
1614 )cpp",
1615       {R"txt(
1616 PrefixUnaryOperatorExpression Expression
1617 |-'compl' OperatorToken
1618 `-IdExpression Operand
1619   `-UnqualifiedId UnqualifiedId
1620     `-'a'
1621 )txt",
1622        R"txt(
1623 PrefixUnaryOperatorExpression Expression
1624 |-'not' OperatorToken
1625 `-IdExpression Operand
1626   `-UnqualifiedId UnqualifiedId
1627     `-'b'
1628 )txt"}));
1629 }
1630 
1631 TEST_P(BuildSyntaxTreeTest, BinaryOperator) {
1632   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1633       R"cpp(
1634 void test(int a) {
1635   [[1 - 2]];
1636   [[1 == 2]];
1637   [[a = 1]];
1638   [[a <<= 1]];
1639   [[1 || 0]];
1640   [[1 & 2]];
1641   [[a != 3]];
1642 }
1643 )cpp",
1644       {R"txt(
1645 BinaryOperatorExpression Expression
1646 |-IntegerLiteralExpression LeftHandSide
1647 | `-'1' LiteralToken
1648 |-'-' OperatorToken
1649 `-IntegerLiteralExpression RightHandSide
1650   `-'2' LiteralToken
1651 )txt",
1652        R"txt(
1653 BinaryOperatorExpression Expression
1654 |-IntegerLiteralExpression LeftHandSide
1655 | `-'1' LiteralToken
1656 |-'==' OperatorToken
1657 `-IntegerLiteralExpression RightHandSide
1658   `-'2' LiteralToken
1659 )txt",
1660        R"txt(
1661 BinaryOperatorExpression Expression
1662 |-IdExpression LeftHandSide
1663 | `-UnqualifiedId UnqualifiedId
1664 |   `-'a'
1665 |-'=' OperatorToken
1666 `-IntegerLiteralExpression RightHandSide
1667   `-'1' LiteralToken
1668 )txt",
1669        R"txt(
1670 BinaryOperatorExpression Expression
1671 |-IdExpression LeftHandSide
1672 | `-UnqualifiedId UnqualifiedId
1673 |   `-'a'
1674 |-'<<=' OperatorToken
1675 `-IntegerLiteralExpression RightHandSide
1676   `-'1' LiteralToken
1677 )txt",
1678        R"txt(
1679 BinaryOperatorExpression Expression
1680 |-IntegerLiteralExpression LeftHandSide
1681 | `-'1' LiteralToken
1682 |-'||' OperatorToken
1683 `-IntegerLiteralExpression RightHandSide
1684   `-'0' LiteralToken
1685 )txt",
1686        R"txt(
1687 BinaryOperatorExpression Expression
1688 |-IntegerLiteralExpression LeftHandSide
1689 | `-'1' LiteralToken
1690 |-'&' OperatorToken
1691 `-IntegerLiteralExpression RightHandSide
1692   `-'2' LiteralToken
1693 )txt",
1694        R"txt(
1695 BinaryOperatorExpression Expression
1696 |-IdExpression LeftHandSide
1697 | `-UnqualifiedId UnqualifiedId
1698 |   `-'a'
1699 |-'!=' OperatorToken
1700 `-IntegerLiteralExpression RightHandSide
1701   `-'3' LiteralToken
1702 )txt"}));
1703 }
1704 
1705 TEST_P(BuildSyntaxTreeTest, BinaryOperatorCxx) {
1706   if (!GetParam().isCXX()) {
1707     return;
1708   }
1709   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1710       R"cpp(
1711 void test(int a) {
1712   [[true || false]];
1713   [[true or false]];
1714   [[1 bitand 2]];
1715   [[a xor_eq 3]];
1716 }
1717 )cpp",
1718       {R"txt(
1719 BinaryOperatorExpression Expression
1720 |-BoolLiteralExpression LeftHandSide
1721 | `-'true' LiteralToken
1722 |-'||' OperatorToken
1723 `-BoolLiteralExpression RightHandSide
1724   `-'false' LiteralToken
1725 )txt",
1726        R"txt(
1727 BinaryOperatorExpression Expression
1728 |-BoolLiteralExpression LeftHandSide
1729 | `-'true' LiteralToken
1730 |-'or' OperatorToken
1731 `-BoolLiteralExpression RightHandSide
1732   `-'false' LiteralToken
1733 )txt",
1734        R"txt(
1735 BinaryOperatorExpression Expression
1736 |-IntegerLiteralExpression LeftHandSide
1737 | `-'1' LiteralToken
1738 |-'bitand' OperatorToken
1739 `-IntegerLiteralExpression RightHandSide
1740   `-'2' LiteralToken
1741 )txt",
1742        R"txt(
1743 BinaryOperatorExpression Expression
1744 |-IdExpression LeftHandSide
1745 | `-UnqualifiedId UnqualifiedId
1746 |   `-'a'
1747 |-'xor_eq' OperatorToken
1748 `-IntegerLiteralExpression RightHandSide
1749   `-'3' LiteralToken
1750 )txt"}));
1751 }
1752 
1753 TEST_P(BuildSyntaxTreeTest, BinaryOperator_NestedWithParenthesis) {
1754   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1755       R"cpp(
1756 void test() {
1757   [[(1 + 2) * (4 / 2)]];
1758 }
1759 )cpp",
1760       {R"txt(
1761 BinaryOperatorExpression Expression
1762 |-ParenExpression LeftHandSide
1763 | |-'(' OpenParen
1764 | |-BinaryOperatorExpression SubExpression
1765 | | |-IntegerLiteralExpression LeftHandSide
1766 | | | `-'1' LiteralToken
1767 | | |-'+' OperatorToken
1768 | | `-IntegerLiteralExpression RightHandSide
1769 | |   `-'2' LiteralToken
1770 | `-')' CloseParen
1771 |-'*' OperatorToken
1772 `-ParenExpression RightHandSide
1773   |-'(' OpenParen
1774   |-BinaryOperatorExpression SubExpression
1775   | |-IntegerLiteralExpression LeftHandSide
1776   | | `-'4' LiteralToken
1777   | |-'/' OperatorToken
1778   | `-IntegerLiteralExpression RightHandSide
1779   |   `-'2' LiteralToken
1780   `-')' CloseParen
1781 )txt"}));
1782 }
1783 
1784 TEST_P(BuildSyntaxTreeTest, BinaryOperator_Associativity) {
1785   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1786       R"cpp(
1787 void test(int a, int b) {
1788   [[a + b + 42]];
1789   [[a = b = 42]];
1790 }
1791 )cpp",
1792       {R"txt(
1793 BinaryOperatorExpression Expression
1794 |-BinaryOperatorExpression LeftHandSide
1795 | |-IdExpression LeftHandSide
1796 | | `-UnqualifiedId UnqualifiedId
1797 | |   `-'a'
1798 | |-'+' OperatorToken
1799 | `-IdExpression RightHandSide
1800 |   `-UnqualifiedId UnqualifiedId
1801 |     `-'b'
1802 |-'+' OperatorToken
1803 `-IntegerLiteralExpression RightHandSide
1804   `-'42' LiteralToken
1805 )txt",
1806        R"txt(
1807 BinaryOperatorExpression Expression
1808 |-IdExpression LeftHandSide
1809 | `-UnqualifiedId UnqualifiedId
1810 |   `-'a'
1811 |-'=' OperatorToken
1812 `-BinaryOperatorExpression RightHandSide
1813   |-IdExpression LeftHandSide
1814   | `-UnqualifiedId UnqualifiedId
1815   |   `-'b'
1816   |-'=' OperatorToken
1817   `-IntegerLiteralExpression RightHandSide
1818     `-'42' LiteralToken
1819 )txt"}));
1820 }
1821 
1822 TEST_P(BuildSyntaxTreeTest, BinaryOperator_Precedence) {
1823   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1824       R"cpp(
1825 void test() {
1826   [[1 + 2 * 3 + 4]];
1827   [[1 % 2 + 3 * 4]];
1828 }
1829 )cpp",
1830       {R"txt(
1831 BinaryOperatorExpression Expression
1832 |-BinaryOperatorExpression LeftHandSide
1833 | |-IntegerLiteralExpression LeftHandSide
1834 | | `-'1' LiteralToken
1835 | |-'+' OperatorToken
1836 | `-BinaryOperatorExpression RightHandSide
1837 |   |-IntegerLiteralExpression LeftHandSide
1838 |   | `-'2' LiteralToken
1839 |   |-'*' OperatorToken
1840 |   `-IntegerLiteralExpression RightHandSide
1841 |     `-'3' LiteralToken
1842 |-'+' OperatorToken
1843 `-IntegerLiteralExpression RightHandSide
1844   `-'4' LiteralToken
1845 )txt",
1846        R"txt(
1847 BinaryOperatorExpression Expression
1848 |-BinaryOperatorExpression LeftHandSide
1849 | |-IntegerLiteralExpression LeftHandSide
1850 | | `-'1' LiteralToken
1851 | |-'%' OperatorToken
1852 | `-IntegerLiteralExpression RightHandSide
1853 |   `-'2' LiteralToken
1854 |-'+' OperatorToken
1855 `-BinaryOperatorExpression RightHandSide
1856   |-IntegerLiteralExpression LeftHandSide
1857   | `-'3' LiteralToken
1858   |-'*' OperatorToken
1859   `-IntegerLiteralExpression RightHandSide
1860     `-'4' LiteralToken
1861 )txt"}));
1862 }
1863 
1864 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Assignment) {
1865   if (!GetParam().isCXX()) {
1866     return;
1867   }
1868   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1869       R"cpp(
1870 struct X {
1871   X& operator=(const X&);
1872 };
1873 void test(X x, X y) {
1874   [[x = y]];
1875 }
1876 )cpp",
1877       {R"txt(
1878 BinaryOperatorExpression Expression
1879 |-IdExpression LeftHandSide
1880 | `-UnqualifiedId UnqualifiedId
1881 |   `-'x'
1882 |-'=' OperatorToken
1883 `-IdExpression RightHandSide
1884   `-UnqualifiedId UnqualifiedId
1885     `-'y'
1886 )txt"}));
1887 }
1888 
1889 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Plus) {
1890   if (!GetParam().isCXX()) {
1891     return;
1892   }
1893   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1894       R"cpp(
1895 struct X {
1896   friend X operator+(X, const X&);
1897 };
1898 void test(X x, X y) {
1899   [[x + y]];
1900 }
1901 )cpp",
1902       {R"txt(
1903 BinaryOperatorExpression Expression
1904 |-IdExpression LeftHandSide
1905 | `-UnqualifiedId UnqualifiedId
1906 |   `-'x'
1907 |-'+' OperatorToken
1908 `-IdExpression RightHandSide
1909   `-UnqualifiedId UnqualifiedId
1910     `-'y'
1911 )txt"}));
1912 }
1913 
1914 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Less) {
1915   if (!GetParam().isCXX()) {
1916     return;
1917   }
1918   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1919       R"cpp(
1920 struct X {
1921   friend bool operator<(const X&, const X&);
1922 };
1923 void test(X x, X y) {
1924   [[x < y]];
1925 }
1926 )cpp",
1927       {R"txt(
1928 BinaryOperatorExpression Expression
1929 |-IdExpression LeftHandSide
1930 | `-UnqualifiedId UnqualifiedId
1931 |   `-'x'
1932 |-'<' OperatorToken
1933 `-IdExpression RightHandSide
1934   `-UnqualifiedId UnqualifiedId
1935     `-'y'
1936 )txt"}));
1937 }
1938 
1939 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_LeftShift) {
1940   if (!GetParam().isCXX()) {
1941     return;
1942   }
1943   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1944       R"cpp(
1945 struct X {
1946   friend X operator<<(X&, const X&);
1947 };
1948 void test(X x, X y) {
1949   [[x << y]];
1950 }
1951 )cpp",
1952       {R"txt(
1953 BinaryOperatorExpression Expression
1954 |-IdExpression LeftHandSide
1955 | `-UnqualifiedId UnqualifiedId
1956 |   `-'x'
1957 |-'<<' OperatorToken
1958 `-IdExpression RightHandSide
1959   `-UnqualifiedId UnqualifiedId
1960     `-'y'
1961 )txt"}));
1962 }
1963 
1964 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Comma) {
1965   if (!GetParam().isCXX()) {
1966     return;
1967   }
1968   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1969       R"cpp(
1970 struct X {
1971   X operator,(X&);
1972 };
1973 void test(X x, X y) {
1974   [[x, y]];
1975 }
1976 )cpp",
1977       {R"txt(
1978 BinaryOperatorExpression Expression
1979 |-IdExpression LeftHandSide
1980 | `-UnqualifiedId UnqualifiedId
1981 |   `-'x'
1982 |-',' OperatorToken
1983 `-IdExpression RightHandSide
1984   `-UnqualifiedId UnqualifiedId
1985     `-'y'
1986 )txt"}));
1987 }
1988 
1989 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PointerToMember) {
1990   if (!GetParam().isCXX()) {
1991     return;
1992   }
1993   EXPECT_TRUE(treeDumpEqualOnAnnotations(
1994       R"cpp(
1995 struct X {
1996   X operator->*(int);
1997 };
1998 void test(X* xp, int X::* pmi) {
1999   [[xp->*pmi]];
2000 }
2001 )cpp",
2002       {R"txt(
2003 BinaryOperatorExpression Expression
2004 |-IdExpression LeftHandSide
2005 | `-UnqualifiedId UnqualifiedId
2006 |   `-'xp'
2007 |-'->*' OperatorToken
2008 `-IdExpression RightHandSide
2009   `-UnqualifiedId UnqualifiedId
2010     `-'pmi'
2011 )txt"}));
2012 }
2013 
2014 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_Negation) {
2015   if (!GetParam().isCXX()) {
2016     return;
2017   }
2018   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2019       R"cpp(
2020 struct X {
2021   bool operator!();
2022 };
2023 void test(X x) {
2024   [[!x]];
2025 }
2026 )cpp",
2027       {R"txt(
2028 PrefixUnaryOperatorExpression Expression
2029 |-'!' OperatorToken
2030 `-IdExpression Operand
2031   `-UnqualifiedId UnqualifiedId
2032     `-'x'
2033 )txt"}));
2034 }
2035 
2036 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_AddressOf) {
2037   if (!GetParam().isCXX()) {
2038     return;
2039   }
2040   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2041       R"cpp(
2042 struct X {
2043   X* operator&();
2044 };
2045 void test(X x) {
2046   [[&x]];
2047 }
2048 )cpp",
2049       {R"txt(
2050 PrefixUnaryOperatorExpression Expression
2051 |-'&' OperatorToken
2052 `-IdExpression Operand
2053   `-UnqualifiedId UnqualifiedId
2054     `-'x'
2055 )txt"}));
2056 }
2057 
2058 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PrefixIncrement) {
2059   if (!GetParam().isCXX()) {
2060     return;
2061   }
2062   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2063       R"cpp(
2064 struct X {
2065   X operator++();
2066 };
2067 void test(X x) {
2068   [[++x]];
2069 }
2070 )cpp",
2071       {R"txt(
2072 PrefixUnaryOperatorExpression Expression
2073 |-'++' OperatorToken
2074 `-IdExpression Operand
2075   `-UnqualifiedId UnqualifiedId
2076     `-'x'
2077 )txt"}));
2078 }
2079 
2080 TEST_P(BuildSyntaxTreeTest, OverloadedOperator_PostfixIncrement) {
2081   if (!GetParam().isCXX()) {
2082     return;
2083   }
2084   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2085       R"cpp(
2086 struct X {
2087   X operator++(int);
2088 };
2089 void test(X x) {
2090   [[x++]];
2091 }
2092 )cpp",
2093       {R"txt(
2094 PostfixUnaryOperatorExpression Expression
2095 |-IdExpression Operand
2096 | `-UnqualifiedId UnqualifiedId
2097 |   `-'x'
2098 `-'++' OperatorToken
2099 )txt"}));
2100 }
2101 
2102 TEST_P(BuildSyntaxTreeTest, MemberExpression_SimpleWithDot) {
2103   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2104       R"cpp(
2105 struct S {
2106   int a;
2107 };
2108 void test(struct S s) {
2109   [[s.a]];
2110 }
2111 )cpp",
2112       {R"txt(
2113 MemberExpression Expression
2114 |-IdExpression Object
2115 | `-UnqualifiedId UnqualifiedId
2116 |   `-'s'
2117 |-'.' AccessToken
2118 `-IdExpression Member
2119   `-UnqualifiedId UnqualifiedId
2120     `-'a'
2121 )txt"}));
2122 }
2123 
2124 TEST_P(BuildSyntaxTreeTest, MemberExpression_StaticDataMember) {
2125   if (!GetParam().isCXX()) {
2126     return;
2127   }
2128   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2129       R"cpp(
2130 struct S {
2131   static int a;
2132 };
2133 void test(S s) {
2134   [[s.a]];
2135 }
2136 )cpp",
2137       {R"txt(
2138 MemberExpression Expression
2139 |-IdExpression Object
2140 | `-UnqualifiedId UnqualifiedId
2141 |   `-'s'
2142 |-'.' AccessToken
2143 `-IdExpression Member
2144   `-UnqualifiedId UnqualifiedId
2145     `-'a'
2146 )txt"}));
2147 }
2148 
2149 TEST_P(BuildSyntaxTreeTest, MemberExpression_SimpleWithArrow) {
2150   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2151       R"cpp(
2152 struct S {
2153   int a;
2154 };
2155 void test(struct S* sp) {
2156   [[sp->a]];
2157 }
2158 )cpp",
2159       {R"txt(
2160 MemberExpression Expression
2161 |-IdExpression Object
2162 | `-UnqualifiedId UnqualifiedId
2163 |   `-'sp'
2164 |-'->' AccessToken
2165 `-IdExpression Member
2166   `-UnqualifiedId UnqualifiedId
2167     `-'a'
2168 )txt"}));
2169 }
2170 
2171 TEST_P(BuildSyntaxTreeTest, MemberExpression_Chaining) {
2172   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2173       R"cpp(
2174 struct S {
2175   struct S* next;
2176 };
2177 void test(struct S s){
2178   [[s.next->next]];
2179 }
2180 )cpp",
2181       {R"txt(
2182 MemberExpression Expression
2183 |-MemberExpression Object
2184 | |-IdExpression Object
2185 | | `-UnqualifiedId UnqualifiedId
2186 | |   `-'s'
2187 | |-'.' AccessToken
2188 | `-IdExpression Member
2189 |   `-UnqualifiedId UnqualifiedId
2190 |     `-'next'
2191 |-'->' AccessToken
2192 `-IdExpression Member
2193   `-UnqualifiedId UnqualifiedId
2194     `-'next'
2195 )txt"}));
2196 }
2197 
2198 TEST_P(BuildSyntaxTreeTest, MemberExpression_OperatorFunction) {
2199   if (!GetParam().isCXX()) {
2200     return;
2201   }
2202   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2203       R"cpp(
2204 struct S {
2205   bool operator!();
2206 };
2207 void test(S s) {
2208   [[s.operator!()]];
2209 }
2210 )cpp",
2211       {R"txt(
2212 CallExpression Expression
2213 |-MemberExpression Callee
2214 | |-IdExpression Object
2215 | | `-UnqualifiedId UnqualifiedId
2216 | |   `-'s'
2217 | |-'.' AccessToken
2218 | `-IdExpression Member
2219 |   `-UnqualifiedId UnqualifiedId
2220 |     |-'operator'
2221 |     `-'!'
2222 |-'(' OpenParen
2223 `-')' CloseParen
2224 )txt"}));
2225 }
2226 
2227 TEST_P(BuildSyntaxTreeTest, MemberExpression_VariableTemplate) {
2228   if (!GetParam().isCXX14OrLater()) {
2229     return;
2230   }
2231   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2232       R"cpp(
2233 struct S {
2234   template<typename T>
2235   static constexpr T x = 42;
2236 };
2237 // FIXME: `<int>` should be a child of `MemberExpression` and `;` of
2238 // `ExpressionStatement`. This is a bug in clang, in `getSourceRange` methods.
2239 void test(S s) [[{
2240   s.x<int>;
2241 }]]
2242 )cpp",
2243       {R"txt(
2244 CompoundStatement
2245 |-'{' OpenParen
2246 |-ExpressionStatement Statement
2247 | `-MemberExpression Expression
2248 |   |-IdExpression Object
2249 |   | `-UnqualifiedId UnqualifiedId
2250 |   |   `-'s'
2251 |   |-'.' AccessToken
2252 |   `-IdExpression Member
2253 |     `-UnqualifiedId UnqualifiedId
2254 |       `-'x'
2255 |-'<'
2256 |-'int'
2257 |-'>'
2258 |-';'
2259 `-'}' CloseParen
2260 )txt"}));
2261 }
2262 
2263 TEST_P(BuildSyntaxTreeTest, MemberExpression_FunctionTemplate) {
2264   if (!GetParam().isCXX()) {
2265     return;
2266   }
2267   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2268       R"cpp(
2269 struct S {
2270   template<typename T>
2271   T f();
2272 };
2273 void test(S* sp){
2274   [[sp->f<int>()]];
2275 }
2276 )cpp",
2277       {R"txt(
2278 CallExpression Expression
2279 |-MemberExpression Callee
2280 | |-IdExpression Object
2281 | | `-UnqualifiedId UnqualifiedId
2282 | |   `-'sp'
2283 | |-'->' AccessToken
2284 | `-IdExpression Member
2285 |   `-UnqualifiedId UnqualifiedId
2286 |     |-'f'
2287 |     |-'<'
2288 |     |-'int'
2289 |     `-'>'
2290 |-'(' OpenParen
2291 `-')' CloseParen
2292 )txt"}));
2293 }
2294 
2295 TEST_P(BuildSyntaxTreeTest,
2296        MemberExpression_FunctionTemplateWithTemplateKeyword) {
2297   if (!GetParam().isCXX()) {
2298     return;
2299   }
2300   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2301       R"cpp(
2302 struct S {
2303   template<typename T>
2304   T f();
2305 };
2306 void test(S s){
2307   [[s.template f<int>()]];
2308 }
2309 )cpp",
2310       {R"txt(
2311 CallExpression Expression
2312 |-MemberExpression Callee
2313 | |-IdExpression Object
2314 | | `-UnqualifiedId UnqualifiedId
2315 | |   `-'s'
2316 | |-'.' AccessToken
2317 | |-'template'
2318 | `-IdExpression Member
2319 |   `-UnqualifiedId UnqualifiedId
2320 |     |-'f'
2321 |     |-'<'
2322 |     |-'int'
2323 |     `-'>'
2324 |-'(' OpenParen
2325 `-')' CloseParen
2326 )txt"}));
2327 }
2328 
2329 TEST_P(BuildSyntaxTreeTest, MemberExpression_WithQualifier) {
2330   if (!GetParam().isCXX()) {
2331     return;
2332   }
2333   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2334       R"cpp(
2335 struct Base {
2336   void f();
2337 };
2338 struct S : public Base {};
2339 void test(S s){
2340   [[s.Base::f()]];
2341   [[s.::S::~S()]];
2342 }
2343 )cpp",
2344       {R"txt(
2345 CallExpression Expression
2346 |-MemberExpression Callee
2347 | |-IdExpression Object
2348 | | `-UnqualifiedId UnqualifiedId
2349 | |   `-'s'
2350 | |-'.' AccessToken
2351 | `-IdExpression Member
2352 |   |-NestedNameSpecifier Qualifier
2353 |   | |-IdentifierNameSpecifier ListElement
2354 |   | | `-'Base'
2355 |   | `-'::' ListDelimiter
2356 |   `-UnqualifiedId UnqualifiedId
2357 |     `-'f'
2358 |-'(' OpenParen
2359 `-')' CloseParen
2360       )txt",
2361        R"txt(
2362 CallExpression Expression
2363 |-MemberExpression Callee
2364 | |-IdExpression Object
2365 | | `-UnqualifiedId UnqualifiedId
2366 | |   `-'s'
2367 | |-'.' AccessToken
2368 | `-IdExpression Member
2369 |   |-NestedNameSpecifier Qualifier
2370 |   | |-'::' ListDelimiter
2371 |   | |-IdentifierNameSpecifier ListElement
2372 |   | | `-'S'
2373 |   | `-'::' ListDelimiter
2374 |   `-UnqualifiedId UnqualifiedId
2375 |     |-'~'
2376 |     `-'S'
2377 |-'(' OpenParen
2378 `-')' CloseParen
2379 )txt"}));
2380 }
2381 
2382 TEST_P(BuildSyntaxTreeTest, MemberExpression_Complex) {
2383   if (!GetParam().isCXX()) {
2384     return;
2385   }
2386   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2387       R"cpp(
2388 template<typename T>
2389 struct U {
2390   template<typename U>
2391   U f();
2392 };
2393 struct S {
2394   U<int> getU();
2395 };
2396 void test(S* sp) {
2397   // FIXME: The first 'template' keyword is a child of `NestedNameSpecifier`,
2398   // but it should be a child of `MemberExpression` according to the grammar.
2399   // However one might argue that the 'template' keyword fits better inside
2400   // `NestedNameSpecifier` because if we change `U<int>` to `UI` we would like
2401   // equally to change the `NameSpecifier` `template U<int>` to just `UI`.
2402   [[sp->getU().template U<int>::template f<int>()]];
2403 }
2404 )cpp",
2405       {R"txt(
2406 CallExpression Expression
2407 |-MemberExpression Callee
2408 | |-CallExpression Object
2409 | | |-MemberExpression Callee
2410 | | | |-IdExpression Object
2411 | | | | `-UnqualifiedId UnqualifiedId
2412 | | | |   `-'sp'
2413 | | | |-'->' AccessToken
2414 | | | `-IdExpression Member
2415 | | |   `-UnqualifiedId UnqualifiedId
2416 | | |     `-'getU'
2417 | | |-'(' OpenParen
2418 | | `-')' CloseParen
2419 | |-'.' AccessToken
2420 | `-IdExpression Member
2421 |   |-NestedNameSpecifier Qualifier
2422 |   | |-SimpleTemplateNameSpecifier ListElement
2423 |   | | |-'template'
2424 |   | | |-'U'
2425 |   | | |-'<'
2426 |   | | |-'int'
2427 |   | | `-'>'
2428 |   | `-'::' ListDelimiter
2429 |   |-'template' TemplateKeyword
2430 |   `-UnqualifiedId UnqualifiedId
2431 |     |-'f'
2432 |     |-'<'
2433 |     |-'int'
2434 |     `-'>'
2435 |-'(' OpenParen
2436 `-')' CloseParen
2437 )txt"}));
2438 }
2439 
2440 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_Member) {
2441   if (!GetParam().isCXX()) {
2442     return;
2443   }
2444   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2445       R"cpp(
2446 struct S{
2447   void f();
2448 };
2449 void test(S s) {
2450   [[s.f()]];
2451 }
2452 )cpp",
2453       {R"txt(
2454 CallExpression Expression
2455 |-MemberExpression Callee
2456 | |-IdExpression Object
2457 | | `-UnqualifiedId UnqualifiedId
2458 | |   `-'s'
2459 | |-'.' AccessToken
2460 | `-IdExpression Member
2461 |   `-UnqualifiedId UnqualifiedId
2462 |     `-'f'
2463 |-'(' OpenParen
2464 `-')' CloseParen
2465 )txt"}));
2466 }
2467 
2468 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_OperatorParens) {
2469   if (!GetParam().isCXX()) {
2470     return;
2471   }
2472   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2473       R"cpp(
2474 struct S {
2475   void operator()();
2476 };
2477 void test(S s) {
2478   [[s()]];
2479 }
2480 )cpp",
2481       {R"txt(
2482 CallExpression Expression
2483 |-IdExpression Callee
2484 | `-UnqualifiedId UnqualifiedId
2485 |   `-'s'
2486 |-'(' OpenParen
2487 `-')' CloseParen
2488 )txt"}));
2489 }
2490 
2491 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_OperatorParensChaining) {
2492   if (!GetParam().isCXX()) {
2493     return;
2494   }
2495   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2496       R"cpp(
2497 struct S {
2498   S operator()();
2499 };
2500 void test(S s) {
2501   [[s()()]];
2502 }
2503 )cpp",
2504       {R"txt(
2505 CallExpression Expression
2506 |-CallExpression Callee
2507 | |-IdExpression Callee
2508 | | `-UnqualifiedId UnqualifiedId
2509 | |   `-'s'
2510 | |-'(' OpenParen
2511 | `-')' CloseParen
2512 |-'(' OpenParen
2513 `-')' CloseParen
2514 )txt"}));
2515 }
2516 
2517 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_MemberWithThis) {
2518   if (!GetParam().isCXX()) {
2519     return;
2520   }
2521   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2522       R"cpp(
2523 struct Base {
2524   void f();
2525 };
2526 struct S: public Base {
2527   void f();
2528   void test() {
2529     [[this->f()]];
2530     [[f()]];
2531     [[this->Base::f()]];
2532   }
2533 };
2534 )cpp",
2535       {R"txt(
2536 CallExpression Expression
2537 |-MemberExpression Callee
2538 | |-ThisExpression Object
2539 | | `-'this' IntroducerKeyword
2540 | |-'->' AccessToken
2541 | `-IdExpression Member
2542 |   `-UnqualifiedId UnqualifiedId
2543 |     `-'f'
2544 |-'(' OpenParen
2545 `-')' CloseParen
2546       )txt",
2547        R"txt(
2548 CallExpression Expression
2549 |-IdExpression Callee
2550 | `-UnqualifiedId UnqualifiedId
2551 |   `-'f'
2552 |-'(' OpenParen
2553 `-')' CloseParen
2554       )txt",
2555        R"txt(
2556 CallExpression Expression
2557 |-MemberExpression Callee
2558 | |-ThisExpression Object
2559 | | `-'this' IntroducerKeyword
2560 | |-'->' AccessToken
2561 | `-IdExpression Member
2562 |   |-NestedNameSpecifier Qualifier
2563 |   | |-IdentifierNameSpecifier ListElement
2564 |   | | `-'Base'
2565 |   | `-'::' ListDelimiter
2566 |   `-UnqualifiedId UnqualifiedId
2567 |     `-'f'
2568 |-'(' OpenParen
2569 `-')' CloseParen
2570 )txt"}));
2571 }
2572 
2573 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_FunctionPointer) {
2574   if (!GetParam().isCXX()) {
2575     return;
2576   }
2577   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2578       R"cpp(
2579 void (*pf)();
2580 void test() {
2581   [[pf()]];
2582   [[(*pf)()]];
2583 }
2584 )cpp",
2585       {R"txt(
2586 CallExpression Expression
2587 |-IdExpression Callee
2588 | `-UnqualifiedId UnqualifiedId
2589 |   `-'pf'
2590 |-'(' OpenParen
2591 `-')' CloseParen
2592 )txt",
2593        R"txt(
2594 CallExpression Expression
2595 |-ParenExpression Callee
2596 | |-'(' OpenParen
2597 | |-PrefixUnaryOperatorExpression SubExpression
2598 | | |-'*' OperatorToken
2599 | | `-IdExpression Operand
2600 | |   `-UnqualifiedId UnqualifiedId
2601 | |     `-'pf'
2602 | `-')' CloseParen
2603 |-'(' OpenParen
2604 `-')' CloseParen
2605 )txt"}));
2606 }
2607 
2608 TEST_P(BuildSyntaxTreeTest, CallExpression_Callee_MemberFunctionPointer) {
2609   if (!GetParam().isCXX()) {
2610     return;
2611   }
2612   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2613       R"cpp(
2614 struct S {
2615   void f();
2616 };
2617 void test(S s) {
2618   void (S::*pmf)();
2619   pmf = &S::f;
2620   [[(s.*pmf)()]];
2621 }
2622 )cpp",
2623       {R"txt(
2624 CallExpression Expression
2625 |-ParenExpression Callee
2626 | |-'(' OpenParen
2627 | |-BinaryOperatorExpression SubExpression
2628 | | |-IdExpression LeftHandSide
2629 | | | `-UnqualifiedId UnqualifiedId
2630 | | |   `-'s'
2631 | | |-'.*' OperatorToken
2632 | | `-IdExpression RightHandSide
2633 | |   `-UnqualifiedId UnqualifiedId
2634 | |     `-'pmf'
2635 | `-')' CloseParen
2636 |-'(' OpenParen
2637 `-')' CloseParen
2638 )txt"}));
2639 }
2640 
2641 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Zero) {
2642   if (!GetParam().isCXX()) {
2643     return;
2644   }
2645   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2646       R"cpp(
2647 void f();
2648 void test() {
2649   [[f();]]
2650 }
2651 )cpp",
2652       {R"txt(
2653 ExpressionStatement Statement
2654 |-CallExpression Expression
2655 | |-IdExpression Callee
2656 | | `-UnqualifiedId UnqualifiedId
2657 | |   `-'f'
2658 | |-'(' OpenParen
2659 | `-')' CloseParen
2660 `-';'
2661 )txt"}));
2662 }
2663 
2664 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_One) {
2665   if (!GetParam().isCXX()) {
2666     return;
2667   }
2668   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2669       R"cpp(
2670 void f(int);
2671 void test() {
2672   [[f(1);]]
2673 }
2674 )cpp",
2675       {R"txt(
2676 ExpressionStatement Statement
2677 |-CallExpression Expression
2678 | |-IdExpression Callee
2679 | | `-UnqualifiedId UnqualifiedId
2680 | |   `-'f'
2681 | |-'(' OpenParen
2682 | |-CallArguments Arguments
2683 | | `-IntegerLiteralExpression ListElement
2684 | |   `-'1' LiteralToken
2685 | `-')' CloseParen
2686 `-';'
2687 )txt"}));
2688 }
2689 
2690 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Multiple) {
2691   if (!GetParam().isCXX()) {
2692     return;
2693   }
2694   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2695       R"cpp(
2696 void f(int, char, float);
2697 void test() {
2698   [[f(1, '2', 3.);]]
2699 }
2700 )cpp",
2701       {R"txt(
2702 ExpressionStatement Statement
2703 |-CallExpression Expression
2704 | |-IdExpression Callee
2705 | | `-UnqualifiedId UnqualifiedId
2706 | |   `-'f'
2707 | |-'(' OpenParen
2708 | |-CallArguments Arguments
2709 | | |-IntegerLiteralExpression ListElement
2710 | | | `-'1' LiteralToken
2711 | | |-',' ListDelimiter
2712 | | |-CharacterLiteralExpression ListElement
2713 | | | `-''2'' LiteralToken
2714 | | |-',' ListDelimiter
2715 | | `-FloatingLiteralExpression ListElement
2716 | |   `-'3.' LiteralToken
2717 | `-')' CloseParen
2718 `-';'
2719 )txt"}));
2720 }
2721 
2722 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_Assignment) {
2723   if (!GetParam().isCXX()) {
2724     return;
2725   }
2726   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2727       R"cpp(
2728 void f(int);
2729 void test(int a) {
2730   [[f(a = 1);]]
2731 }
2732 )cpp",
2733       {R"txt(
2734 ExpressionStatement Statement
2735 |-CallExpression Expression
2736 | |-IdExpression Callee
2737 | | `-UnqualifiedId UnqualifiedId
2738 | |   `-'f'
2739 | |-'(' OpenParen
2740 | |-CallArguments Arguments
2741 | | `-BinaryOperatorExpression ListElement
2742 | |   |-IdExpression LeftHandSide
2743 | |   | `-UnqualifiedId UnqualifiedId
2744 | |   |   `-'a'
2745 | |   |-'=' OperatorToken
2746 | |   `-IntegerLiteralExpression RightHandSide
2747 | |     `-'1' LiteralToken
2748 | `-')' CloseParen
2749 `-';'
2750 )txt"}));
2751 }
2752 
2753 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_BracedInitList_Empty) {
2754   if (!GetParam().isCXX11OrLater()) {
2755     return;
2756   }
2757   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2758       R"cpp(
2759 void f(int[]);
2760 void test() {
2761   [[f({});]]
2762 }
2763 )cpp",
2764       {R"txt(
2765 ExpressionStatement Statement
2766 |-CallExpression Expression
2767 | |-IdExpression Callee
2768 | | `-UnqualifiedId UnqualifiedId
2769 | |   `-'f'
2770 | |-'(' OpenParen
2771 | |-CallArguments Arguments
2772 | | `-UnknownExpression ListElement
2773 | |   `-UnknownExpression
2774 | |     |-'{'
2775 | |     `-'}'
2776 | `-')' CloseParen
2777 `-';'
2778 )txt"}));
2779 }
2780 
2781 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_BracedInitList_Simple) {
2782   if (!GetParam().isCXX11OrLater()) {
2783     return;
2784   }
2785   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2786       R"cpp(
2787 struct TT {};
2788 struct T{
2789   int a;
2790   TT b;
2791 };
2792 void f(T);
2793 void test() {
2794   [[f({1, {}});]]
2795 }
2796 )cpp",
2797       {R"txt(
2798 ExpressionStatement Statement
2799 |-CallExpression Expression
2800 | |-IdExpression Callee
2801 | | `-UnqualifiedId UnqualifiedId
2802 | |   `-'f'
2803 | |-'(' OpenParen
2804 | |-CallArguments Arguments
2805 | | `-UnknownExpression ListElement
2806 | |   `-UnknownExpression
2807 | |     |-'{'
2808 | |     |-IntegerLiteralExpression
2809 | |     | `-'1' LiteralToken
2810 | |     |-','
2811 | |     |-UnknownExpression
2812 | |     | `-UnknownExpression
2813 | |     |   |-'{'
2814 | |     |   `-'}'
2815 | |     `-'}'
2816 | `-')' CloseParen
2817 `-';'
2818 )txt"}));
2819 }
2820 
2821 TEST_P(BuildSyntaxTreeTest,
2822        CallExpression_Arguments_BracedInitList_Designated) {
2823   if (!GetParam().isCXX11OrLater()) {
2824     return;
2825   }
2826   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2827       R"cpp(
2828 struct TT {};
2829 struct T{
2830   int a;
2831   TT b;
2832 };
2833 void f(T);
2834 void test() {
2835   [[f({.a = 1, .b {}});]]
2836 }
2837 )cpp",
2838       {R"txt(
2839 ExpressionStatement Statement
2840 |-CallExpression Expression
2841 | |-IdExpression Callee
2842 | | `-UnqualifiedId UnqualifiedId
2843 | |   `-'f'
2844 | |-'(' OpenParen
2845 | |-CallArguments Arguments
2846 | | `-UnknownExpression ListElement
2847 | |   `-UnknownExpression
2848 | |     |-'{'
2849 | |     |-UnknownExpression
2850 | |     | |-'.'
2851 | |     | |-'a'
2852 | |     | |-'='
2853 | |     | `-IntegerLiteralExpression
2854 | |     |   `-'1' LiteralToken
2855 | |     |-','
2856 | |     |-UnknownExpression
2857 | |     | |-'.'
2858 | |     | |-'b'
2859 | |     | `-UnknownExpression
2860 | |     |   `-UnknownExpression
2861 | |     |     |-'{'
2862 | |     |     `-'}'
2863 | |     `-'}'
2864 | `-')' CloseParen
2865 `-';'
2866 )txt"}));
2867 }
2868 
2869 TEST_P(BuildSyntaxTreeTest, CallExpression_Arguments_ParameterPack) {
2870   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
2871     return;
2872   }
2873   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2874       R"cpp(
2875 template<typename T, typename... Args>
2876 void test(T t, Args... args) {
2877   [[test(args...)]];
2878 }
2879 )cpp",
2880       {R"txt(
2881 CallExpression Expression
2882 |-UnknownExpression Callee
2883 | `-'test'
2884 |-'(' OpenParen
2885 |-CallArguments Arguments
2886 | `-UnknownExpression ListElement
2887 |   |-IdExpression
2888 |   | `-UnqualifiedId UnqualifiedId
2889 |   |   `-'args'
2890 |   `-'...'
2891 `-')' CloseParen
2892 )txt"}));
2893 }
2894 
2895 TEST_P(BuildSyntaxTreeTest, CallExpression_DefaultArguments) {
2896   if (!GetParam().isCXX11OrLater()) {
2897     return;
2898   }
2899   EXPECT_TRUE(treeDumpEqualOnAnnotations(
2900       R"cpp(
2901 void f(int i = 1, char c = '2');
2902 void test() {
2903   [[f()]];
2904   [[f(1)]];
2905   [[f(1, '2')]];
2906 }
2907 )cpp",
2908       {R"txt(
2909 CallExpression Expression
2910 |-IdExpression Callee
2911 | `-UnqualifiedId UnqualifiedId
2912 |   `-'f'
2913 |-'(' OpenParen
2914 `-')' CloseParen
2915       )txt",
2916        R"txt(
2917 CallExpression Expression
2918 |-IdExpression Callee
2919 | `-UnqualifiedId UnqualifiedId
2920 |   `-'f'
2921 |-'(' OpenParen
2922 |-CallArguments Arguments
2923 | `-IntegerLiteralExpression ListElement
2924 |   `-'1' LiteralToken
2925 `-')' CloseParen
2926       )txt",
2927        R"txt(
2928 CallExpression Expression
2929 |-IdExpression Callee
2930 | `-UnqualifiedId UnqualifiedId
2931 |   `-'f'
2932 |-'(' OpenParen
2933 |-CallArguments Arguments
2934 | |-IntegerLiteralExpression ListElement
2935 | | `-'1' LiteralToken
2936 | |-',' ListDelimiter
2937 | `-CharacterLiteralExpression ListElement
2938 |   `-''2'' LiteralToken
2939 `-')' CloseParen
2940 )txt"}));
2941 }
2942 
2943 TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsGrouping) {
2944   EXPECT_TRUE(treeDumpEqual(
2945       R"cpp(
2946 int *a, b;
2947 int *c, d;
2948 )cpp",
2949       R"txt(
2950 TranslationUnit Detached
2951 |-SimpleDeclaration
2952 | |-'int'
2953 | |-DeclaratorList Declarators
2954 | | |-SimpleDeclarator ListElement
2955 | | | |-'*'
2956 | | | `-'a'
2957 | | |-',' ListDelimiter
2958 | | `-SimpleDeclarator ListElement
2959 | |   `-'b'
2960 | `-';'
2961 `-SimpleDeclaration
2962   |-'int'
2963   |-DeclaratorList Declarators
2964   | |-SimpleDeclarator ListElement
2965   | | |-'*'
2966   | | `-'c'
2967   | |-',' ListDelimiter
2968   | `-SimpleDeclarator ListElement
2969   |   `-'d'
2970   `-';'
2971 )txt"));
2972 }
2973 
2974 TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
2975   EXPECT_TRUE(treeDumpEqual(
2976       R"cpp(
2977 typedef int *a, b;
2978 )cpp",
2979       R"txt(
2980 TranslationUnit Detached
2981 `-SimpleDeclaration
2982   |-'typedef'
2983   |-'int'
2984   |-DeclaratorList Declarators
2985   | |-SimpleDeclarator ListElement
2986   | | |-'*'
2987   | | `-'a'
2988   | |-',' ListDelimiter
2989   | `-SimpleDeclarator ListElement
2990   |   `-'b'
2991   `-';'
2992 )txt"));
2993 }
2994 
2995 TEST_P(BuildSyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
2996   EXPECT_TRUE(treeDumpEqual(
2997       R"cpp(
2998 void foo() {
2999   int *a, b;
3000   typedef int *ta, tb;
3001 }
3002 )cpp",
3003       R"txt(
3004 TranslationUnit Detached
3005 `-SimpleDeclaration
3006   |-'void'
3007   |-DeclaratorList Declarators
3008   | `-SimpleDeclarator ListElement
3009   |   |-'foo'
3010   |   `-ParametersAndQualifiers
3011   |     |-'(' OpenParen
3012   |     `-')' CloseParen
3013   `-CompoundStatement
3014     |-'{' OpenParen
3015     |-DeclarationStatement Statement
3016     | |-SimpleDeclaration
3017     | | |-'int'
3018     | | `-DeclaratorList Declarators
3019     | |   |-SimpleDeclarator ListElement
3020     | |   | |-'*'
3021     | |   | `-'a'
3022     | |   |-',' ListDelimiter
3023     | |   `-SimpleDeclarator ListElement
3024     | |     `-'b'
3025     | `-';'
3026     |-DeclarationStatement Statement
3027     | |-SimpleDeclaration
3028     | | |-'typedef'
3029     | | |-'int'
3030     | | `-DeclaratorList Declarators
3031     | |   |-SimpleDeclarator ListElement
3032     | |   | |-'*'
3033     | |   | `-'ta'
3034     | |   |-',' ListDelimiter
3035     | |   `-SimpleDeclarator ListElement
3036     | |     `-'tb'
3037     | `-';'
3038     `-'}' CloseParen
3039 )txt"));
3040 }
3041 
3042 TEST_P(BuildSyntaxTreeTest, SizeTTypedef) {
3043   if (!GetParam().isCXX11OrLater()) {
3044     return;
3045   }
3046   EXPECT_TRUE(treeDumpEqual(
3047       R"cpp(
3048 typedef decltype(sizeof(void *)) size_t;
3049     )cpp",
3050       R"txt(
3051 TranslationUnit Detached
3052 `-SimpleDeclaration
3053   |-'typedef'
3054   |-'decltype'
3055   |-'('
3056   |-UnknownExpression
3057   | |-'sizeof'
3058   | |-'('
3059   | |-'void'
3060   | |-'*'
3061   | `-')'
3062   |-')'
3063   |-DeclaratorList Declarators
3064   | `-SimpleDeclarator ListElement
3065   |   `-'size_t'
3066   `-';'
3067 )txt"));
3068 }
3069 
3070 TEST_P(BuildSyntaxTreeTest, Namespace_Nested) {
3071   if (!GetParam().isCXX()) {
3072     return;
3073   }
3074   EXPECT_TRUE(treeDumpEqual(
3075       R"cpp(
3076 namespace a { namespace b {} }
3077 )cpp",
3078       R"txt(
3079 TranslationUnit Detached
3080 `-NamespaceDefinition
3081   |-'namespace'
3082   |-'a'
3083   |-'{'
3084   |-NamespaceDefinition
3085   | |-'namespace'
3086   | |-'b'
3087   | |-'{'
3088   | `-'}'
3089   `-'}'
3090 )txt"));
3091 }
3092 
3093 TEST_P(BuildSyntaxTreeTest, Namespace_NestedDefinition) {
3094   if (!GetParam().isCXX17OrLater()) {
3095     return;
3096   }
3097   EXPECT_TRUE(treeDumpEqual(
3098       R"cpp(
3099 namespace a::b {}
3100 )cpp",
3101       R"txt(
3102 TranslationUnit Detached
3103 `-NamespaceDefinition
3104   |-'namespace'
3105   |-'a'
3106   |-'::'
3107   |-'b'
3108   |-'{'
3109   `-'}'
3110 )txt"));
3111 }
3112 
3113 TEST_P(BuildSyntaxTreeTest, Namespace_Unnamed) {
3114   if (!GetParam().isCXX()) {
3115     return;
3116   }
3117   EXPECT_TRUE(treeDumpEqual(
3118       R"cpp(
3119 namespace {}
3120 )cpp",
3121       R"txt(
3122 TranslationUnit Detached
3123 `-NamespaceDefinition
3124   |-'namespace'
3125   |-'{'
3126   `-'}'
3127 )txt"));
3128 }
3129 
3130 TEST_P(BuildSyntaxTreeTest, Namespace_Alias) {
3131   if (!GetParam().isCXX()) {
3132     return;
3133   }
3134   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3135       R"cpp(
3136 namespace a {}
3137 [[namespace foo = a;]]
3138 )cpp",
3139       {R"txt(
3140 NamespaceAliasDefinition
3141 |-'namespace'
3142 |-'foo'
3143 |-'='
3144 |-'a'
3145 `-';'
3146 )txt"}));
3147 }
3148 
3149 TEST_P(BuildSyntaxTreeTest, UsingDirective) {
3150   if (!GetParam().isCXX()) {
3151     return;
3152   }
3153   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3154       R"cpp(
3155 namespace ns {}
3156 [[using namespace ::ns;]]
3157 )cpp",
3158       {R"txt(
3159 UsingNamespaceDirective
3160 |-'using'
3161 |-'namespace'
3162 |-NestedNameSpecifier
3163 | `-'::' ListDelimiter
3164 |-'ns'
3165 `-';'
3166 )txt"}));
3167 }
3168 
3169 TEST_P(BuildSyntaxTreeTest, UsingDeclaration_Namespace) {
3170   if (!GetParam().isCXX()) {
3171     return;
3172   }
3173   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3174       R"cpp(
3175 namespace ns { int a; }
3176 [[using ns::a;]]
3177 )cpp",
3178       {R"txt(
3179 UsingDeclaration
3180 |-'using'
3181 |-NestedNameSpecifier
3182 | |-IdentifierNameSpecifier ListElement
3183 | | `-'ns'
3184 | `-'::' ListDelimiter
3185 |-'a'
3186 `-';'
3187 )txt"}));
3188 }
3189 
3190 TEST_P(BuildSyntaxTreeTest, UsingDeclaration_ClassMember) {
3191   if (!GetParam().isCXX()) {
3192     return;
3193   }
3194   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3195       R"cpp(
3196 template <class T> struct X {
3197   [[using T::foo;]]
3198   [[using typename T::bar;]]
3199 };
3200 )cpp",
3201       {R"txt(
3202 UsingDeclaration
3203 |-'using'
3204 |-NestedNameSpecifier
3205 | |-IdentifierNameSpecifier ListElement
3206 | | `-'T'
3207 | `-'::' ListDelimiter
3208 |-'foo'
3209 `-';'
3210 )txt",
3211        R"txt(
3212 UsingDeclaration
3213 |-'using'
3214 |-'typename'
3215 |-NestedNameSpecifier
3216 | |-IdentifierNameSpecifier ListElement
3217 | | `-'T'
3218 | `-'::' ListDelimiter
3219 |-'bar'
3220 `-';'
3221 )txt"}));
3222 }
3223 
3224 TEST_P(BuildSyntaxTreeTest, UsingTypeAlias) {
3225   if (!GetParam().isCXX11OrLater()) {
3226     return;
3227   }
3228   EXPECT_TRUE(treeDumpEqual(
3229       R"cpp(
3230 using type = int;
3231 )cpp",
3232       R"txt(
3233 TranslationUnit Detached
3234 `-TypeAliasDeclaration
3235   |-'using'
3236   |-'type'
3237   |-'='
3238   |-'int'
3239   `-';'
3240 )txt"));
3241 }
3242 
3243 TEST_P(BuildSyntaxTreeTest, FreeStandingClass_ForwardDeclaration) {
3244   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3245       R"cpp(
3246 [[struct X;]]
3247 [[struct Y *y1;]]
3248 )cpp",
3249       {R"txt(
3250 SimpleDeclaration
3251 |-'struct'
3252 |-'X'
3253 `-';'
3254 )txt",
3255        R"txt(
3256 SimpleDeclaration
3257 |-'struct'
3258 |-'Y'
3259 |-DeclaratorList Declarators
3260 | `-SimpleDeclarator ListElement
3261 |   |-'*'
3262 |   `-'y1'
3263 `-';'
3264 )txt"}));
3265 }
3266 
3267 TEST_P(BuildSyntaxTreeTest, FreeStandingClasses_Definition) {
3268   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3269       R"cpp(
3270 [[struct X {};]]
3271 [[struct Y {} *y2;]]
3272 [[struct {} *a1;]]
3273 )cpp",
3274       {R"txt(
3275 SimpleDeclaration
3276 |-'struct'
3277 |-'X'
3278 |-'{'
3279 |-'}'
3280 `-';'
3281 )txt",
3282        R"txt(
3283 SimpleDeclaration
3284 |-'struct'
3285 |-'Y'
3286 |-'{'
3287 |-'}'
3288 |-DeclaratorList Declarators
3289 | `-SimpleDeclarator ListElement
3290 |   |-'*'
3291 |   `-'y2'
3292 `-';'
3293 )txt",
3294        R"txt(
3295 SimpleDeclaration
3296 |-'struct'
3297 |-'{'
3298 |-'}'
3299 |-DeclaratorList Declarators
3300 | `-SimpleDeclarator ListElement
3301 |   |-'*'
3302 |   `-'a1'
3303 `-';'
3304 )txt"}));
3305 }
3306 
3307 TEST_P(BuildSyntaxTreeTest, StaticMemberFunction) {
3308   if (!GetParam().isCXX11OrLater()) {
3309     return;
3310   }
3311   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3312       R"cpp(
3313 struct S {
3314   [[static void f(){}]]
3315 };
3316 )cpp",
3317       {R"txt(
3318 SimpleDeclaration
3319 |-'static'
3320 |-'void'
3321 |-DeclaratorList Declarators
3322 | `-SimpleDeclarator ListElement
3323 |   |-'f'
3324 |   `-ParametersAndQualifiers
3325 |     |-'(' OpenParen
3326 |     `-')' CloseParen
3327 `-CompoundStatement
3328   |-'{' OpenParen
3329   `-'}' CloseParen
3330 )txt"}));
3331 }
3332 
3333 TEST_P(BuildSyntaxTreeTest, OutOfLineMemberFunctionDefinition) {
3334   if (!GetParam().isCXX11OrLater()) {
3335     return;
3336   }
3337   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3338       R"cpp(
3339 struct S {
3340   void f();
3341 };
3342 [[void S::f(){}]]
3343 )cpp",
3344       {R"txt(
3345 SimpleDeclaration
3346 |-'void'
3347 |-DeclaratorList Declarators
3348 | `-SimpleDeclarator ListElement
3349 |   |-NestedNameSpecifier
3350 |   | |-IdentifierNameSpecifier ListElement
3351 |   | | `-'S'
3352 |   | `-'::' ListDelimiter
3353 |   |-'f'
3354 |   `-ParametersAndQualifiers
3355 |     |-'(' OpenParen
3356 |     `-')' CloseParen
3357 `-CompoundStatement
3358   |-'{' OpenParen
3359   `-'}' CloseParen
3360 )txt"}));
3361 }
3362 
3363 TEST_P(BuildSyntaxTreeTest, ConversionMemberFunction) {
3364   if (!GetParam().isCXX()) {
3365     return;
3366   }
3367   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3368       R"cpp(
3369 struct X {
3370   [[operator int();]]
3371 };
3372 )cpp",
3373       {R"txt(
3374 SimpleDeclaration
3375 |-DeclaratorList Declarators
3376 | `-SimpleDeclarator ListElement
3377 |   |-'operator'
3378 |   |-'int'
3379 |   `-ParametersAndQualifiers
3380 |     |-'(' OpenParen
3381 |     `-')' CloseParen
3382 `-';'
3383 )txt"}));
3384 }
3385 
3386 TEST_P(BuildSyntaxTreeTest, LiteralOperatorDeclaration) {
3387   if (!GetParam().isCXX11OrLater()) {
3388     return;
3389   }
3390   EXPECT_TRUE(treeDumpEqual(
3391       R"cpp(
3392 unsigned operator "" _c(char);
3393     )cpp",
3394       R"txt(
3395 TranslationUnit Detached
3396 `-SimpleDeclaration
3397   |-'unsigned'
3398   |-DeclaratorList Declarators
3399   | `-SimpleDeclarator ListElement
3400   |   |-'operator'
3401   |   |-'""'
3402   |   |-'_c'
3403   |   `-ParametersAndQualifiers
3404   |     |-'(' OpenParen
3405   |     |-ParameterDeclarationList Parameters
3406   |     | `-SimpleDeclaration ListElement
3407   |     |   `-'char'
3408   |     `-')' CloseParen
3409   `-';'
3410 )txt"));
3411 }
3412 
3413 TEST_P(BuildSyntaxTreeTest, NumericLiteralOperatorTemplateDeclaration) {
3414   if (!GetParam().isCXX11OrLater()) {
3415     return;
3416   }
3417   EXPECT_TRUE(treeDumpEqual(
3418       R"cpp(
3419 template <char...>
3420 unsigned operator "" _t();
3421     )cpp",
3422       R"txt(
3423 TranslationUnit Detached
3424 `-TemplateDeclaration Declaration
3425   |-'template' IntroducerKeyword
3426   |-'<'
3427   |-SimpleDeclaration
3428   | `-'char'
3429   |-'...'
3430   |-'>'
3431   `-SimpleDeclaration
3432     |-'unsigned'
3433     |-DeclaratorList Declarators
3434     | `-SimpleDeclarator ListElement
3435     |   |-'operator'
3436     |   |-'""'
3437     |   |-'_t'
3438     |   `-ParametersAndQualifiers
3439     |     |-'(' OpenParen
3440     |     `-')' CloseParen
3441     `-';'
3442 )txt"));
3443 }
3444 
3445 TEST_P(BuildSyntaxTreeTest, OverloadedOperatorDeclaration) {
3446   if (!GetParam().isCXX()) {
3447     return;
3448   }
3449   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3450       R"cpp(
3451 struct X {
3452   [[X& operator=(const X&);]]
3453 };
3454 )cpp",
3455       {R"txt(
3456 SimpleDeclaration
3457 |-'X'
3458 |-DeclaratorList Declarators
3459 | `-SimpleDeclarator ListElement
3460 |   |-'&'
3461 |   |-'operator'
3462 |   |-'='
3463 |   `-ParametersAndQualifiers
3464 |     |-'(' OpenParen
3465 |     |-ParameterDeclarationList Parameters
3466 |     | `-SimpleDeclaration ListElement
3467 |     |   |-'const'
3468 |     |   |-'X'
3469 |     |   `-DeclaratorList Declarators
3470 |     |     `-SimpleDeclarator ListElement
3471 |     |       `-'&'
3472 |     `-')' CloseParen
3473 `-';'
3474 )txt"}));
3475 }
3476 
3477 TEST_P(BuildSyntaxTreeTest, OverloadedOperatorFriendDeclaration) {
3478   if (!GetParam().isCXX()) {
3479     return;
3480   }
3481   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3482       R"cpp(
3483 struct X {
3484   [[friend X operator+(X, const X&);]]
3485 };
3486 )cpp",
3487       {R"txt(
3488 UnknownDeclaration
3489 `-SimpleDeclaration
3490   |-'friend'
3491   |-'X'
3492   |-DeclaratorList Declarators
3493   | `-SimpleDeclarator ListElement
3494   |   |-'operator'
3495   |   |-'+'
3496   |   `-ParametersAndQualifiers
3497   |     |-'(' OpenParen
3498   |     |-ParameterDeclarationList Parameters
3499   |     | |-SimpleDeclaration ListElement
3500   |     | | `-'X'
3501   |     | |-',' ListDelimiter
3502   |     | `-SimpleDeclaration ListElement
3503   |     |   |-'const'
3504   |     |   |-'X'
3505   |     |   `-DeclaratorList Declarators
3506   |     |     `-SimpleDeclarator ListElement
3507   |     |       `-'&'
3508   |     `-')' CloseParen
3509   `-';'
3510 )txt"}));
3511 }
3512 
3513 TEST_P(BuildSyntaxTreeTest, ClassTemplateDeclaration) {
3514   if (!GetParam().isCXX()) {
3515     return;
3516   }
3517   EXPECT_TRUE(treeDumpEqual(
3518       R"cpp(
3519 template<typename T>
3520 struct ST {};
3521 )cpp",
3522       R"txt(
3523 TranslationUnit Detached
3524 `-TemplateDeclaration Declaration
3525   |-'template' IntroducerKeyword
3526   |-'<'
3527   |-UnknownDeclaration
3528   | |-'typename'
3529   | `-'T'
3530   |-'>'
3531   `-SimpleDeclaration
3532     |-'struct'
3533     |-'ST'
3534     |-'{'
3535     |-'}'
3536     `-';'
3537 )txt"));
3538 }
3539 
3540 TEST_P(BuildSyntaxTreeTest, FunctionTemplateDeclaration) {
3541   if (!GetParam().isCXX()) {
3542     return;
3543   }
3544   EXPECT_TRUE(treeDumpEqual(
3545       R"cpp(
3546 template<typename T>
3547 T f();
3548 )cpp",
3549       R"txt(
3550 TranslationUnit Detached
3551 `-TemplateDeclaration Declaration
3552   |-'template' IntroducerKeyword
3553   |-'<'
3554   |-UnknownDeclaration
3555   | |-'typename'
3556   | `-'T'
3557   |-'>'
3558   `-SimpleDeclaration
3559     |-'T'
3560     |-DeclaratorList Declarators
3561     | `-SimpleDeclarator ListElement
3562     |   |-'f'
3563     |   `-ParametersAndQualifiers
3564     |     |-'(' OpenParen
3565     |     `-')' CloseParen
3566     `-';'
3567 )txt"));
3568 }
3569 
3570 TEST_P(BuildSyntaxTreeTest, VariableTemplateDeclaration) {
3571   if (!GetParam().isCXX14OrLater()) {
3572     return;
3573   }
3574   EXPECT_TRUE(treeDumpEqual(
3575       R"cpp(
3576 template <class T> T var = 10;
3577 )cpp",
3578       R"txt(
3579 TranslationUnit Detached
3580 `-TemplateDeclaration Declaration
3581   |-'template' IntroducerKeyword
3582   |-'<'
3583   |-UnknownDeclaration
3584   | |-'class'
3585   | `-'T'
3586   |-'>'
3587   `-SimpleDeclaration
3588     |-'T'
3589     |-DeclaratorList Declarators
3590     | `-SimpleDeclarator ListElement
3591     |   |-'var'
3592     |   |-'='
3593     |   `-IntegerLiteralExpression
3594     |     `-'10' LiteralToken
3595     `-';'
3596 )txt"));
3597 }
3598 
3599 TEST_P(BuildSyntaxTreeTest, StaticMemberFunctionTemplate) {
3600   if (!GetParam().isCXX()) {
3601     return;
3602   }
3603   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3604       R"cpp(
3605 struct S {
3606   [[template<typename U>
3607   static U f();]]
3608 };
3609 )cpp",
3610       {R"txt(
3611 TemplateDeclaration Declaration
3612 |-'template' IntroducerKeyword
3613 |-'<'
3614 |-UnknownDeclaration
3615 | |-'typename'
3616 | `-'U'
3617 |-'>'
3618 `-SimpleDeclaration
3619   |-'static'
3620   |-'U'
3621   |-DeclaratorList Declarators
3622   | `-SimpleDeclarator ListElement
3623   |   |-'f'
3624   |   `-ParametersAndQualifiers
3625   |     |-'(' OpenParen
3626   |     `-')' CloseParen
3627   `-';'
3628 )txt"}));
3629 }
3630 
3631 TEST_P(BuildSyntaxTreeTest, NestedTemplates) {
3632   if (!GetParam().isCXX()) {
3633     return;
3634   }
3635   EXPECT_TRUE(treeDumpEqual(
3636       R"cpp(
3637 template <class T>
3638 struct X {
3639   template <class U>
3640   U foo();
3641 };
3642 )cpp",
3643       R"txt(
3644 TranslationUnit Detached
3645 `-TemplateDeclaration Declaration
3646   |-'template' IntroducerKeyword
3647   |-'<'
3648   |-UnknownDeclaration
3649   | |-'class'
3650   | `-'T'
3651   |-'>'
3652   `-SimpleDeclaration
3653     |-'struct'
3654     |-'X'
3655     |-'{'
3656     |-TemplateDeclaration Declaration
3657     | |-'template' IntroducerKeyword
3658     | |-'<'
3659     | |-UnknownDeclaration
3660     | | |-'class'
3661     | | `-'U'
3662     | |-'>'
3663     | `-SimpleDeclaration
3664     |   |-'U'
3665     |   |-DeclaratorList Declarators
3666     |   | `-SimpleDeclarator ListElement
3667     |   |   |-'foo'
3668     |   |   `-ParametersAndQualifiers
3669     |   |     |-'(' OpenParen
3670     |   |     `-')' CloseParen
3671     |   `-';'
3672     |-'}'
3673     `-';'
3674 )txt"));
3675 }
3676 
3677 TEST_P(BuildSyntaxTreeTest, NestedTemplatesInNamespace) {
3678   if (!GetParam().isCXX()) {
3679     return;
3680   }
3681   EXPECT_TRUE(treeDumpEqual(
3682       R"cpp(
3683 namespace n {
3684   template<typename T>
3685   struct ST {
3686     template<typename U>
3687     static U f();
3688   };
3689 }
3690 )cpp",
3691       R"txt(
3692 TranslationUnit Detached
3693 `-NamespaceDefinition
3694   |-'namespace'
3695   |-'n'
3696   |-'{'
3697   |-TemplateDeclaration Declaration
3698   | |-'template' IntroducerKeyword
3699   | |-'<'
3700   | |-UnknownDeclaration
3701   | | |-'typename'
3702   | | `-'T'
3703   | |-'>'
3704   | `-SimpleDeclaration
3705   |   |-'struct'
3706   |   |-'ST'
3707   |   |-'{'
3708   |   |-TemplateDeclaration Declaration
3709   |   | |-'template' IntroducerKeyword
3710   |   | |-'<'
3711   |   | |-UnknownDeclaration
3712   |   | | |-'typename'
3713   |   | | `-'U'
3714   |   | |-'>'
3715   |   | `-SimpleDeclaration
3716   |   |   |-'static'
3717   |   |   |-'U'
3718   |   |   |-DeclaratorList Declarators
3719   |   |   | `-SimpleDeclarator ListElement
3720   |   |   |   |-'f'
3721   |   |   |   `-ParametersAndQualifiers
3722   |   |   |     |-'(' OpenParen
3723   |   |   |     `-')' CloseParen
3724   |   |   `-';'
3725   |   |-'}'
3726   |   `-';'
3727   `-'}'
3728 )txt"));
3729 }
3730 
3731 TEST_P(BuildSyntaxTreeTest, ClassTemplate_MemberClassDefinition) {
3732   if (!GetParam().isCXX()) {
3733     return;
3734   }
3735   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3736       R"cpp(
3737 template <class T> struct X { struct Y; };
3738 [[template <class T> struct X<T>::Y {};]]
3739 )cpp",
3740       {R"txt(
3741 TemplateDeclaration Declaration
3742 |-'template' IntroducerKeyword
3743 |-'<'
3744 |-UnknownDeclaration
3745 | |-'class'
3746 | `-'T'
3747 |-'>'
3748 `-SimpleDeclaration
3749   |-'struct'
3750   |-NestedNameSpecifier
3751   | |-SimpleTemplateNameSpecifier ListElement
3752   | | |-'X'
3753   | | |-'<'
3754   | | |-'T'
3755   | | `-'>'
3756   | `-'::' ListDelimiter
3757   |-'Y'
3758   |-'{'
3759   |-'}'
3760   `-';'
3761 )txt"}));
3762 }
3763 
3764 TEST_P(BuildSyntaxTreeTest, ExplicitClassTemplateInstantiation_Definition) {
3765   if (!GetParam().isCXX()) {
3766     return;
3767   }
3768   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3769       R"cpp(
3770 template <class T> struct X {};
3771 [[template struct X<double>;]]
3772 )cpp",
3773       {R"txt(
3774 ExplicitTemplateInstantiation
3775 |-'template' IntroducerKeyword
3776 `-SimpleDeclaration Declaration
3777   |-'struct'
3778   |-'X'
3779   |-'<'
3780   |-'double'
3781   |-'>'
3782   `-';'
3783 )txt"}));
3784 }
3785 
3786 TEST_P(BuildSyntaxTreeTest, ExplicitClassTemplateInstantiation_Declaration) {
3787   if (!GetParam().isCXX()) {
3788     return;
3789   }
3790   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3791       R"cpp(
3792 template <class T> struct X {};
3793 [[extern template struct X<float>;]]
3794 )cpp",
3795       {R"txt(
3796 ExplicitTemplateInstantiation
3797 |-'extern' ExternKeyword
3798 |-'template' IntroducerKeyword
3799 `-SimpleDeclaration Declaration
3800   |-'struct'
3801   |-'X'
3802   |-'<'
3803   |-'float'
3804   |-'>'
3805   `-';'
3806 )txt"}));
3807 }
3808 
3809 TEST_P(BuildSyntaxTreeTest, ClassTemplateSpecialization_Partial) {
3810   if (!GetParam().isCXX()) {
3811     return;
3812   }
3813   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3814       R"cpp(
3815 template <class T> struct X {};
3816 [[template <class T> struct X<T*> {};]]
3817 )cpp",
3818       {R"txt(
3819 TemplateDeclaration Declaration
3820 |-'template' IntroducerKeyword
3821 |-'<'
3822 |-UnknownDeclaration
3823 | |-'class'
3824 | `-'T'
3825 |-'>'
3826 `-SimpleDeclaration
3827   |-'struct'
3828   |-'X'
3829   |-'<'
3830   |-'T'
3831   |-'*'
3832   |-'>'
3833   |-'{'
3834   |-'}'
3835   `-';'
3836 )txt"}));
3837 }
3838 
3839 TEST_P(BuildSyntaxTreeTest, ClassTemplateSpecialization_Full) {
3840   if (!GetParam().isCXX()) {
3841     return;
3842   }
3843   EXPECT_TRUE(treeDumpEqualOnAnnotations(
3844       R"cpp(
3845 template <class T> struct X {};
3846 [[template <> struct X<int> {};]]
3847 )cpp",
3848       {R"txt(
3849 TemplateDeclaration Declaration
3850 |-'template' IntroducerKeyword
3851 |-'<'
3852 |-'>'
3853 `-SimpleDeclaration
3854   |-'struct'
3855   |-'X'
3856   |-'<'
3857   |-'int'
3858   |-'>'
3859   |-'{'
3860   |-'}'
3861   `-';'
3862 )txt"}));
3863 }
3864 
3865 TEST_P(BuildSyntaxTreeTest, EmptyDeclaration) {
3866   EXPECT_TRUE(treeDumpEqual(
3867       R"cpp(
3868 ;
3869 )cpp",
3870       R"txt(
3871 TranslationUnit Detached
3872 `-EmptyDeclaration
3873   `-';'
3874 )txt"));
3875 }
3876 
3877 TEST_P(BuildSyntaxTreeTest, StaticAssert) {
3878   if (!GetParam().isCXX11OrLater()) {
3879     return;
3880   }
3881   EXPECT_TRUE(treeDumpEqual(
3882       R"cpp(
3883 static_assert(true, "message");
3884 )cpp",
3885       R"txt(
3886 TranslationUnit Detached
3887 `-StaticAssertDeclaration
3888   |-'static_assert'
3889   |-'('
3890   |-BoolLiteralExpression Condition
3891   | `-'true' LiteralToken
3892   |-','
3893   |-StringLiteralExpression Message
3894   | `-'"message"' LiteralToken
3895   |-')'
3896   `-';'
3897 )txt"));
3898 }
3899 
3900 TEST_P(BuildSyntaxTreeTest, StaticAssert_WithoutMessage) {
3901   if (!GetParam().isCXX17OrLater()) {
3902     return;
3903   }
3904   EXPECT_TRUE(treeDumpEqual(
3905       R"cpp(
3906 static_assert(true);
3907 )cpp",
3908       R"txt(
3909 TranslationUnit Detached
3910 `-StaticAssertDeclaration
3911   |-'static_assert'
3912   |-'('
3913   |-BoolLiteralExpression Condition
3914   | `-'true' LiteralToken
3915   |-')'
3916   `-';'
3917 )txt"));
3918 }
3919 
3920 TEST_P(BuildSyntaxTreeTest, ExternC) {
3921   if (!GetParam().isCXX()) {
3922     return;
3923   }
3924   EXPECT_TRUE(treeDumpEqual(
3925       R"cpp(
3926 extern "C" int a;
3927 extern "C" { int b; int c; }
3928 )cpp",
3929       R"txt(
3930 TranslationUnit Detached
3931 |-LinkageSpecificationDeclaration
3932 | |-'extern'
3933 | |-'"C"'
3934 | `-SimpleDeclaration
3935 |   |-'int'
3936 |   |-DeclaratorList Declarators
3937 |   | `-SimpleDeclarator ListElement
3938 |   |   `-'a'
3939 |   `-';'
3940 `-LinkageSpecificationDeclaration
3941   |-'extern'
3942   |-'"C"'
3943   |-'{'
3944   |-SimpleDeclaration
3945   | |-'int'
3946   | |-DeclaratorList Declarators
3947   | | `-SimpleDeclarator ListElement
3948   | |   `-'b'
3949   | `-';'
3950   |-SimpleDeclaration
3951   | |-'int'
3952   | |-DeclaratorList Declarators
3953   | | `-SimpleDeclarator ListElement
3954   | |   `-'c'
3955   | `-';'
3956   `-'}'
3957 )txt"));
3958 }
3959 
3960 TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_Leaf) {
3961   // All nodes can be mutated.
3962   EXPECT_TRUE(treeDumpEqual(
3963       R"cpp(
3964 #define OPEN {
3965 #define CLOSE }
3966 
3967 void test() {
3968   OPEN
3969     1;
3970   CLOSE
3971 
3972   OPEN
3973     2;
3974   }
3975 }
3976 )cpp",
3977       R"txt(
3978 TranslationUnit Detached
3979 `-SimpleDeclaration
3980   |-'void'
3981   |-DeclaratorList Declarators
3982   | `-SimpleDeclarator ListElement
3983   |   |-'test'
3984   |   `-ParametersAndQualifiers
3985   |     |-'(' OpenParen
3986   |     `-')' CloseParen
3987   `-CompoundStatement
3988     |-'{' OpenParen
3989     |-CompoundStatement Statement
3990     | |-'{' OpenParen
3991     | |-ExpressionStatement Statement
3992     | | |-IntegerLiteralExpression Expression
3993     | | | `-'1' LiteralToken
3994     | | `-';'
3995     | `-'}' CloseParen
3996     |-CompoundStatement Statement
3997     | |-'{' OpenParen
3998     | |-ExpressionStatement Statement
3999     | | |-IntegerLiteralExpression Expression
4000     | | | `-'2' LiteralToken
4001     | | `-';'
4002     | `-'}' CloseParen
4003     `-'}' CloseParen
4004 )txt"));
4005 }
4006 
4007 TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MatchTree) {
4008   // Some nodes are unmodifiable, they are marked with 'unmodifiable'.
4009   EXPECT_TRUE(treeDumpEqual(
4010       R"cpp(
4011 #define BRACES {}
4012 
4013 void test() BRACES
4014 )cpp",
4015       R"txt(
4016 TranslationUnit Detached
4017 `-SimpleDeclaration
4018   |-'void'
4019   |-DeclaratorList Declarators
4020   | `-SimpleDeclarator ListElement
4021   |   |-'test'
4022   |   `-ParametersAndQualifiers
4023   |     |-'(' OpenParen
4024   |     `-')' CloseParen
4025   `-CompoundStatement
4026     |-'{' OpenParen unmodifiable
4027     `-'}' CloseParen unmodifiable
4028 )txt"));
4029 }
4030 
4031 TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MismatchTree) {
4032   EXPECT_TRUE(treeDumpEqual(
4033       R"cpp(
4034 #define HALF_IF if (1+
4035 #define HALF_IF_2 1) {}
4036 void test() {
4037   HALF_IF HALF_IF_2 else {}
4038 })cpp",
4039       R"txt(
4040 TranslationUnit Detached
4041 `-SimpleDeclaration
4042   |-'void'
4043   |-DeclaratorList Declarators
4044   | `-SimpleDeclarator ListElement
4045   |   |-'test'
4046   |   `-ParametersAndQualifiers
4047   |     |-'(' OpenParen
4048   |     `-')' CloseParen
4049   `-CompoundStatement
4050     |-'{' OpenParen
4051     |-IfStatement Statement
4052     | |-'if' IntroducerKeyword unmodifiable
4053     | |-'(' unmodifiable
4054     | |-ExpressionStatement Condition unmodifiable
4055     | | `-BinaryOperatorExpression Expression unmodifiable
4056     | |   |-IntegerLiteralExpression LeftHandSide unmodifiable
4057     | |   | `-'1' LiteralToken unmodifiable
4058     | |   |-'+' OperatorToken unmodifiable
4059     | |   `-IntegerLiteralExpression RightHandSide unmodifiable
4060     | |     `-'1' LiteralToken unmodifiable
4061     | |-')' unmodifiable
4062     | |-CompoundStatement ThenStatement unmodifiable
4063     | | |-'{' OpenParen unmodifiable
4064     | | `-'}' CloseParen unmodifiable
4065     | |-'else' ElseKeyword
4066     | `-CompoundStatement ElseStatement
4067     |   |-'{' OpenParen
4068     |   `-'}' CloseParen
4069     `-'}' CloseParen
4070 )txt"));
4071 }
4072 
4073 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_ModifiableArguments) {
4074   // FIXME: Note that the substitutions for `X` and `Y` are marked modifiable.
4075   // However we cannot change `X` freely. Indeed if we change its substitution
4076   // in the condition we should also change it the then-branch.
4077   EXPECT_TRUE(treeDumpEqual(
4078       R"cpp(
4079 #define MIN(X,Y) X < Y ? X : Y
4080 
4081 void test() {
4082   MIN(1,2);
4083 }
4084 )cpp",
4085       R"txt(
4086 TranslationUnit Detached
4087 `-SimpleDeclaration
4088   |-'void'
4089   |-DeclaratorList Declarators
4090   | `-SimpleDeclarator ListElement
4091   |   |-'test'
4092   |   `-ParametersAndQualifiers
4093   |     |-'(' OpenParen
4094   |     `-')' CloseParen
4095   `-CompoundStatement
4096     |-'{' OpenParen
4097     |-ExpressionStatement Statement
4098     | |-UnknownExpression Expression
4099     | | |-BinaryOperatorExpression unmodifiable
4100     | | | |-IntegerLiteralExpression LeftHandSide
4101     | | | | `-'1' LiteralToken
4102     | | | |-'<' OperatorToken unmodifiable
4103     | | | `-IntegerLiteralExpression RightHandSide
4104     | | |   `-'2' LiteralToken
4105     | | |-'?' unmodifiable
4106     | | |-IntegerLiteralExpression
4107     | | | `-'1' LiteralToken
4108     | | |-':' unmodifiable
4109     | | `-IntegerLiteralExpression
4110     | |   `-'2' LiteralToken
4111     | `-';'
4112     `-'}' CloseParen
4113 )txt"));
4114 }
4115 
4116 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_MismatchTree) {
4117   EXPECT_TRUE(treeDumpEqual(
4118       R"cpp(
4119 #define HALF_IF(X) if (X &&
4120 #define HALF_IF_2(Y) Y) {}
4121 void test() {
4122   HALF_IF(1) HALF_IF_2(0) else {}
4123 })cpp",
4124       R"txt(
4125 TranslationUnit Detached
4126 `-SimpleDeclaration
4127   |-'void'
4128   |-DeclaratorList Declarators
4129   | `-SimpleDeclarator ListElement
4130   |   |-'test'
4131   |   `-ParametersAndQualifiers
4132   |     |-'(' OpenParen
4133   |     `-')' CloseParen
4134   `-CompoundStatement
4135     |-'{' OpenParen
4136     |-IfStatement Statement
4137     | |-'if' IntroducerKeyword unmodifiable
4138     | |-'(' unmodifiable
4139     | |-ExpressionStatement Condition unmodifiable
4140     | | `-BinaryOperatorExpression Expression unmodifiable
4141     | |   |-IntegerLiteralExpression LeftHandSide
4142     | |   | `-'1' LiteralToken
4143     | |   |-'&&' OperatorToken unmodifiable
4144     | |   `-IntegerLiteralExpression RightHandSide
4145     | |     `-'0' LiteralToken
4146     | |-')' unmodifiable
4147     | |-CompoundStatement ThenStatement unmodifiable
4148     | | |-'{' OpenParen unmodifiable
4149     | | `-'}' CloseParen unmodifiable
4150     | |-'else' ElseKeyword
4151     | `-CompoundStatement ElseStatement
4152     |   |-'{' OpenParen
4153     |   `-'}' CloseParen
4154     `-'}' CloseParen
4155 )txt"));
4156 }
4157 
4158 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_Variadic) {
4159   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4160       R"cpp(
4161 #define CALL(F_NAME, ...) F_NAME(__VA_ARGS__)
4162 
4163 void f(int);
4164 void g(int, int);
4165 void test() [[{
4166   CALL(f, 0);
4167   CALL(g, 0, 1);
4168 }]]
4169 )cpp",
4170       {R"txt(
4171 CompoundStatement
4172 |-'{' OpenParen
4173 |-ExpressionStatement Statement
4174 | |-CallExpression Expression
4175 | | |-IdExpression Callee
4176 | | | `-UnqualifiedId UnqualifiedId
4177 | | |   `-'f'
4178 | | |-'(' OpenParen unmodifiable
4179 | | |-CallArguments Arguments
4180 | | | `-IntegerLiteralExpression ListElement
4181 | | |   `-'0' LiteralToken
4182 | | `-')' CloseParen unmodifiable
4183 | `-';'
4184 |-ExpressionStatement Statement
4185 | |-CallExpression Expression
4186 | | |-IdExpression Callee
4187 | | | `-UnqualifiedId UnqualifiedId
4188 | | |   `-'g'
4189 | | |-'(' OpenParen unmodifiable
4190 | | |-CallArguments Arguments
4191 | | | |-IntegerLiteralExpression ListElement
4192 | | | | `-'0' LiteralToken
4193 | | | |-',' ListDelimiter
4194 | | | `-IntegerLiteralExpression ListElement
4195 | | |   `-'1' LiteralToken
4196 | | `-')' CloseParen unmodifiable
4197 | `-';'
4198 `-'}' CloseParen
4199 )txt"}));
4200 }
4201 
4202 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Equal) {
4203   if (!GetParam().isCXX()) {
4204     return;
4205   }
4206   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4207       R"cpp(
4208 struct S { S(int);};
4209 void test() {
4210   [[S s = 1]];
4211 }
4212 )cpp",
4213       {R"txt(
4214 SimpleDeclaration
4215 |-'S'
4216 `-DeclaratorList Declarators
4217   `-SimpleDeclarator ListElement
4218     |-'s'
4219     |-'='
4220     `-IntegerLiteralExpression
4221       `-'1' LiteralToken
4222 )txt"}));
4223 }
4224 
4225 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Brace) {
4226   if (!GetParam().isCXX11OrLater()) {
4227     return;
4228   }
4229   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4230       R"cpp(
4231 struct S {
4232   S();
4233   S(int);
4234   S(int, float);
4235 };
4236 void test(){
4237   // FIXME: 's...' is a declarator and '{...}' is initializer
4238   [[S s0{}]];
4239   [[S s1{1}]];
4240   [[S s2{1, 2.}]];
4241 }
4242 )cpp",
4243       {R"txt(
4244 SimpleDeclaration
4245 |-'S'
4246 `-DeclaratorList Declarators
4247   `-SimpleDeclarator ListElement
4248     `-UnknownExpression
4249       |-'s0'
4250       |-'{'
4251       `-'}'
4252   )txt",
4253        R"txt(
4254 SimpleDeclaration
4255 |-'S'
4256 `-DeclaratorList Declarators
4257   `-SimpleDeclarator ListElement
4258     `-UnknownExpression
4259       |-'s1'
4260       |-'{'
4261       |-IntegerLiteralExpression
4262       | `-'1' LiteralToken
4263       `-'}'
4264   )txt",
4265        R"txt(
4266 SimpleDeclaration
4267 |-'S'
4268 `-DeclaratorList Declarators
4269   `-SimpleDeclarator ListElement
4270     `-UnknownExpression
4271       |-'s2'
4272       |-'{'
4273       |-IntegerLiteralExpression
4274       | `-'1' LiteralToken
4275       |-','
4276       |-FloatingLiteralExpression
4277       | `-'2.' LiteralToken
4278       `-'}'
4279 )txt"}));
4280 }
4281 
4282 TEST_P(BuildSyntaxTreeTest, InitDeclarator_EqualBrace) {
4283   if (!GetParam().isCXX11OrLater()) {
4284     return;
4285   }
4286   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4287       R"cpp(
4288 struct S {
4289   S();
4290   S(int);
4291   S(int, float);
4292 };
4293 void test() {
4294   // FIXME: '= {...}' is initializer
4295   [[S s0 = {}]];
4296   [[S s1 = {1}]];
4297   [[S s2 = {1, 2.}]];
4298 }
4299 )cpp",
4300       {R"txt(
4301 SimpleDeclaration
4302 |-'S'
4303 `-DeclaratorList Declarators
4304   `-SimpleDeclarator ListElement
4305     |-'s0'
4306     |-'='
4307     `-UnknownExpression
4308       |-'{'
4309       `-'}'
4310   )txt",
4311        R"txt(
4312 SimpleDeclaration
4313 |-'S'
4314 `-DeclaratorList Declarators
4315   `-SimpleDeclarator ListElement
4316     |-'s1'
4317     |-'='
4318     `-UnknownExpression
4319       |-'{'
4320       |-IntegerLiteralExpression
4321       | `-'1' LiteralToken
4322       `-'}'
4323   )txt",
4324        R"txt(
4325 SimpleDeclaration
4326 |-'S'
4327 `-DeclaratorList Declarators
4328   `-SimpleDeclarator ListElement
4329     |-'s2'
4330     |-'='
4331     `-UnknownExpression
4332       |-'{'
4333       |-IntegerLiteralExpression
4334       | `-'1' LiteralToken
4335       |-','
4336       |-FloatingLiteralExpression
4337       | `-'2.' LiteralToken
4338       `-'}'
4339 )txt"}));
4340 }
4341 
4342 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Paren) {
4343   if (!GetParam().isCXX()) {
4344     return;
4345   }
4346   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4347       R"cpp(
4348 struct S {
4349   S(int);
4350   S(int, float);
4351 };
4352 // FIXME: 's...' is a declarator and '(...)' is initializer
4353 [[S s1(1);]]
4354 [[S s2(1, 2.);]]
4355 )cpp",
4356       {R"txt(
4357 SimpleDeclaration
4358 |-'S'
4359 |-DeclaratorList Declarators
4360 | `-SimpleDeclarator ListElement
4361 |   `-UnknownExpression
4362 |     |-'s1'
4363 |     |-'('
4364 |     |-IntegerLiteralExpression
4365 |     | `-'1' LiteralToken
4366 |     `-')'
4367 `-';'
4368   )txt",
4369        R"txt(
4370 SimpleDeclaration
4371 |-'S'
4372 |-DeclaratorList Declarators
4373 | `-SimpleDeclarator ListElement
4374 |   `-UnknownExpression
4375 |     |-'s2'
4376 |     |-'('
4377 |     |-IntegerLiteralExpression
4378 |     | `-'1' LiteralToken
4379 |     |-','
4380 |     |-FloatingLiteralExpression
4381 |     | `-'2.' LiteralToken
4382 |     `-')'
4383 `-';'
4384 )txt"}));
4385 }
4386 
4387 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Paren_DefaultArguments) {
4388   if (!GetParam().isCXX()) {
4389     return;
4390   }
4391   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4392       R"cpp(
4393 struct S {
4394   S(int i = 1, float = 2.);
4395 };
4396 [[S s0;]]
4397 // FIXME: 's...' is a declarator and '(...)' is initializer
4398 [[S s1(1);]]
4399 [[S s2(1, 2.);]]
4400 )cpp",
4401       {R"txt(
4402 SimpleDeclaration
4403 |-'S'
4404 |-DeclaratorList Declarators
4405 | `-SimpleDeclarator ListElement
4406 |   `-'s0'
4407 `-';'
4408   )txt",
4409        R"txt(
4410 SimpleDeclaration
4411 |-'S'
4412 |-DeclaratorList Declarators
4413 | `-SimpleDeclarator ListElement
4414 |   `-UnknownExpression
4415 |     |-'s1'
4416 |     |-'('
4417 |     |-IntegerLiteralExpression
4418 |     | `-'1' LiteralToken
4419 |     `-')'
4420 `-';'
4421   )txt",
4422        R"txt(
4423 SimpleDeclaration
4424 |-'S'
4425 |-DeclaratorList Declarators
4426 | `-SimpleDeclarator ListElement
4427 |   `-UnknownExpression
4428 |     |-'s2'
4429 |     |-'('
4430 |     |-IntegerLiteralExpression
4431 |     | `-'1' LiteralToken
4432 |     |-','
4433 |     |-FloatingLiteralExpression
4434 |     | `-'2.' LiteralToken
4435 |     `-')'
4436 `-';'
4437 )txt"}));
4438 }
4439 
4440 TEST_P(BuildSyntaxTreeTest, ImplicitConversion_Argument) {
4441   if (!GetParam().isCXX()) {
4442     return;
4443   }
4444   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4445       R"cpp(
4446 struct X {
4447   X(int);
4448 };
4449 void TakeX(const X&);
4450 void test() {
4451   [[TakeX(1)]];
4452 }
4453 )cpp",
4454       {R"txt(
4455 CallExpression Expression
4456 |-IdExpression Callee
4457 | `-UnqualifiedId UnqualifiedId
4458 |   `-'TakeX'
4459 |-'(' OpenParen
4460 |-CallArguments Arguments
4461 | `-IntegerLiteralExpression ListElement
4462 |   `-'1' LiteralToken
4463 `-')' CloseParen
4464 )txt"}));
4465 }
4466 
4467 TEST_P(BuildSyntaxTreeTest, ImplicitConversion_Return) {
4468   if (!GetParam().isCXX()) {
4469     return;
4470   }
4471   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4472       R"cpp(
4473 struct X {
4474   X(int);
4475 };
4476 X CreateX(){
4477   [[return 1;]]
4478 }
4479 )cpp",
4480       {R"txt(
4481 ReturnStatement Statement
4482 |-'return' IntroducerKeyword
4483 |-IntegerLiteralExpression ReturnValue
4484 | `-'1' LiteralToken
4485 `-';'
4486 )txt"}));
4487 }
4488 
4489 TEST_P(BuildSyntaxTreeTest, ConstructorCall_ZeroArguments) {
4490   if (!GetParam().isCXX()) {
4491     return;
4492   }
4493   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4494       R"cpp(
4495 struct X {
4496   X();
4497 };
4498 X test() {
4499   [[return X();]]
4500 }
4501 )cpp",
4502       {R"txt(
4503 ReturnStatement Statement
4504 |-'return' IntroducerKeyword
4505 |-UnknownExpression ReturnValue
4506 | |-'X'
4507 | |-'('
4508 | `-')'
4509 `-';'
4510 )txt"}));
4511 }
4512 
4513 TEST_P(BuildSyntaxTreeTest, ConstructorCall_OneArgument) {
4514   if (!GetParam().isCXX()) {
4515     return;
4516   }
4517   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4518       R"cpp(
4519 struct X {
4520   X(int);
4521 };
4522 X test() {
4523   [[return X(1);]]
4524 }
4525 )cpp",
4526       {R"txt(
4527 ReturnStatement Statement
4528 |-'return' IntroducerKeyword
4529 |-UnknownExpression ReturnValue
4530 | |-'X'
4531 | |-'('
4532 | |-IntegerLiteralExpression
4533 | | `-'1' LiteralToken
4534 | `-')'
4535 `-';'
4536 )txt"}));
4537 }
4538 
4539 TEST_P(BuildSyntaxTreeTest, ConstructorCall_MultipleArguments) {
4540   if (!GetParam().isCXX()) {
4541     return;
4542   }
4543   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4544       R"cpp(
4545 struct X {
4546   X(int, char);
4547 };
4548 X test() {
4549   [[return X(1, '2');]]
4550 }
4551 )cpp",
4552       {R"txt(
4553 ReturnStatement Statement
4554 |-'return' IntroducerKeyword
4555 |-UnknownExpression ReturnValue
4556 | |-'X'
4557 | |-'('
4558 | |-IntegerLiteralExpression
4559 | | `-'1' LiteralToken
4560 | |-','
4561 | |-CharacterLiteralExpression
4562 | | `-''2'' LiteralToken
4563 | `-')'
4564 `-';'
4565 )txt"}));
4566 }
4567 
4568 TEST_P(BuildSyntaxTreeTest, ConstructorCall_DefaultArguments) {
4569   if (!GetParam().isCXX()) {
4570     return;
4571   }
4572   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4573       R"cpp(
4574 struct X {
4575   X(int i = 1, char c = '2');
4576 };
4577 X test() {
4578   auto x0 = [[X()]];
4579   auto x1 = [[X(1)]];
4580   auto x2 = [[X(1, '2')]];
4581 }
4582 )cpp",
4583       {R"txt(
4584 UnknownExpression
4585 |-'X'
4586 |-'('
4587 `-')'
4588 )txt",
4589        R"txt(
4590 UnknownExpression
4591 |-'X'
4592 |-'('
4593 |-IntegerLiteralExpression
4594 | `-'1' LiteralToken
4595 `-')'
4596 )txt",
4597        R"txt(
4598 UnknownExpression
4599 |-'X'
4600 |-'('
4601 |-IntegerLiteralExpression
4602 | `-'1' LiteralToken
4603 |-','
4604 |-CharacterLiteralExpression
4605 | `-''2'' LiteralToken
4606 `-')'
4607 )txt"}));
4608 }
4609 
4610 TEST_P(BuildSyntaxTreeTest, TypeConversion_FunctionalNotation) {
4611   if (!GetParam().isCXX()) {
4612     return;
4613   }
4614   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4615       R"cpp(
4616 float test() {
4617   [[return float(1);]]
4618 }
4619 )cpp",
4620       {R"txt(
4621 ReturnStatement Statement
4622 |-'return' IntroducerKeyword
4623 |-UnknownExpression ReturnValue
4624 | |-'float'
4625 | |-'('
4626 | |-IntegerLiteralExpression
4627 | | `-'1' LiteralToken
4628 | `-')'
4629 `-';'
4630 )txt"}));
4631 }
4632 
4633 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Simple) {
4634   EXPECT_TRUE(treeDumpEqual(
4635       R"cpp(
4636 int a[10];
4637 )cpp",
4638       R"txt(
4639 TranslationUnit Detached
4640 `-SimpleDeclaration
4641   |-'int'
4642   |-DeclaratorList Declarators
4643   | `-SimpleDeclarator ListElement
4644   |   |-'a'
4645   |   `-ArraySubscript
4646   |     |-'[' OpenParen
4647   |     |-IntegerLiteralExpression Size
4648   |     | `-'10' LiteralToken
4649   |     `-']' CloseParen
4650   `-';'
4651 )txt"));
4652 }
4653 
4654 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Multidimensional) {
4655   EXPECT_TRUE(treeDumpEqual(
4656       R"cpp(
4657 int b[1][2][3];
4658 )cpp",
4659       R"txt(
4660 TranslationUnit Detached
4661 `-SimpleDeclaration
4662   |-'int'
4663   |-DeclaratorList Declarators
4664   | `-SimpleDeclarator ListElement
4665   |   |-'b'
4666   |   |-ArraySubscript
4667   |   | |-'[' OpenParen
4668   |   | |-IntegerLiteralExpression Size
4669   |   | | `-'1' LiteralToken
4670   |   | `-']' CloseParen
4671   |   |-ArraySubscript
4672   |   | |-'[' OpenParen
4673   |   | |-IntegerLiteralExpression Size
4674   |   | | `-'2' LiteralToken
4675   |   | `-']' CloseParen
4676   |   `-ArraySubscript
4677   |     |-'[' OpenParen
4678   |     |-IntegerLiteralExpression Size
4679   |     | `-'3' LiteralToken
4680   |     `-']' CloseParen
4681   `-';'
4682 )txt"));
4683 }
4684 
4685 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_UnknownBound) {
4686   EXPECT_TRUE(treeDumpEqual(
4687       R"cpp(
4688 int c[] = {1,2,3};
4689 )cpp",
4690       R"txt(
4691 TranslationUnit Detached
4692 `-SimpleDeclaration
4693   |-'int'
4694   |-DeclaratorList Declarators
4695   | `-SimpleDeclarator ListElement
4696   |   |-'c'
4697   |   |-ArraySubscript
4698   |   | |-'[' OpenParen
4699   |   | `-']' CloseParen
4700   |   |-'='
4701   |   `-UnknownExpression
4702   |     `-UnknownExpression
4703   |       |-'{'
4704   |       |-IntegerLiteralExpression
4705   |       | `-'1' LiteralToken
4706   |       |-','
4707   |       |-IntegerLiteralExpression
4708   |       | `-'2' LiteralToken
4709   |       |-','
4710   |       |-IntegerLiteralExpression
4711   |       | `-'3' LiteralToken
4712   |       `-'}'
4713   `-';'
4714 )txt"));
4715 }
4716 
4717 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Static) {
4718   if (!GetParam().isC99OrLater()) {
4719     return;
4720   }
4721   EXPECT_TRUE(treeDumpEqual(
4722       R"cpp(
4723 void f(int xs[static 10]);
4724 )cpp",
4725       R"txt(
4726 TranslationUnit Detached
4727 `-SimpleDeclaration
4728   |-'void'
4729   |-DeclaratorList Declarators
4730   | `-SimpleDeclarator ListElement
4731   |   |-'f'
4732   |   `-ParametersAndQualifiers
4733   |     |-'(' OpenParen
4734   |     |-ParameterDeclarationList Parameters
4735   |     | `-SimpleDeclaration ListElement
4736   |     |   |-'int'
4737   |     |   `-DeclaratorList Declarators
4738   |     |     `-SimpleDeclarator ListElement
4739   |     |       |-'xs'
4740   |     |       `-ArraySubscript
4741   |     |         |-'[' OpenParen
4742   |     |         |-'static'
4743   |     |         |-IntegerLiteralExpression Size
4744   |     |         | `-'10' LiteralToken
4745   |     |         `-']' CloseParen
4746   |     `-')' CloseParen
4747   `-';'
4748 )txt"));
4749 }
4750 
4751 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) {
4752   EXPECT_TRUE(treeDumpEqual(
4753       R"cpp(
4754 int func();
4755 )cpp",
4756       R"txt(
4757 TranslationUnit Detached
4758 `-SimpleDeclaration
4759   |-'int'
4760   |-DeclaratorList Declarators
4761   | `-SimpleDeclarator ListElement
4762   |   |-'func'
4763   |   `-ParametersAndQualifiers
4764   |     |-'(' OpenParen
4765   |     `-')' CloseParen
4766   `-';'
4767 )txt"));
4768 }
4769 
4770 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) {
4771   EXPECT_TRUE(treeDumpEqual(
4772       R"cpp(
4773 int func1(int a);
4774 int func2(int *ap);
4775 int func3(int a, float b);
4776 )cpp",
4777       R"txt(
4778 TranslationUnit Detached
4779 |-SimpleDeclaration
4780 | |-'int'
4781 | |-DeclaratorList Declarators
4782 | | `-SimpleDeclarator ListElement
4783 | |   |-'func1'
4784 | |   `-ParametersAndQualifiers
4785 | |     |-'(' OpenParen
4786 | |     |-ParameterDeclarationList Parameters
4787 | |     | `-SimpleDeclaration ListElement
4788 | |     |   |-'int'
4789 | |     |   `-DeclaratorList Declarators
4790 | |     |     `-SimpleDeclarator ListElement
4791 | |     |       `-'a'
4792 | |     `-')' CloseParen
4793 | `-';'
4794 |-SimpleDeclaration
4795 | |-'int'
4796 | |-DeclaratorList Declarators
4797 | | `-SimpleDeclarator ListElement
4798 | |   |-'func2'
4799 | |   `-ParametersAndQualifiers
4800 | |     |-'(' OpenParen
4801 | |     |-ParameterDeclarationList Parameters
4802 | |     | `-SimpleDeclaration ListElement
4803 | |     |   |-'int'
4804 | |     |   `-DeclaratorList Declarators
4805 | |     |     `-SimpleDeclarator ListElement
4806 | |     |       |-'*'
4807 | |     |       `-'ap'
4808 | |     `-')' CloseParen
4809 | `-';'
4810 `-SimpleDeclaration
4811   |-'int'
4812   |-DeclaratorList Declarators
4813   | `-SimpleDeclarator ListElement
4814   |   |-'func3'
4815   |   `-ParametersAndQualifiers
4816   |     |-'(' OpenParen
4817   |     |-ParameterDeclarationList Parameters
4818   |     | |-SimpleDeclaration ListElement
4819   |     | | |-'int'
4820   |     | | `-DeclaratorList Declarators
4821   |     | |   `-SimpleDeclarator ListElement
4822   |     | |     `-'a'
4823   |     | |-',' ListDelimiter
4824   |     | `-SimpleDeclaration ListElement
4825   |     |   |-'float'
4826   |     |   `-DeclaratorList Declarators
4827   |     |     `-SimpleDeclarator ListElement
4828   |     |       `-'b'
4829   |     `-')' CloseParen
4830   `-';'
4831 )txt"));
4832 }
4833 
4834 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
4835   EXPECT_TRUE(treeDumpEqual(
4836       R"cpp(
4837 int func1(int);
4838 int func2(int *);
4839 int func3(int, float);
4840 )cpp",
4841       R"txt(
4842 TranslationUnit Detached
4843 |-SimpleDeclaration
4844 | |-'int'
4845 | |-DeclaratorList Declarators
4846 | | `-SimpleDeclarator ListElement
4847 | |   |-'func1'
4848 | |   `-ParametersAndQualifiers
4849 | |     |-'(' OpenParen
4850 | |     |-ParameterDeclarationList Parameters
4851 | |     | `-SimpleDeclaration ListElement
4852 | |     |   `-'int'
4853 | |     `-')' CloseParen
4854 | `-';'
4855 |-SimpleDeclaration
4856 | |-'int'
4857 | |-DeclaratorList Declarators
4858 | | `-SimpleDeclarator ListElement
4859 | |   |-'func2'
4860 | |   `-ParametersAndQualifiers
4861 | |     |-'(' OpenParen
4862 | |     |-ParameterDeclarationList Parameters
4863 | |     | `-SimpleDeclaration ListElement
4864 | |     |   |-'int'
4865 | |     |   `-DeclaratorList Declarators
4866 | |     |     `-SimpleDeclarator ListElement
4867 | |     |       `-'*'
4868 | |     `-')' CloseParen
4869 | `-';'
4870 `-SimpleDeclaration
4871   |-'int'
4872   |-DeclaratorList Declarators
4873   | `-SimpleDeclarator ListElement
4874   |   |-'func3'
4875   |   `-ParametersAndQualifiers
4876   |     |-'(' OpenParen
4877   |     |-ParameterDeclarationList Parameters
4878   |     | |-SimpleDeclaration ListElement
4879   |     | | `-'int'
4880   |     | |-',' ListDelimiter
4881   |     | `-SimpleDeclaration ListElement
4882   |     |   `-'float'
4883   |     `-')' CloseParen
4884   `-';'
4885 )txt"));
4886 }
4887 
4888 TEST_P(BuildSyntaxTreeTest,
4889        ParametersAndQualifiers_InFreeFunctions_Default_One) {
4890   if (!GetParam().isCXX()) {
4891     return;
4892   }
4893   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4894       R"cpp(
4895 int func1([[int a = 1]]);
4896 )cpp",
4897       {R"txt(
4898 ParameterDeclarationList Parameters
4899 `-SimpleDeclaration ListElement
4900   |-'int'
4901   `-DeclaratorList Declarators
4902     `-SimpleDeclarator ListElement
4903       |-'a'
4904       |-'='
4905       `-IntegerLiteralExpression
4906         `-'1' LiteralToken
4907 )txt"}));
4908 }
4909 
4910 TEST_P(BuildSyntaxTreeTest,
4911        ParametersAndQualifiers_InFreeFunctions_Default_Multiple) {
4912   if (!GetParam().isCXX()) {
4913     return;
4914   }
4915   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4916       R"cpp(
4917 int func2([[int *ap, int a = 1, char c = '2']]);
4918 )cpp",
4919       {R"txt(
4920 ParameterDeclarationList Parameters
4921 |-SimpleDeclaration ListElement
4922 | |-'int'
4923 | `-DeclaratorList Declarators
4924 |   `-SimpleDeclarator ListElement
4925 |     |-'*'
4926 |     `-'ap'
4927 |-',' ListDelimiter
4928 |-SimpleDeclaration ListElement
4929 | |-'int'
4930 | `-DeclaratorList Declarators
4931 |   `-SimpleDeclarator ListElement
4932 |     |-'a'
4933 |     |-'='
4934 |     `-IntegerLiteralExpression
4935 |       `-'1' LiteralToken
4936 |-',' ListDelimiter
4937 `-SimpleDeclaration ListElement
4938   |-'char'
4939   `-DeclaratorList Declarators
4940     `-SimpleDeclarator ListElement
4941       |-'c'
4942       |-'='
4943       `-CharacterLiteralExpression
4944         `-''2'' LiteralToken
4945 )txt"}));
4946 }
4947 
4948 TEST_P(BuildSyntaxTreeTest,
4949        ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) {
4950   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4951     return;
4952   }
4953   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4954       R"cpp(
4955 template<typename T, typename... Args>
4956 [[void test(T , Args... );]]
4957 )cpp",
4958       {R"txt(
4959 SimpleDeclaration
4960 |-'void'
4961 |-DeclaratorList Declarators
4962 | `-SimpleDeclarator ListElement
4963 |   |-'test'
4964 |   `-ParametersAndQualifiers
4965 |     |-'(' OpenParen
4966 |     |-ParameterDeclarationList Parameters
4967 |     | |-SimpleDeclaration ListElement
4968 |     | | `-'T'
4969 |     | |-',' ListDelimiter
4970 |     | `-SimpleDeclaration ListElement
4971 |     |   |-'Args'
4972 |     |   `-'...'
4973 |     `-')' CloseParen
4974 `-';'
4975 )txt"}));
4976 }
4977 
4978 TEST_P(BuildSyntaxTreeTest,
4979        ParametersAndQualifiers_InVariadicFunctionTemplate_NamedParameterPack) {
4980   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4981     return;
4982   }
4983   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4984       R"cpp(
4985 template<typename T, typename... Args>
4986 [[void test(T t, Args... args);]]
4987 )cpp",
4988       {R"txt(
4989 SimpleDeclaration
4990 |-'void'
4991 |-DeclaratorList Declarators
4992 | `-SimpleDeclarator ListElement
4993 |   |-'test'
4994 |   `-ParametersAndQualifiers
4995 |     |-'(' OpenParen
4996 |     |-ParameterDeclarationList Parameters
4997 |     | |-SimpleDeclaration ListElement
4998 |     | | |-'T'
4999 |     | | `-DeclaratorList Declarators
5000 |     | |   `-SimpleDeclarator ListElement
5001 |     | |     `-'t'
5002 |     | |-',' ListDelimiter
5003 |     | `-SimpleDeclaration ListElement
5004 |     |   |-'Args'
5005 |     |   |-'...'
5006 |     |   `-DeclaratorList Declarators
5007 |     |     `-SimpleDeclarator ListElement
5008 |     |       `-'args'
5009 |     `-')' CloseParen
5010 `-';'
5011 )txt"}));
5012 }
5013 
5014 TEST_P(BuildSyntaxTreeTest,
5015        ParametersAndQualifiers_InFreeFunctions_VariadicArguments) {
5016   if (!GetParam().isCXX11OrLater()) {
5017     return;
5018   }
5019   EXPECT_TRUE(treeDumpEqual(
5020       R"cpp(
5021 void test(int , char ...);
5022 )cpp",
5023       R"txt(
5024 TranslationUnit Detached
5025 `-SimpleDeclaration
5026   |-'void'
5027   |-DeclaratorList Declarators
5028   | `-SimpleDeclarator ListElement
5029   |   |-'test'
5030   |   `-ParametersAndQualifiers
5031   |     |-'(' OpenParen
5032   |     |-ParameterDeclarationList Parameters
5033   |     | |-SimpleDeclaration ListElement
5034   |     | | `-'int'
5035   |     | |-',' ListDelimiter
5036   |     | `-SimpleDeclaration ListElement
5037   |     |   `-'char'
5038   |     |-'...'
5039   |     `-')' CloseParen
5040   `-';'
5041 )txt"));
5042 }
5043 
5044 TEST_P(BuildSyntaxTreeTest,
5045        ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
5046   if (!GetParam().isCXX()) {
5047     return;
5048   }
5049   EXPECT_TRUE(treeDumpEqual(
5050       R"cpp(
5051 int func(const int a, volatile int b, const volatile int c);
5052 )cpp",
5053       R"txt(
5054 TranslationUnit Detached
5055 `-SimpleDeclaration
5056   |-'int'
5057   |-DeclaratorList Declarators
5058   | `-SimpleDeclarator ListElement
5059   |   |-'func'
5060   |   `-ParametersAndQualifiers
5061   |     |-'(' OpenParen
5062   |     |-ParameterDeclarationList Parameters
5063   |     | |-SimpleDeclaration ListElement
5064   |     | | |-'const'
5065   |     | | |-'int'
5066   |     | | `-DeclaratorList Declarators
5067   |     | |   `-SimpleDeclarator ListElement
5068   |     | |     `-'a'
5069   |     | |-',' ListDelimiter
5070   |     | |-SimpleDeclaration ListElement
5071   |     | | |-'volatile'
5072   |     | | |-'int'
5073   |     | | `-DeclaratorList Declarators
5074   |     | |   `-SimpleDeclarator ListElement
5075   |     | |     `-'b'
5076   |     | |-',' ListDelimiter
5077   |     | `-SimpleDeclaration ListElement
5078   |     |   |-'const'
5079   |     |   |-'volatile'
5080   |     |   |-'int'
5081   |     |   `-DeclaratorList Declarators
5082   |     |     `-SimpleDeclarator ListElement
5083   |     |       `-'c'
5084   |     `-')' CloseParen
5085   `-';'
5086 )txt"));
5087 }
5088 
5089 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
5090   if (!GetParam().isCXX()) {
5091     return;
5092   }
5093   EXPECT_TRUE(treeDumpEqual(
5094       R"cpp(
5095 int func(int& a);
5096 )cpp",
5097       R"txt(
5098 TranslationUnit Detached
5099 `-SimpleDeclaration
5100   |-'int'
5101   |-DeclaratorList Declarators
5102   | `-SimpleDeclarator ListElement
5103   |   |-'func'
5104   |   `-ParametersAndQualifiers
5105   |     |-'(' OpenParen
5106   |     |-ParameterDeclarationList Parameters
5107   |     | `-SimpleDeclaration ListElement
5108   |     |   |-'int'
5109   |     |   `-DeclaratorList Declarators
5110   |     |     `-SimpleDeclarator ListElement
5111   |     |       |-'&'
5112   |     |       `-'a'
5113   |     `-')' CloseParen
5114   `-';'
5115 )txt"));
5116 }
5117 
5118 TEST_P(BuildSyntaxTreeTest,
5119        ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
5120   if (!GetParam().isCXX11OrLater()) {
5121     return;
5122   }
5123   EXPECT_TRUE(treeDumpEqual(
5124       R"cpp(
5125 int func(int&& a);
5126 )cpp",
5127       R"txt(
5128 TranslationUnit Detached
5129 `-SimpleDeclaration
5130   |-'int'
5131   |-DeclaratorList Declarators
5132   | `-SimpleDeclarator ListElement
5133   |   |-'func'
5134   |   `-ParametersAndQualifiers
5135   |     |-'(' OpenParen
5136   |     |-ParameterDeclarationList Parameters
5137   |     | `-SimpleDeclaration ListElement
5138   |     |   |-'int'
5139   |     |   `-DeclaratorList Declarators
5140   |     |     `-SimpleDeclarator ListElement
5141   |     |       |-'&&'
5142   |     |       `-'a'
5143   |     `-')' CloseParen
5144   `-';'
5145 )txt"));
5146 }
5147 
5148 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
5149   if (!GetParam().isCXX()) {
5150     return;
5151   }
5152   EXPECT_TRUE(treeDumpEqual(
5153       R"cpp(
5154 struct Test {
5155   int a();
5156 };
5157 )cpp",
5158       R"txt(
5159 TranslationUnit Detached
5160 `-SimpleDeclaration
5161   |-'struct'
5162   |-'Test'
5163   |-'{'
5164   |-SimpleDeclaration
5165   | |-'int'
5166   | |-DeclaratorList Declarators
5167   | | `-SimpleDeclarator ListElement
5168   | |   |-'a'
5169   | |   `-ParametersAndQualifiers
5170   | |     |-'(' OpenParen
5171   | |     `-')' CloseParen
5172   | `-';'
5173   |-'}'
5174   `-';'
5175 )txt"));
5176 }
5177 
5178 TEST_P(BuildSyntaxTreeTest,
5179        ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
5180   if (!GetParam().isCXX()) {
5181     return;
5182   }
5183   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5184       R"cpp(
5185 struct Test {
5186   [[int b() const;]]
5187   [[int c() volatile;]]
5188   [[int d() const volatile;]]
5189 };
5190 )cpp",
5191       {R"txt(
5192 SimpleDeclaration
5193 |-'int'
5194 |-DeclaratorList Declarators
5195 | `-SimpleDeclarator ListElement
5196 |   |-'b'
5197 |   `-ParametersAndQualifiers
5198 |     |-'(' OpenParen
5199 |     |-')' CloseParen
5200 |     `-'const'
5201 `-';'
5202 )txt",
5203        R"txt(
5204 SimpleDeclaration
5205 |-'int'
5206 |-DeclaratorList Declarators
5207 | `-SimpleDeclarator ListElement
5208 |   |-'c'
5209 |   `-ParametersAndQualifiers
5210 |     |-'(' OpenParen
5211 |     |-')' CloseParen
5212 |     `-'volatile'
5213 `-';'
5214 )txt",
5215        R"txt(
5216 SimpleDeclaration
5217 |-'int'
5218 |-DeclaratorList Declarators
5219 | `-SimpleDeclarator ListElement
5220 |   |-'d'
5221 |   `-ParametersAndQualifiers
5222 |     |-'(' OpenParen
5223 |     |-')' CloseParen
5224 |     |-'const'
5225 |     `-'volatile'
5226 `-';'
5227 )txt"}));
5228 }
5229 
5230 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
5231   if (!GetParam().isCXX11OrLater()) {
5232     return;
5233   }
5234   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5235       R"cpp(
5236 struct Test {
5237   [[int e() &;]]
5238 };
5239 )cpp",
5240       {R"txt(
5241 SimpleDeclaration
5242 |-'int'
5243 |-DeclaratorList Declarators
5244 | `-SimpleDeclarator ListElement
5245 |   |-'e'
5246 |   `-ParametersAndQualifiers
5247 |     |-'(' OpenParen
5248 |     |-')' CloseParen
5249 |     `-'&'
5250 `-';'
5251 )txt"}));
5252 }
5253 
5254 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
5255   if (!GetParam().isCXX11OrLater()) {
5256     return;
5257   }
5258   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5259       R"cpp(
5260 struct Test {
5261   [[int f() &&;]]
5262 };
5263 )cpp",
5264       {R"txt(
5265 SimpleDeclaration
5266 |-'int'
5267 |-DeclaratorList Declarators
5268 | `-SimpleDeclarator ListElement
5269 |   |-'f'
5270 |   `-ParametersAndQualifiers
5271 |     |-'(' OpenParen
5272 |     |-')' CloseParen
5273 |     `-'&&'
5274 `-';'
5275 )txt"}));
5276 }
5277 
5278 TEST_P(BuildSyntaxTreeTest, TrailingReturn) {
5279   if (!GetParam().isCXX11OrLater()) {
5280     return;
5281   }
5282   EXPECT_TRUE(treeDumpEqual(
5283       R"cpp(
5284 auto foo() -> int;
5285 )cpp",
5286       R"txt(
5287 TranslationUnit Detached
5288 `-SimpleDeclaration
5289   |-'auto'
5290   |-DeclaratorList Declarators
5291   | `-SimpleDeclarator ListElement
5292   |   |-'foo'
5293   |   `-ParametersAndQualifiers
5294   |     |-'(' OpenParen
5295   |     |-')' CloseParen
5296   |     `-TrailingReturnType TrailingReturn
5297   |       |-'->' ArrowToken
5298   |       `-'int'
5299   `-';'
5300 )txt"));
5301 }
5302 
5303 TEST_P(BuildSyntaxTreeTest, DynamicExceptionSpecification) {
5304   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
5305     return;
5306   }
5307   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5308       R"cpp(
5309 struct MyException1 {};
5310 struct MyException2 {};
5311 [[int a() throw();]]
5312 [[int b() throw(...);]]
5313 [[int c() throw(MyException1);]]
5314 [[int d() throw(MyException1, MyException2);]]
5315 )cpp",
5316       {R"txt(
5317 SimpleDeclaration
5318 |-'int'
5319 |-DeclaratorList Declarators
5320 | `-SimpleDeclarator ListElement
5321 |   |-'a'
5322 |   `-ParametersAndQualifiers
5323 |     |-'(' OpenParen
5324 |     |-')' CloseParen
5325 |     |-'throw'
5326 |     |-'('
5327 |     `-')'
5328 `-';'
5329 )txt",
5330        R"txt(
5331 SimpleDeclaration
5332 |-'int'
5333 |-DeclaratorList Declarators
5334 | `-SimpleDeclarator ListElement
5335 |   |-'b'
5336 |   `-ParametersAndQualifiers
5337 |     |-'(' OpenParen
5338 |     |-')' CloseParen
5339 |     |-'throw'
5340 |     |-'('
5341 |     |-'...'
5342 |     `-')'
5343 `-';'
5344 )txt",
5345        R"txt(
5346 SimpleDeclaration
5347 |-'int'
5348 |-DeclaratorList Declarators
5349 | `-SimpleDeclarator ListElement
5350 |   |-'c'
5351 |   `-ParametersAndQualifiers
5352 |     |-'(' OpenParen
5353 |     |-')' CloseParen
5354 |     |-'throw'
5355 |     |-'('
5356 |     |-'MyException1'
5357 |     `-')'
5358 `-';'
5359 )txt",
5360        R"txt(
5361 SimpleDeclaration
5362 |-'int'
5363 |-DeclaratorList Declarators
5364 | `-SimpleDeclarator ListElement
5365 |   |-'d'
5366 |   `-ParametersAndQualifiers
5367 |     |-'(' OpenParen
5368 |     |-')' CloseParen
5369 |     |-'throw'
5370 |     |-'('
5371 |     |-'MyException1'
5372 |     |-','
5373 |     |-'MyException2'
5374 |     `-')'
5375 `-';'
5376 )txt"}));
5377 }
5378 
5379 TEST_P(BuildSyntaxTreeTest, NoexceptExceptionSpecification) {
5380   if (!GetParam().isCXX11OrLater()) {
5381     return;
5382   }
5383   EXPECT_TRUE(treeDumpEqual(
5384       R"cpp(
5385 int a() noexcept;
5386 int b() noexcept(true);
5387 )cpp",
5388       R"txt(
5389 TranslationUnit Detached
5390 |-SimpleDeclaration
5391 | |-'int'
5392 | |-DeclaratorList Declarators
5393 | | `-SimpleDeclarator ListElement
5394 | |   |-'a'
5395 | |   `-ParametersAndQualifiers
5396 | |     |-'(' OpenParen
5397 | |     |-')' CloseParen
5398 | |     `-'noexcept'
5399 | `-';'
5400 `-SimpleDeclaration
5401   |-'int'
5402   |-DeclaratorList Declarators
5403   | `-SimpleDeclarator ListElement
5404   |   |-'b'
5405   |   `-ParametersAndQualifiers
5406   |     |-'(' OpenParen
5407   |     |-')' CloseParen
5408   |     |-'noexcept'
5409   |     |-'('
5410   |     |-BoolLiteralExpression
5411   |     | `-'true' LiteralToken
5412   |     `-')'
5413   `-';'
5414 )txt"));
5415 }
5416 
5417 TEST_P(BuildSyntaxTreeTest, DeclaratorsInParentheses) {
5418   EXPECT_TRUE(treeDumpEqual(
5419       R"cpp(
5420 int (a);
5421 int *(b);
5422 int (*c)(int);
5423 int *(d)(int);
5424 )cpp",
5425       R"txt(
5426 TranslationUnit Detached
5427 |-SimpleDeclaration
5428 | |-'int'
5429 | |-DeclaratorList Declarators
5430 | | `-SimpleDeclarator ListElement
5431 | |   `-ParenDeclarator
5432 | |     |-'(' OpenParen
5433 | |     |-'a'
5434 | |     `-')' CloseParen
5435 | `-';'
5436 |-SimpleDeclaration
5437 | |-'int'
5438 | |-DeclaratorList Declarators
5439 | | `-SimpleDeclarator ListElement
5440 | |   |-'*'
5441 | |   `-ParenDeclarator
5442 | |     |-'(' OpenParen
5443 | |     |-'b'
5444 | |     `-')' CloseParen
5445 | `-';'
5446 |-SimpleDeclaration
5447 | |-'int'
5448 | |-DeclaratorList Declarators
5449 | | `-SimpleDeclarator ListElement
5450 | |   |-ParenDeclarator
5451 | |   | |-'(' OpenParen
5452 | |   | |-'*'
5453 | |   | |-'c'
5454 | |   | `-')' CloseParen
5455 | |   `-ParametersAndQualifiers
5456 | |     |-'(' OpenParen
5457 | |     |-ParameterDeclarationList Parameters
5458 | |     | `-SimpleDeclaration ListElement
5459 | |     |   `-'int'
5460 | |     `-')' CloseParen
5461 | `-';'
5462 `-SimpleDeclaration
5463   |-'int'
5464   |-DeclaratorList Declarators
5465   | `-SimpleDeclarator ListElement
5466   |   |-'*'
5467   |   |-ParenDeclarator
5468   |   | |-'(' OpenParen
5469   |   | |-'d'
5470   |   | `-')' CloseParen
5471   |   `-ParametersAndQualifiers
5472   |     |-'(' OpenParen
5473   |     |-ParameterDeclarationList Parameters
5474   |     | `-SimpleDeclaration ListElement
5475   |     |   `-'int'
5476   |     `-')' CloseParen
5477   `-';'
5478 )txt"));
5479 }
5480 
5481 TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
5482   EXPECT_TRUE(treeDumpEqual(
5483       R"cpp(
5484 const int west = -1;
5485 int const east = 1;
5486 )cpp",
5487       R"txt(
5488 TranslationUnit Detached
5489 |-SimpleDeclaration
5490 | |-'const'
5491 | |-'int'
5492 | |-DeclaratorList Declarators
5493 | | `-SimpleDeclarator ListElement
5494 | |   |-'west'
5495 | |   |-'='
5496 | |   `-PrefixUnaryOperatorExpression
5497 | |     |-'-' OperatorToken
5498 | |     `-IntegerLiteralExpression Operand
5499 | |       `-'1' LiteralToken
5500 | `-';'
5501 `-SimpleDeclaration
5502   |-'int'
5503   |-'const'
5504   |-DeclaratorList Declarators
5505   | `-SimpleDeclarator ListElement
5506   |   |-'east'
5507   |   |-'='
5508   |   `-IntegerLiteralExpression
5509   |     `-'1' LiteralToken
5510   `-';'
5511 )txt"));
5512 }
5513 
5514 TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
5515   EXPECT_TRUE(treeDumpEqual(
5516       R"cpp(
5517 const int const universal = 0;
5518 )cpp",
5519       R"txt(
5520 TranslationUnit Detached
5521 `-SimpleDeclaration
5522   |-'const'
5523   |-'int'
5524   |-'const'
5525   |-DeclaratorList Declarators
5526   | `-SimpleDeclarator ListElement
5527   |   |-'universal'
5528   |   |-'='
5529   |   `-IntegerLiteralExpression
5530   |     `-'0' LiteralToken
5531   `-';'
5532 )txt"));
5533 }
5534 
5535 TEST_P(BuildSyntaxTreeTest,
5536        Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
5537   EXPECT_TRUE(treeDumpEqual(
5538       R"cpp(
5539 const int const *const *volatile b;
5540 )cpp",
5541       R"txt(
5542 TranslationUnit Detached
5543 `-SimpleDeclaration
5544   |-'const'
5545   |-'int'
5546   |-'const'
5547   |-DeclaratorList Declarators
5548   | `-SimpleDeclarator ListElement
5549   |   |-'*'
5550   |   |-'const'
5551   |   |-'*'
5552   |   |-'volatile'
5553   |   `-'b'
5554   `-';'
5555 )txt"));
5556 }
5557 
5558 TEST_P(BuildSyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
5559   if (!GetParam().isCXX11OrLater()) {
5560     return;
5561   }
5562   EXPECT_TRUE(treeDumpEqual(
5563       R"cpp(
5564 auto foo() -> auto(*)(int) -> double*;
5565 )cpp",
5566       R"txt(
5567 TranslationUnit Detached
5568 `-SimpleDeclaration
5569   |-'auto'
5570   |-DeclaratorList Declarators
5571   | `-SimpleDeclarator ListElement
5572   |   |-'foo'
5573   |   `-ParametersAndQualifiers
5574   |     |-'(' OpenParen
5575   |     |-')' CloseParen
5576   |     `-TrailingReturnType TrailingReturn
5577   |       |-'->' ArrowToken
5578   |       |-'auto'
5579   |       `-SimpleDeclarator Declarator
5580   |         |-ParenDeclarator
5581   |         | |-'(' OpenParen
5582   |         | |-'*'
5583   |         | `-')' CloseParen
5584   |         `-ParametersAndQualifiers
5585   |           |-'(' OpenParen
5586   |           |-ParameterDeclarationList Parameters
5587   |           | `-SimpleDeclaration ListElement
5588   |           |   `-'int'
5589   |           |-')' CloseParen
5590   |           `-TrailingReturnType TrailingReturn
5591   |             |-'->' ArrowToken
5592   |             |-'double'
5593   |             `-SimpleDeclarator Declarator
5594   |               `-'*'
5595   `-';'
5596 )txt"));
5597 }
5598 
5599 TEST_P(BuildSyntaxTreeTest, MemberPointers) {
5600   if (!GetParam().isCXX()) {
5601     return;
5602   }
5603   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5604       R"cpp(
5605 struct X {};
5606 [[int X::* a;]]
5607 [[const int X::* b;]]
5608 )cpp",
5609       {R"txt(
5610 SimpleDeclaration
5611 |-'int'
5612 |-DeclaratorList Declarators
5613 | `-SimpleDeclarator ListElement
5614 |   |-MemberPointer
5615 |   | |-'X'
5616 |   | |-'::'
5617 |   | `-'*'
5618 |   `-'a'
5619 `-';'
5620 )txt",
5621        R"txt(
5622 SimpleDeclaration
5623 |-'const'
5624 |-'int'
5625 |-DeclaratorList Declarators
5626 | `-SimpleDeclarator ListElement
5627 |   |-MemberPointer
5628 |   | |-'X'
5629 |   | |-'::'
5630 |   | `-'*'
5631 |   `-'b'
5632 `-';'
5633 )txt"}));
5634 }
5635 
5636 TEST_P(BuildSyntaxTreeTest, MemberFunctionPointer) {
5637   if (!GetParam().isCXX()) {
5638     return;
5639   }
5640   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5641       R"cpp(
5642 struct X {
5643   struct Y {};
5644 };
5645 [[void (X::*xp)();]]
5646 [[void (X::**xpp)(const int*);]]
5647 // FIXME: Generate the right syntax tree for this type,
5648 // i.e. create a syntax node for the outer member pointer
5649 [[void (X::Y::*xyp)(const int*, char);]]
5650 )cpp",
5651       {R"txt(
5652 SimpleDeclaration
5653 |-'void'
5654 |-DeclaratorList Declarators
5655 | `-SimpleDeclarator ListElement
5656 |   |-ParenDeclarator
5657 |   | |-'(' OpenParen
5658 |   | |-MemberPointer
5659 |   | | |-'X'
5660 |   | | |-'::'
5661 |   | | `-'*'
5662 |   | |-'xp'
5663 |   | `-')' CloseParen
5664 |   `-ParametersAndQualifiers
5665 |     |-'(' OpenParen
5666 |     `-')' CloseParen
5667 `-';'
5668 )txt",
5669        R"txt(
5670 SimpleDeclaration
5671 |-'void'
5672 |-DeclaratorList Declarators
5673 | `-SimpleDeclarator ListElement
5674 |   |-ParenDeclarator
5675 |   | |-'(' OpenParen
5676 |   | |-MemberPointer
5677 |   | | |-'X'
5678 |   | | |-'::'
5679 |   | | `-'*'
5680 |   | |-'*'
5681 |   | |-'xpp'
5682 |   | `-')' CloseParen
5683 |   `-ParametersAndQualifiers
5684 |     |-'(' OpenParen
5685 |     |-ParameterDeclarationList Parameters
5686 |     | `-SimpleDeclaration ListElement
5687 |     |   |-'const'
5688 |     |   |-'int'
5689 |     |   `-DeclaratorList Declarators
5690 |     |     `-SimpleDeclarator ListElement
5691 |     |       `-'*'
5692 |     `-')' CloseParen
5693 `-';'
5694 )txt",
5695        R"txt(
5696 SimpleDeclaration
5697 |-'void'
5698 |-DeclaratorList Declarators
5699 | `-SimpleDeclarator ListElement
5700 |   |-ParenDeclarator
5701 |   | |-'(' OpenParen
5702 |   | |-'X'
5703 |   | |-'::'
5704 |   | |-MemberPointer
5705 |   | | |-'Y'
5706 |   | | |-'::'
5707 |   | | `-'*'
5708 |   | |-'xyp'
5709 |   | `-')' CloseParen
5710 |   `-ParametersAndQualifiers
5711 |     |-'(' OpenParen
5712 |     |-ParameterDeclarationList Parameters
5713 |     | |-SimpleDeclaration ListElement
5714 |     | | |-'const'
5715 |     | | |-'int'
5716 |     | | `-DeclaratorList Declarators
5717 |     | |   `-SimpleDeclarator ListElement
5718 |     | |     `-'*'
5719 |     | |-',' ListDelimiter
5720 |     | `-SimpleDeclaration ListElement
5721 |     |   `-'char'
5722 |     `-')' CloseParen
5723 `-';'
5724 )txt"}));
5725 }
5726 
5727 TEST_P(BuildSyntaxTreeTest, ComplexDeclarator) {
5728   EXPECT_TRUE(treeDumpEqual(
5729       R"cpp(
5730 void x(char a, short (*b)(int));
5731 )cpp",
5732       R"txt(
5733 TranslationUnit Detached
5734 `-SimpleDeclaration
5735   |-'void'
5736   |-DeclaratorList Declarators
5737   | `-SimpleDeclarator ListElement
5738   |   |-'x'
5739   |   `-ParametersAndQualifiers
5740   |     |-'(' OpenParen
5741   |     |-ParameterDeclarationList Parameters
5742   |     | |-SimpleDeclaration ListElement
5743   |     | | |-'char'
5744   |     | | `-DeclaratorList Declarators
5745   |     | |   `-SimpleDeclarator ListElement
5746   |     | |     `-'a'
5747   |     | |-',' ListDelimiter
5748   |     | `-SimpleDeclaration ListElement
5749   |     |   |-'short'
5750   |     |   `-DeclaratorList Declarators
5751   |     |     `-SimpleDeclarator ListElement
5752   |     |       |-ParenDeclarator
5753   |     |       | |-'(' OpenParen
5754   |     |       | |-'*'
5755   |     |       | |-'b'
5756   |     |       | `-')' CloseParen
5757   |     |       `-ParametersAndQualifiers
5758   |     |         |-'(' OpenParen
5759   |     |         |-ParameterDeclarationList Parameters
5760   |     |         | `-SimpleDeclaration ListElement
5761   |     |         |   `-'int'
5762   |     |         `-')' CloseParen
5763   |     `-')' CloseParen
5764   `-';'
5765 )txt"));
5766 }
5767 
5768 TEST_P(BuildSyntaxTreeTest, ComplexDeclarator2) {
5769   EXPECT_TRUE(treeDumpEqual(
5770       R"cpp(
5771 void x(char a, short (*b)(int), long (**c)(long long));
5772 )cpp",
5773       R"txt(
5774 TranslationUnit Detached
5775 `-SimpleDeclaration
5776   |-'void'
5777   |-DeclaratorList Declarators
5778   | `-SimpleDeclarator ListElement
5779   |   |-'x'
5780   |   `-ParametersAndQualifiers
5781   |     |-'(' OpenParen
5782   |     |-ParameterDeclarationList Parameters
5783   |     | |-SimpleDeclaration ListElement
5784   |     | | |-'char'
5785   |     | | `-DeclaratorList Declarators
5786   |     | |   `-SimpleDeclarator ListElement
5787   |     | |     `-'a'
5788   |     | |-',' ListDelimiter
5789   |     | |-SimpleDeclaration ListElement
5790   |     | | |-'short'
5791   |     | | `-DeclaratorList Declarators
5792   |     | |   `-SimpleDeclarator ListElement
5793   |     | |     |-ParenDeclarator
5794   |     | |     | |-'(' OpenParen
5795   |     | |     | |-'*'
5796   |     | |     | |-'b'
5797   |     | |     | `-')' CloseParen
5798   |     | |     `-ParametersAndQualifiers
5799   |     | |       |-'(' OpenParen
5800   |     | |       |-ParameterDeclarationList Parameters
5801   |     | |       | `-SimpleDeclaration ListElement
5802   |     | |       |   `-'int'
5803   |     | |       `-')' CloseParen
5804   |     | |-',' ListDelimiter
5805   |     | `-SimpleDeclaration ListElement
5806   |     |   |-'long'
5807   |     |   `-DeclaratorList Declarators
5808   |     |     `-SimpleDeclarator ListElement
5809   |     |       |-ParenDeclarator
5810   |     |       | |-'(' OpenParen
5811   |     |       | |-'*'
5812   |     |       | |-'*'
5813   |     |       | |-'c'
5814   |     |       | `-')' CloseParen
5815   |     |       `-ParametersAndQualifiers
5816   |     |         |-'(' OpenParen
5817   |     |         |-ParameterDeclarationList Parameters
5818   |     |         | `-SimpleDeclaration ListElement
5819   |     |         |   |-'long'
5820   |     |         |   `-'long'
5821   |     |         `-')' CloseParen
5822   |     `-')' CloseParen
5823   `-';'
5824 )txt"));
5825 }
5826 
5827 } // namespace
5828