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