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