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