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(treeDumpEqualOnAnnotations(
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 ParameterDeclarationList Parameters
4779 `-SimpleDeclaration ListElement
4780   |-'int'
4781   `-DeclaratorList Declarators
4782     `-SimpleDeclarator ListElement
4783       `-'a'
4784 )txt",
4785        R"txt(
4786 ParameterDeclarationList Parameters
4787 `-SimpleDeclaration ListElement
4788   |-'int'
4789   `-DeclaratorList Declarators
4790     `-SimpleDeclarator ListElement
4791       |-'*'
4792       `-'ap'
4793 )txt",
4794        R"txt(
4795 ParameterDeclarationList Parameters
4796 |-SimpleDeclaration ListElement
4797 | |-'int'
4798 | `-DeclaratorList Declarators
4799 |   `-SimpleDeclarator ListElement
4800 |     `-'a'
4801 |-',' ListDelimiter
4802 `-SimpleDeclaration ListElement
4803   |-'float'
4804   `-DeclaratorList Declarators
4805     `-SimpleDeclarator ListElement
4806       `-'b'
4807 )txt"}));
4808 }
4809 
4810 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
4811   EXPECT_TRUE(treeDumpEqual(
4812       R"cpp(
4813 int func1(int);
4814 int func2(int *);
4815 int func3(int, float);
4816 )cpp",
4817       R"txt(
4818 TranslationUnit Detached
4819 |-SimpleDeclaration
4820 | |-'int'
4821 | |-DeclaratorList Declarators
4822 | | `-SimpleDeclarator ListElement
4823 | |   |-'func1'
4824 | |   `-ParametersAndQualifiers
4825 | |     |-'(' OpenParen
4826 | |     |-ParameterDeclarationList Parameters
4827 | |     | `-SimpleDeclaration ListElement
4828 | |     |   `-'int'
4829 | |     `-')' CloseParen
4830 | `-';'
4831 |-SimpleDeclaration
4832 | |-'int'
4833 | |-DeclaratorList Declarators
4834 | | `-SimpleDeclarator ListElement
4835 | |   |-'func2'
4836 | |   `-ParametersAndQualifiers
4837 | |     |-'(' OpenParen
4838 | |     |-ParameterDeclarationList Parameters
4839 | |     | `-SimpleDeclaration ListElement
4840 | |     |   |-'int'
4841 | |     |   `-DeclaratorList Declarators
4842 | |     |     `-SimpleDeclarator ListElement
4843 | |     |       `-'*'
4844 | |     `-')' CloseParen
4845 | `-';'
4846 `-SimpleDeclaration
4847   |-'int'
4848   |-DeclaratorList Declarators
4849   | `-SimpleDeclarator ListElement
4850   |   |-'func3'
4851   |   `-ParametersAndQualifiers
4852   |     |-'(' OpenParen
4853   |     |-ParameterDeclarationList Parameters
4854   |     | |-SimpleDeclaration ListElement
4855   |     | | `-'int'
4856   |     | |-',' ListDelimiter
4857   |     | `-SimpleDeclaration ListElement
4858   |     |   `-'float'
4859   |     `-')' CloseParen
4860   `-';'
4861 )txt"));
4862 }
4863 
4864 TEST_P(BuildSyntaxTreeTest,
4865        ParametersAndQualifiers_InFreeFunctions_Default_One) {
4866   if (!GetParam().isCXX()) {
4867     return;
4868   }
4869   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4870       R"cpp(
4871 int func1([[int a = 1]]);
4872 )cpp",
4873       {R"txt(
4874 ParameterDeclarationList Parameters
4875 `-SimpleDeclaration ListElement
4876   |-'int'
4877   `-DeclaratorList Declarators
4878     `-SimpleDeclarator ListElement
4879       |-'a'
4880       |-'='
4881       `-IntegerLiteralExpression
4882         `-'1' LiteralToken
4883 )txt"}));
4884 }
4885 
4886 TEST_P(BuildSyntaxTreeTest,
4887        ParametersAndQualifiers_InFreeFunctions_Default_Multiple) {
4888   if (!GetParam().isCXX()) {
4889     return;
4890   }
4891   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4892       R"cpp(
4893 int func2([[int *ap, int a = 1, char c = '2']]);
4894 )cpp",
4895       {R"txt(
4896 ParameterDeclarationList Parameters
4897 |-SimpleDeclaration ListElement
4898 | |-'int'
4899 | `-DeclaratorList Declarators
4900 |   `-SimpleDeclarator ListElement
4901 |     |-'*'
4902 |     `-'ap'
4903 |-',' ListDelimiter
4904 |-SimpleDeclaration ListElement
4905 | |-'int'
4906 | `-DeclaratorList Declarators
4907 |   `-SimpleDeclarator ListElement
4908 |     |-'a'
4909 |     |-'='
4910 |     `-IntegerLiteralExpression
4911 |       `-'1' LiteralToken
4912 |-',' ListDelimiter
4913 `-SimpleDeclaration ListElement
4914   |-'char'
4915   `-DeclaratorList Declarators
4916     `-SimpleDeclarator ListElement
4917       |-'c'
4918       |-'='
4919       `-CharacterLiteralExpression
4920         `-''2'' LiteralToken
4921 )txt"}));
4922 }
4923 
4924 TEST_P(BuildSyntaxTreeTest,
4925        ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) {
4926   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4927     return;
4928   }
4929   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4930       R"cpp(
4931 template<typename T, typename... Args>
4932 [[void test(T , Args... );]]
4933 )cpp",
4934       {R"txt(
4935 SimpleDeclaration
4936 |-'void'
4937 |-DeclaratorList Declarators
4938 | `-SimpleDeclarator ListElement
4939 |   |-'test'
4940 |   `-ParametersAndQualifiers
4941 |     |-'(' OpenParen
4942 |     |-ParameterDeclarationList Parameters
4943 |     | |-SimpleDeclaration ListElement
4944 |     | | `-'T'
4945 |     | |-',' ListDelimiter
4946 |     | `-SimpleDeclaration ListElement
4947 |     |   |-'Args'
4948 |     |   `-'...'
4949 |     `-')' CloseParen
4950 `-';'
4951 )txt"}));
4952 }
4953 
4954 TEST_P(BuildSyntaxTreeTest,
4955        ParametersAndQualifiers_InVariadicFunctionTemplate_NamedParameterPack) {
4956   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4957     return;
4958   }
4959   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4960       R"cpp(
4961 template<typename T, typename... Args>
4962 [[void test(T t, Args... args);]]
4963 )cpp",
4964       {R"txt(
4965 SimpleDeclaration
4966 |-'void'
4967 |-DeclaratorList Declarators
4968 | `-SimpleDeclarator ListElement
4969 |   |-'test'
4970 |   `-ParametersAndQualifiers
4971 |     |-'(' OpenParen
4972 |     |-ParameterDeclarationList Parameters
4973 |     | |-SimpleDeclaration ListElement
4974 |     | | |-'T'
4975 |     | | `-DeclaratorList Declarators
4976 |     | |   `-SimpleDeclarator ListElement
4977 |     | |     `-'t'
4978 |     | |-',' ListDelimiter
4979 |     | `-SimpleDeclaration ListElement
4980 |     |   |-'Args'
4981 |     |   |-'...'
4982 |     |   `-DeclaratorList Declarators
4983 |     |     `-SimpleDeclarator ListElement
4984 |     |       `-'args'
4985 |     `-')' CloseParen
4986 `-';'
4987 )txt"}));
4988 }
4989 
4990 TEST_P(BuildSyntaxTreeTest,
4991        ParametersAndQualifiers_InFreeFunctions_VariadicArguments) {
4992   if (!GetParam().isCXX11OrLater()) {
4993     return;
4994   }
4995   EXPECT_TRUE(treeDumpEqual(
4996       R"cpp(
4997 void test(int , char ...);
4998 )cpp",
4999       R"txt(
5000 TranslationUnit Detached
5001 `-SimpleDeclaration
5002   |-'void'
5003   |-DeclaratorList Declarators
5004   | `-SimpleDeclarator ListElement
5005   |   |-'test'
5006   |   `-ParametersAndQualifiers
5007   |     |-'(' OpenParen
5008   |     |-ParameterDeclarationList Parameters
5009   |     | |-SimpleDeclaration ListElement
5010   |     | | `-'int'
5011   |     | |-',' ListDelimiter
5012   |     | `-SimpleDeclaration ListElement
5013   |     |   `-'char'
5014   |     |-'...'
5015   |     `-')' CloseParen
5016   `-';'
5017 )txt"));
5018 }
5019 
5020 TEST_P(BuildSyntaxTreeTest,
5021        ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
5022   if (!GetParam().isCXX()) {
5023     return;
5024   }
5025   EXPECT_TRUE(treeDumpEqual(
5026       R"cpp(
5027 int func(const int a, volatile int b, const volatile int c);
5028 )cpp",
5029       R"txt(
5030 TranslationUnit Detached
5031 `-SimpleDeclaration
5032   |-'int'
5033   |-DeclaratorList Declarators
5034   | `-SimpleDeclarator ListElement
5035   |   |-'func'
5036   |   `-ParametersAndQualifiers
5037   |     |-'(' OpenParen
5038   |     |-ParameterDeclarationList Parameters
5039   |     | |-SimpleDeclaration ListElement
5040   |     | | |-'const'
5041   |     | | |-'int'
5042   |     | | `-DeclaratorList Declarators
5043   |     | |   `-SimpleDeclarator ListElement
5044   |     | |     `-'a'
5045   |     | |-',' ListDelimiter
5046   |     | |-SimpleDeclaration ListElement
5047   |     | | |-'volatile'
5048   |     | | |-'int'
5049   |     | | `-DeclaratorList Declarators
5050   |     | |   `-SimpleDeclarator ListElement
5051   |     | |     `-'b'
5052   |     | |-',' ListDelimiter
5053   |     | `-SimpleDeclaration ListElement
5054   |     |   |-'const'
5055   |     |   |-'volatile'
5056   |     |   |-'int'
5057   |     |   `-DeclaratorList Declarators
5058   |     |     `-SimpleDeclarator ListElement
5059   |     |       `-'c'
5060   |     `-')' CloseParen
5061   `-';'
5062 )txt"));
5063 }
5064 
5065 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
5066   if (!GetParam().isCXX()) {
5067     return;
5068   }
5069   EXPECT_TRUE(treeDumpEqual(
5070       R"cpp(
5071 int func(int& a);
5072 )cpp",
5073       R"txt(
5074 TranslationUnit Detached
5075 `-SimpleDeclaration
5076   |-'int'
5077   |-DeclaratorList Declarators
5078   | `-SimpleDeclarator ListElement
5079   |   |-'func'
5080   |   `-ParametersAndQualifiers
5081   |     |-'(' OpenParen
5082   |     |-ParameterDeclarationList Parameters
5083   |     | `-SimpleDeclaration ListElement
5084   |     |   |-'int'
5085   |     |   `-DeclaratorList Declarators
5086   |     |     `-SimpleDeclarator ListElement
5087   |     |       |-'&'
5088   |     |       `-'a'
5089   |     `-')' CloseParen
5090   `-';'
5091 )txt"));
5092 }
5093 
5094 TEST_P(BuildSyntaxTreeTest,
5095        ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
5096   if (!GetParam().isCXX11OrLater()) {
5097     return;
5098   }
5099   EXPECT_TRUE(treeDumpEqual(
5100       R"cpp(
5101 int func(int&& a);
5102 )cpp",
5103       R"txt(
5104 TranslationUnit Detached
5105 `-SimpleDeclaration
5106   |-'int'
5107   |-DeclaratorList Declarators
5108   | `-SimpleDeclarator ListElement
5109   |   |-'func'
5110   |   `-ParametersAndQualifiers
5111   |     |-'(' OpenParen
5112   |     |-ParameterDeclarationList Parameters
5113   |     | `-SimpleDeclaration ListElement
5114   |     |   |-'int'
5115   |     |   `-DeclaratorList Declarators
5116   |     |     `-SimpleDeclarator ListElement
5117   |     |       |-'&&'
5118   |     |       `-'a'
5119   |     `-')' CloseParen
5120   `-';'
5121 )txt"));
5122 }
5123 
5124 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
5125   if (!GetParam().isCXX()) {
5126     return;
5127   }
5128   EXPECT_TRUE(treeDumpEqual(
5129       R"cpp(
5130 struct Test {
5131   int a();
5132 };
5133 )cpp",
5134       R"txt(
5135 TranslationUnit Detached
5136 `-SimpleDeclaration
5137   |-'struct'
5138   |-'Test'
5139   |-'{'
5140   |-SimpleDeclaration
5141   | |-'int'
5142   | |-DeclaratorList Declarators
5143   | | `-SimpleDeclarator ListElement
5144   | |   |-'a'
5145   | |   `-ParametersAndQualifiers
5146   | |     |-'(' OpenParen
5147   | |     `-')' CloseParen
5148   | `-';'
5149   |-'}'
5150   `-';'
5151 )txt"));
5152 }
5153 
5154 TEST_P(BuildSyntaxTreeTest,
5155        ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
5156   if (!GetParam().isCXX()) {
5157     return;
5158   }
5159   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5160       R"cpp(
5161 struct Test {
5162   [[int b() const;]]
5163   [[int c() volatile;]]
5164   [[int d() const volatile;]]
5165 };
5166 )cpp",
5167       {R"txt(
5168 SimpleDeclaration
5169 |-'int'
5170 |-DeclaratorList Declarators
5171 | `-SimpleDeclarator ListElement
5172 |   |-'b'
5173 |   `-ParametersAndQualifiers
5174 |     |-'(' OpenParen
5175 |     |-')' CloseParen
5176 |     `-'const'
5177 `-';'
5178 )txt",
5179        R"txt(
5180 SimpleDeclaration
5181 |-'int'
5182 |-DeclaratorList Declarators
5183 | `-SimpleDeclarator ListElement
5184 |   |-'c'
5185 |   `-ParametersAndQualifiers
5186 |     |-'(' OpenParen
5187 |     |-')' CloseParen
5188 |     `-'volatile'
5189 `-';'
5190 )txt",
5191        R"txt(
5192 SimpleDeclaration
5193 |-'int'
5194 |-DeclaratorList Declarators
5195 | `-SimpleDeclarator ListElement
5196 |   |-'d'
5197 |   `-ParametersAndQualifiers
5198 |     |-'(' OpenParen
5199 |     |-')' CloseParen
5200 |     |-'const'
5201 |     `-'volatile'
5202 `-';'
5203 )txt"}));
5204 }
5205 
5206 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
5207   if (!GetParam().isCXX11OrLater()) {
5208     return;
5209   }
5210   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5211       R"cpp(
5212 struct Test {
5213   [[int e() &;]]
5214 };
5215 )cpp",
5216       {R"txt(
5217 SimpleDeclaration
5218 |-'int'
5219 |-DeclaratorList Declarators
5220 | `-SimpleDeclarator ListElement
5221 |   |-'e'
5222 |   `-ParametersAndQualifiers
5223 |     |-'(' OpenParen
5224 |     |-')' CloseParen
5225 |     `-'&'
5226 `-';'
5227 )txt"}));
5228 }
5229 
5230 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
5231   if (!GetParam().isCXX11OrLater()) {
5232     return;
5233   }
5234   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5235       R"cpp(
5236 struct Test {
5237   [[int f() &&;]]
5238 };
5239 )cpp",
5240       {R"txt(
5241 SimpleDeclaration
5242 |-'int'
5243 |-DeclaratorList Declarators
5244 | `-SimpleDeclarator ListElement
5245 |   |-'f'
5246 |   `-ParametersAndQualifiers
5247 |     |-'(' OpenParen
5248 |     |-')' CloseParen
5249 |     `-'&&'
5250 `-';'
5251 )txt"}));
5252 }
5253 
5254 TEST_P(BuildSyntaxTreeTest, TrailingReturn) {
5255   if (!GetParam().isCXX11OrLater()) {
5256     return;
5257   }
5258   EXPECT_TRUE(treeDumpEqual(
5259       R"cpp(
5260 auto foo() -> int;
5261 )cpp",
5262       R"txt(
5263 TranslationUnit Detached
5264 `-SimpleDeclaration
5265   |-'auto'
5266   |-DeclaratorList Declarators
5267   | `-SimpleDeclarator ListElement
5268   |   |-'foo'
5269   |   `-ParametersAndQualifiers
5270   |     |-'(' OpenParen
5271   |     |-')' CloseParen
5272   |     `-TrailingReturnType TrailingReturn
5273   |       |-'->' ArrowToken
5274   |       `-'int'
5275   `-';'
5276 )txt"));
5277 }
5278 
5279 TEST_P(BuildSyntaxTreeTest, DynamicExceptionSpecification) {
5280   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
5281     return;
5282   }
5283   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5284       R"cpp(
5285 struct MyException1 {};
5286 struct MyException2 {};
5287 [[int a() throw();]]
5288 [[int b() throw(...);]]
5289 [[int c() throw(MyException1);]]
5290 [[int d() throw(MyException1, MyException2);]]
5291 )cpp",
5292       {R"txt(
5293 SimpleDeclaration
5294 |-'int'
5295 |-DeclaratorList Declarators
5296 | `-SimpleDeclarator ListElement
5297 |   |-'a'
5298 |   `-ParametersAndQualifiers
5299 |     |-'(' OpenParen
5300 |     |-')' CloseParen
5301 |     |-'throw'
5302 |     |-'('
5303 |     `-')'
5304 `-';'
5305 )txt",
5306        R"txt(
5307 SimpleDeclaration
5308 |-'int'
5309 |-DeclaratorList Declarators
5310 | `-SimpleDeclarator ListElement
5311 |   |-'b'
5312 |   `-ParametersAndQualifiers
5313 |     |-'(' OpenParen
5314 |     |-')' CloseParen
5315 |     |-'throw'
5316 |     |-'('
5317 |     |-'...'
5318 |     `-')'
5319 `-';'
5320 )txt",
5321        R"txt(
5322 SimpleDeclaration
5323 |-'int'
5324 |-DeclaratorList Declarators
5325 | `-SimpleDeclarator ListElement
5326 |   |-'c'
5327 |   `-ParametersAndQualifiers
5328 |     |-'(' OpenParen
5329 |     |-')' CloseParen
5330 |     |-'throw'
5331 |     |-'('
5332 |     |-'MyException1'
5333 |     `-')'
5334 `-';'
5335 )txt",
5336        R"txt(
5337 SimpleDeclaration
5338 |-'int'
5339 |-DeclaratorList Declarators
5340 | `-SimpleDeclarator ListElement
5341 |   |-'d'
5342 |   `-ParametersAndQualifiers
5343 |     |-'(' OpenParen
5344 |     |-')' CloseParen
5345 |     |-'throw'
5346 |     |-'('
5347 |     |-'MyException1'
5348 |     |-','
5349 |     |-'MyException2'
5350 |     `-')'
5351 `-';'
5352 )txt"}));
5353 }
5354 
5355 TEST_P(BuildSyntaxTreeTest, NoexceptExceptionSpecification) {
5356   if (!GetParam().isCXX11OrLater()) {
5357     return;
5358   }
5359   EXPECT_TRUE(treeDumpEqual(
5360       R"cpp(
5361 int a() noexcept;
5362 int b() noexcept(true);
5363 )cpp",
5364       R"txt(
5365 TranslationUnit Detached
5366 |-SimpleDeclaration
5367 | |-'int'
5368 | |-DeclaratorList Declarators
5369 | | `-SimpleDeclarator ListElement
5370 | |   |-'a'
5371 | |   `-ParametersAndQualifiers
5372 | |     |-'(' OpenParen
5373 | |     |-')' CloseParen
5374 | |     `-'noexcept'
5375 | `-';'
5376 `-SimpleDeclaration
5377   |-'int'
5378   |-DeclaratorList Declarators
5379   | `-SimpleDeclarator ListElement
5380   |   |-'b'
5381   |   `-ParametersAndQualifiers
5382   |     |-'(' OpenParen
5383   |     |-')' CloseParen
5384   |     |-'noexcept'
5385   |     |-'('
5386   |     |-BoolLiteralExpression
5387   |     | `-'true' LiteralToken
5388   |     `-')'
5389   `-';'
5390 )txt"));
5391 }
5392 
5393 TEST_P(BuildSyntaxTreeTest, DeclaratorsInParentheses) {
5394   EXPECT_TRUE(treeDumpEqual(
5395       R"cpp(
5396 int (a);
5397 int *(b);
5398 int (*c)(int);
5399 int *(d)(int);
5400 )cpp",
5401       R"txt(
5402 TranslationUnit Detached
5403 |-SimpleDeclaration
5404 | |-'int'
5405 | |-DeclaratorList Declarators
5406 | | `-SimpleDeclarator ListElement
5407 | |   `-ParenDeclarator
5408 | |     |-'(' OpenParen
5409 | |     |-'a'
5410 | |     `-')' CloseParen
5411 | `-';'
5412 |-SimpleDeclaration
5413 | |-'int'
5414 | |-DeclaratorList Declarators
5415 | | `-SimpleDeclarator ListElement
5416 | |   |-'*'
5417 | |   `-ParenDeclarator
5418 | |     |-'(' OpenParen
5419 | |     |-'b'
5420 | |     `-')' CloseParen
5421 | `-';'
5422 |-SimpleDeclaration
5423 | |-'int'
5424 | |-DeclaratorList Declarators
5425 | | `-SimpleDeclarator ListElement
5426 | |   |-ParenDeclarator
5427 | |   | |-'(' OpenParen
5428 | |   | |-'*'
5429 | |   | |-'c'
5430 | |   | `-')' CloseParen
5431 | |   `-ParametersAndQualifiers
5432 | |     |-'(' OpenParen
5433 | |     |-ParameterDeclarationList Parameters
5434 | |     | `-SimpleDeclaration ListElement
5435 | |     |   `-'int'
5436 | |     `-')' CloseParen
5437 | `-';'
5438 `-SimpleDeclaration
5439   |-'int'
5440   |-DeclaratorList Declarators
5441   | `-SimpleDeclarator ListElement
5442   |   |-'*'
5443   |   |-ParenDeclarator
5444   |   | |-'(' OpenParen
5445   |   | |-'d'
5446   |   | `-')' CloseParen
5447   |   `-ParametersAndQualifiers
5448   |     |-'(' OpenParen
5449   |     |-ParameterDeclarationList Parameters
5450   |     | `-SimpleDeclaration ListElement
5451   |     |   `-'int'
5452   |     `-')' CloseParen
5453   `-';'
5454 )txt"));
5455 }
5456 
5457 TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
5458   EXPECT_TRUE(treeDumpEqual(
5459       R"cpp(
5460 const int west = -1;
5461 int const east = 1;
5462 )cpp",
5463       R"txt(
5464 TranslationUnit Detached
5465 |-SimpleDeclaration
5466 | |-'const'
5467 | |-'int'
5468 | |-DeclaratorList Declarators
5469 | | `-SimpleDeclarator ListElement
5470 | |   |-'west'
5471 | |   |-'='
5472 | |   `-PrefixUnaryOperatorExpression
5473 | |     |-'-' OperatorToken
5474 | |     `-IntegerLiteralExpression Operand
5475 | |       `-'1' LiteralToken
5476 | `-';'
5477 `-SimpleDeclaration
5478   |-'int'
5479   |-'const'
5480   |-DeclaratorList Declarators
5481   | `-SimpleDeclarator ListElement
5482   |   |-'east'
5483   |   |-'='
5484   |   `-IntegerLiteralExpression
5485   |     `-'1' LiteralToken
5486   `-';'
5487 )txt"));
5488 }
5489 
5490 TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
5491   EXPECT_TRUE(treeDumpEqual(
5492       R"cpp(
5493 const int const universal = 0;
5494 )cpp",
5495       R"txt(
5496 TranslationUnit Detached
5497 `-SimpleDeclaration
5498   |-'const'
5499   |-'int'
5500   |-'const'
5501   |-DeclaratorList Declarators
5502   | `-SimpleDeclarator ListElement
5503   |   |-'universal'
5504   |   |-'='
5505   |   `-IntegerLiteralExpression
5506   |     `-'0' LiteralToken
5507   `-';'
5508 )txt"));
5509 }
5510 
5511 TEST_P(BuildSyntaxTreeTest,
5512        Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
5513   EXPECT_TRUE(treeDumpEqual(
5514       R"cpp(
5515 const int const *const *volatile b;
5516 )cpp",
5517       R"txt(
5518 TranslationUnit Detached
5519 `-SimpleDeclaration
5520   |-'const'
5521   |-'int'
5522   |-'const'
5523   |-DeclaratorList Declarators
5524   | `-SimpleDeclarator ListElement
5525   |   |-'*'
5526   |   |-'const'
5527   |   |-'*'
5528   |   |-'volatile'
5529   |   `-'b'
5530   `-';'
5531 )txt"));
5532 }
5533 
5534 TEST_P(BuildSyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
5535   if (!GetParam().isCXX11OrLater()) {
5536     return;
5537   }
5538   EXPECT_TRUE(treeDumpEqual(
5539       R"cpp(
5540 auto foo() -> auto(*)(int) -> double*;
5541 )cpp",
5542       R"txt(
5543 TranslationUnit Detached
5544 `-SimpleDeclaration
5545   |-'auto'
5546   |-DeclaratorList Declarators
5547   | `-SimpleDeclarator ListElement
5548   |   |-'foo'
5549   |   `-ParametersAndQualifiers
5550   |     |-'(' OpenParen
5551   |     |-')' CloseParen
5552   |     `-TrailingReturnType TrailingReturn
5553   |       |-'->' ArrowToken
5554   |       |-'auto'
5555   |       `-SimpleDeclarator Declarator
5556   |         |-ParenDeclarator
5557   |         | |-'(' OpenParen
5558   |         | |-'*'
5559   |         | `-')' CloseParen
5560   |         `-ParametersAndQualifiers
5561   |           |-'(' OpenParen
5562   |           |-ParameterDeclarationList Parameters
5563   |           | `-SimpleDeclaration ListElement
5564   |           |   `-'int'
5565   |           |-')' CloseParen
5566   |           `-TrailingReturnType TrailingReturn
5567   |             |-'->' ArrowToken
5568   |             |-'double'
5569   |             `-SimpleDeclarator Declarator
5570   |               `-'*'
5571   `-';'
5572 )txt"));
5573 }
5574 
5575 TEST_P(BuildSyntaxTreeTest, MemberPointers) {
5576   if (!GetParam().isCXX()) {
5577     return;
5578   }
5579   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5580       R"cpp(
5581 struct X {};
5582 [[int X::* a;]]
5583 [[const int X::* b;]]
5584 )cpp",
5585       {R"txt(
5586 SimpleDeclaration
5587 |-'int'
5588 |-DeclaratorList Declarators
5589 | `-SimpleDeclarator ListElement
5590 |   |-MemberPointer
5591 |   | |-'X'
5592 |   | |-'::'
5593 |   | `-'*'
5594 |   `-'a'
5595 `-';'
5596 )txt",
5597        R"txt(
5598 SimpleDeclaration
5599 |-'const'
5600 |-'int'
5601 |-DeclaratorList Declarators
5602 | `-SimpleDeclarator ListElement
5603 |   |-MemberPointer
5604 |   | |-'X'
5605 |   | |-'::'
5606 |   | `-'*'
5607 |   `-'b'
5608 `-';'
5609 )txt"}));
5610 }
5611 
5612 TEST_P(BuildSyntaxTreeTest, MemberFunctionPointer) {
5613   if (!GetParam().isCXX()) {
5614     return;
5615   }
5616   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5617       R"cpp(
5618 struct X {
5619   struct Y {};
5620 };
5621 [[void (X::*xp)();]]
5622 [[void (X::**xpp)(const int*);]]
5623 // FIXME: Generate the right syntax tree for this type,
5624 // i.e. create a syntax node for the outer member pointer
5625 [[void (X::Y::*xyp)(const int*, char);]]
5626 )cpp",
5627       {R"txt(
5628 SimpleDeclaration
5629 |-'void'
5630 |-DeclaratorList Declarators
5631 | `-SimpleDeclarator ListElement
5632 |   |-ParenDeclarator
5633 |   | |-'(' OpenParen
5634 |   | |-MemberPointer
5635 |   | | |-'X'
5636 |   | | |-'::'
5637 |   | | `-'*'
5638 |   | |-'xp'
5639 |   | `-')' CloseParen
5640 |   `-ParametersAndQualifiers
5641 |     |-'(' OpenParen
5642 |     `-')' CloseParen
5643 `-';'
5644 )txt",
5645        R"txt(
5646 SimpleDeclaration
5647 |-'void'
5648 |-DeclaratorList Declarators
5649 | `-SimpleDeclarator ListElement
5650 |   |-ParenDeclarator
5651 |   | |-'(' OpenParen
5652 |   | |-MemberPointer
5653 |   | | |-'X'
5654 |   | | |-'::'
5655 |   | | `-'*'
5656 |   | |-'*'
5657 |   | |-'xpp'
5658 |   | `-')' CloseParen
5659 |   `-ParametersAndQualifiers
5660 |     |-'(' OpenParen
5661 |     |-ParameterDeclarationList Parameters
5662 |     | `-SimpleDeclaration ListElement
5663 |     |   |-'const'
5664 |     |   |-'int'
5665 |     |   `-DeclaratorList Declarators
5666 |     |     `-SimpleDeclarator ListElement
5667 |     |       `-'*'
5668 |     `-')' CloseParen
5669 `-';'
5670 )txt",
5671        R"txt(
5672 SimpleDeclaration
5673 |-'void'
5674 |-DeclaratorList Declarators
5675 | `-SimpleDeclarator ListElement
5676 |   |-ParenDeclarator
5677 |   | |-'(' OpenParen
5678 |   | |-'X'
5679 |   | |-'::'
5680 |   | |-MemberPointer
5681 |   | | |-'Y'
5682 |   | | |-'::'
5683 |   | | `-'*'
5684 |   | |-'xyp'
5685 |   | `-')' CloseParen
5686 |   `-ParametersAndQualifiers
5687 |     |-'(' OpenParen
5688 |     |-ParameterDeclarationList Parameters
5689 |     | |-SimpleDeclaration ListElement
5690 |     | | |-'const'
5691 |     | | |-'int'
5692 |     | | `-DeclaratorList Declarators
5693 |     | |   `-SimpleDeclarator ListElement
5694 |     | |     `-'*'
5695 |     | |-',' ListDelimiter
5696 |     | `-SimpleDeclaration ListElement
5697 |     |   `-'char'
5698 |     `-')' CloseParen
5699 `-';'
5700 )txt"}));
5701 }
5702 
5703 TEST_P(BuildSyntaxTreeTest, ComplexDeclarator) {
5704   EXPECT_TRUE(treeDumpEqual(
5705       R"cpp(
5706 void x(char a, short (*b)(int));
5707 )cpp",
5708       R"txt(
5709 TranslationUnit Detached
5710 `-SimpleDeclaration
5711   |-'void'
5712   |-DeclaratorList Declarators
5713   | `-SimpleDeclarator ListElement
5714   |   |-'x'
5715   |   `-ParametersAndQualifiers
5716   |     |-'(' OpenParen
5717   |     |-ParameterDeclarationList Parameters
5718   |     | |-SimpleDeclaration ListElement
5719   |     | | |-'char'
5720   |     | | `-DeclaratorList Declarators
5721   |     | |   `-SimpleDeclarator ListElement
5722   |     | |     `-'a'
5723   |     | |-',' ListDelimiter
5724   |     | `-SimpleDeclaration ListElement
5725   |     |   |-'short'
5726   |     |   `-DeclaratorList Declarators
5727   |     |     `-SimpleDeclarator ListElement
5728   |     |       |-ParenDeclarator
5729   |     |       | |-'(' OpenParen
5730   |     |       | |-'*'
5731   |     |       | |-'b'
5732   |     |       | `-')' CloseParen
5733   |     |       `-ParametersAndQualifiers
5734   |     |         |-'(' OpenParen
5735   |     |         |-ParameterDeclarationList Parameters
5736   |     |         | `-SimpleDeclaration ListElement
5737   |     |         |   `-'int'
5738   |     |         `-')' CloseParen
5739   |     `-')' CloseParen
5740   `-';'
5741 )txt"));
5742 }
5743 
5744 TEST_P(BuildSyntaxTreeTest, ComplexDeclarator2) {
5745   EXPECT_TRUE(treeDumpEqual(
5746       R"cpp(
5747 void x(char a, short (*b)(int), long (**c)(long long));
5748 )cpp",
5749       R"txt(
5750 TranslationUnit Detached
5751 `-SimpleDeclaration
5752   |-'void'
5753   |-DeclaratorList Declarators
5754   | `-SimpleDeclarator ListElement
5755   |   |-'x'
5756   |   `-ParametersAndQualifiers
5757   |     |-'(' OpenParen
5758   |     |-ParameterDeclarationList Parameters
5759   |     | |-SimpleDeclaration ListElement
5760   |     | | |-'char'
5761   |     | | `-DeclaratorList Declarators
5762   |     | |   `-SimpleDeclarator ListElement
5763   |     | |     `-'a'
5764   |     | |-',' ListDelimiter
5765   |     | |-SimpleDeclaration ListElement
5766   |     | | |-'short'
5767   |     | | `-DeclaratorList Declarators
5768   |     | |   `-SimpleDeclarator ListElement
5769   |     | |     |-ParenDeclarator
5770   |     | |     | |-'(' OpenParen
5771   |     | |     | |-'*'
5772   |     | |     | |-'b'
5773   |     | |     | `-')' CloseParen
5774   |     | |     `-ParametersAndQualifiers
5775   |     | |       |-'(' OpenParen
5776   |     | |       |-ParameterDeclarationList Parameters
5777   |     | |       | `-SimpleDeclaration ListElement
5778   |     | |       |   `-'int'
5779   |     | |       `-')' CloseParen
5780   |     | |-',' ListDelimiter
5781   |     | `-SimpleDeclaration ListElement
5782   |     |   |-'long'
5783   |     |   `-DeclaratorList Declarators
5784   |     |     `-SimpleDeclarator ListElement
5785   |     |       |-ParenDeclarator
5786   |     |       | |-'(' OpenParen
5787   |     |       | |-'*'
5788   |     |       | |-'*'
5789   |     |       | |-'c'
5790   |     |       | `-')' CloseParen
5791   |     |       `-ParametersAndQualifiers
5792   |     |         |-'(' OpenParen
5793   |     |         |-ParameterDeclarationList Parameters
5794   |     |         | `-SimpleDeclaration ListElement
5795   |     |         |   |-'long'
5796   |     |         |   `-'long'
5797   |     |         `-')' CloseParen
5798   |     `-')' CloseParen
5799   `-';'
5800 )txt"));
5801 }
5802 
5803 } // namespace
5804