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, Macro_ObjectLike_Leaf) {
3859   // All nodes can be mutated.
3860   EXPECT_TRUE(treeDumpEqual(
3861       R"cpp(
3862 #define OPEN {
3863 #define CLOSE }
3864 
3865 void test() {
3866   OPEN
3867     1;
3868   CLOSE
3869 
3870   OPEN
3871     2;
3872   }
3873 }
3874 )cpp",
3875       R"txt(
3876 TranslationUnit Detached
3877 `-SimpleDeclaration
3878   |-'void'
3879   |-SimpleDeclarator Declarator
3880   | |-'test'
3881   | `-ParametersAndQualifiers
3882   |   |-'(' OpenParen
3883   |   `-')' CloseParen
3884   `-CompoundStatement
3885     |-'{' OpenParen
3886     |-CompoundStatement Statement
3887     | |-'{' OpenParen
3888     | |-ExpressionStatement Statement
3889     | | |-IntegerLiteralExpression Expression
3890     | | | `-'1' LiteralToken
3891     | | `-';'
3892     | `-'}' CloseParen
3893     |-CompoundStatement Statement
3894     | |-'{' OpenParen
3895     | |-ExpressionStatement Statement
3896     | | |-IntegerLiteralExpression Expression
3897     | | | `-'2' LiteralToken
3898     | | `-';'
3899     | `-'}' CloseParen
3900     `-'}' CloseParen
3901 )txt"));
3902 }
3903 
3904 TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MatchTree) {
3905   // Some nodes are unmodifiable, they are marked with 'unmodifiable'.
3906   EXPECT_TRUE(treeDumpEqual(
3907       R"cpp(
3908 #define BRACES {}
3909 
3910 void test() BRACES
3911 )cpp",
3912       R"txt(
3913 TranslationUnit Detached
3914 `-SimpleDeclaration
3915   |-'void'
3916   |-SimpleDeclarator Declarator
3917   | |-'test'
3918   | `-ParametersAndQualifiers
3919   |   |-'(' OpenParen
3920   |   `-')' CloseParen
3921   `-CompoundStatement
3922     |-'{' OpenParen unmodifiable
3923     `-'}' CloseParen unmodifiable
3924 )txt"));
3925 }
3926 
3927 TEST_P(BuildSyntaxTreeTest, Macro_ObjectLike_MismatchTree) {
3928   EXPECT_TRUE(treeDumpEqual(
3929       R"cpp(
3930 #define HALF_IF if (1+
3931 #define HALF_IF_2 1) {}
3932 void test() {
3933   HALF_IF HALF_IF_2 else {}
3934 })cpp",
3935       R"txt(
3936 TranslationUnit Detached
3937 `-SimpleDeclaration
3938   |-'void'
3939   |-SimpleDeclarator Declarator
3940   | |-'test'
3941   | `-ParametersAndQualifiers
3942   |   |-'(' OpenParen
3943   |   `-')' CloseParen
3944   `-CompoundStatement
3945     |-'{' OpenParen
3946     |-IfStatement Statement
3947     | |-'if' IntroducerKeyword unmodifiable
3948     | |-'(' unmodifiable
3949     | |-BinaryOperatorExpression unmodifiable
3950     | | |-IntegerLiteralExpression LeftHandSide unmodifiable
3951     | | | `-'1' LiteralToken unmodifiable
3952     | | |-'+' OperatorToken unmodifiable
3953     | | `-IntegerLiteralExpression RightHandSide unmodifiable
3954     | |   `-'1' LiteralToken unmodifiable
3955     | |-')' unmodifiable
3956     | |-CompoundStatement ThenStatement unmodifiable
3957     | | |-'{' OpenParen unmodifiable
3958     | | `-'}' CloseParen unmodifiable
3959     | |-'else' ElseKeyword
3960     | `-CompoundStatement ElseStatement
3961     |   |-'{' OpenParen
3962     |   `-'}' CloseParen
3963     `-'}' CloseParen
3964 )txt"));
3965 }
3966 
3967 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_ModifiableArguments) {
3968   // FIXME: Note that the substitutions for `X` and `Y` are marked modifiable.
3969   // However we cannot change `X` freely. Indeed if we change its substitution
3970   // in the condition we should also change it the then-branch.
3971   EXPECT_TRUE(treeDumpEqual(
3972       R"cpp(
3973 #define MIN(X,Y) X < Y ? X : Y
3974 
3975 void test() {
3976   MIN(1,2);
3977 }
3978 )cpp",
3979       R"txt(
3980 TranslationUnit Detached
3981 `-SimpleDeclaration
3982   |-'void'
3983   |-SimpleDeclarator Declarator
3984   | |-'test'
3985   | `-ParametersAndQualifiers
3986   |   |-'(' OpenParen
3987   |   `-')' CloseParen
3988   `-CompoundStatement
3989     |-'{' OpenParen
3990     |-ExpressionStatement Statement
3991     | |-UnknownExpression Expression
3992     | | |-BinaryOperatorExpression unmodifiable
3993     | | | |-IntegerLiteralExpression LeftHandSide
3994     | | | | `-'1' LiteralToken
3995     | | | |-'<' OperatorToken unmodifiable
3996     | | | `-IntegerLiteralExpression RightHandSide
3997     | | |   `-'2' LiteralToken
3998     | | |-'?' unmodifiable
3999     | | |-IntegerLiteralExpression
4000     | | | `-'1' LiteralToken
4001     | | |-':' unmodifiable
4002     | | `-IntegerLiteralExpression
4003     | |   `-'2' LiteralToken
4004     | `-';'
4005     `-'}' CloseParen
4006 )txt"));
4007 }
4008 
4009 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_MismatchTree) {
4010   EXPECT_TRUE(treeDumpEqual(
4011       R"cpp(
4012 #define HALF_IF(X) if (X &&
4013 #define HALF_IF_2(Y) Y) {}
4014 void test() {
4015   HALF_IF(1) HALF_IF_2(0) else {}
4016 })cpp",
4017       R"txt(
4018 TranslationUnit Detached
4019 `-SimpleDeclaration
4020   |-'void'
4021   |-SimpleDeclarator Declarator
4022   | |-'test'
4023   | `-ParametersAndQualifiers
4024   |   |-'(' OpenParen
4025   |   `-')' CloseParen
4026   `-CompoundStatement
4027     |-'{' OpenParen
4028     |-IfStatement Statement
4029     | |-'if' IntroducerKeyword unmodifiable
4030     | |-'(' unmodifiable
4031     | |-BinaryOperatorExpression unmodifiable
4032     | | |-IntegerLiteralExpression LeftHandSide
4033     | | | `-'1' LiteralToken
4034     | | |-'&&' OperatorToken unmodifiable
4035     | | `-IntegerLiteralExpression RightHandSide
4036     | |   `-'0' LiteralToken
4037     | |-')' unmodifiable
4038     | |-CompoundStatement ThenStatement unmodifiable
4039     | | |-'{' OpenParen unmodifiable
4040     | | `-'}' CloseParen unmodifiable
4041     | |-'else' ElseKeyword
4042     | `-CompoundStatement ElseStatement
4043     |   |-'{' OpenParen
4044     |   `-'}' CloseParen
4045     `-'}' CloseParen
4046 )txt"));
4047 }
4048 
4049 TEST_P(BuildSyntaxTreeTest, Macro_FunctionLike_Variadic) {
4050   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4051       R"cpp(
4052 #define CALL(F_NAME, ...) F_NAME(__VA_ARGS__)
4053 
4054 void f(int);
4055 void g(int, int);
4056 void test() [[{
4057   CALL(f, 0);
4058   CALL(g, 0, 1);
4059 }]]
4060 )cpp",
4061       {R"txt(
4062 CompoundStatement
4063 |-'{' OpenParen
4064 |-ExpressionStatement Statement
4065 | |-CallExpression Expression
4066 | | |-IdExpression Callee
4067 | | | `-UnqualifiedId UnqualifiedId
4068 | | |   `-'f'
4069 | | |-'(' OpenParen unmodifiable
4070 | | |-CallArguments Arguments
4071 | | | `-IntegerLiteralExpression ListElement
4072 | | |   `-'0' LiteralToken
4073 | | `-')' CloseParen unmodifiable
4074 | `-';'
4075 |-ExpressionStatement Statement
4076 | |-CallExpression Expression
4077 | | |-IdExpression Callee
4078 | | | `-UnqualifiedId UnqualifiedId
4079 | | |   `-'g'
4080 | | |-'(' OpenParen unmodifiable
4081 | | |-CallArguments Arguments
4082 | | | |-IntegerLiteralExpression ListElement
4083 | | | | `-'0' LiteralToken
4084 | | | |-',' ListDelimiter
4085 | | | `-IntegerLiteralExpression ListElement
4086 | | |   `-'1' LiteralToken
4087 | | `-')' CloseParen unmodifiable
4088 | `-';'
4089 `-'}' CloseParen
4090 )txt"}));
4091 }
4092 
4093 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Equal) {
4094   if (!GetParam().isCXX()) {
4095     return;
4096   }
4097   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4098       R"cpp(
4099 struct S { S(int);};
4100 void test() {
4101   [[S s = 1]];
4102 }
4103 )cpp",
4104       {R"txt(
4105 SimpleDeclaration
4106 |-'S'
4107 `-SimpleDeclarator Declarator
4108   |-'s'
4109   |-'='
4110   `-IntegerLiteralExpression
4111     `-'1' LiteralToken
4112 )txt"}));
4113 }
4114 
4115 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Brace) {
4116   if (!GetParam().isCXX11OrLater()) {
4117     return;
4118   }
4119   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4120       R"cpp(
4121 struct S {
4122   S();
4123   S(int);
4124   S(int, float);
4125 };
4126 void test(){
4127   // FIXME: 's...' is a declarator and '{...}' is initializer
4128   [[S s0{}]];
4129   [[S s1{1}]];
4130   [[S s2{1, 2.}]];
4131 }
4132 )cpp",
4133       {R"txt(
4134 SimpleDeclaration
4135 |-'S'
4136 `-SimpleDeclarator Declarator
4137   `-UnknownExpression
4138     |-'s0'
4139     |-'{'
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   )txt",
4153        R"txt(
4154 SimpleDeclaration
4155 |-'S'
4156 `-SimpleDeclarator Declarator
4157   `-UnknownExpression
4158     |-'s2'
4159     |-'{'
4160     |-IntegerLiteralExpression
4161     | `-'1' LiteralToken
4162     |-','
4163     |-FloatingLiteralExpression
4164     | `-'2.' LiteralToken
4165     `-'}'
4166 )txt"}));
4167 }
4168 
4169 TEST_P(BuildSyntaxTreeTest, InitDeclarator_EqualBrace) {
4170   if (!GetParam().isCXX11OrLater()) {
4171     return;
4172   }
4173   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4174       R"cpp(
4175 struct S {
4176   S();
4177   S(int);
4178   S(int, float);
4179 };
4180 void test() {
4181   // FIXME: '= {...}' is initializer
4182   [[S s0 = {}]];
4183   [[S s1 = {1}]];
4184   [[S s2 = {1, 2.}]];
4185 }
4186 )cpp",
4187       {R"txt(
4188 SimpleDeclaration
4189 |-'S'
4190 `-SimpleDeclarator Declarator
4191   |-'s0'
4192   |-'='
4193   `-UnknownExpression
4194     |-'{'
4195     `-'}'
4196   )txt",
4197        R"txt(
4198 SimpleDeclaration
4199 |-'S'
4200 `-SimpleDeclarator Declarator
4201   |-'s1'
4202   |-'='
4203   `-UnknownExpression
4204     |-'{'
4205     |-IntegerLiteralExpression
4206     | `-'1' LiteralToken
4207     `-'}'
4208   )txt",
4209        R"txt(
4210 SimpleDeclaration
4211 |-'S'
4212 `-SimpleDeclarator Declarator
4213   |-'s2'
4214   |-'='
4215   `-UnknownExpression
4216     |-'{'
4217     |-IntegerLiteralExpression
4218     | `-'1' LiteralToken
4219     |-','
4220     |-FloatingLiteralExpression
4221     | `-'2.' LiteralToken
4222     `-'}'
4223 )txt"}));
4224 }
4225 
4226 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Paren) {
4227   if (!GetParam().isCXX()) {
4228     return;
4229   }
4230   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4231       R"cpp(
4232 struct S {
4233   S(int);
4234   S(int, float);
4235 };
4236 // FIXME: 's...' is a declarator and '(...)' is initializer
4237 [[S s1(1);]]
4238 [[S s2(1, 2.);]]
4239 )cpp",
4240       {R"txt(
4241 SimpleDeclaration
4242 |-'S'
4243 |-SimpleDeclarator Declarator
4244 | `-UnknownExpression
4245 |   |-'s1'
4246 |   |-'('
4247 |   |-IntegerLiteralExpression
4248 |   | `-'1' LiteralToken
4249 |   `-')'
4250 `-';'
4251   )txt",
4252        R"txt(
4253 SimpleDeclaration
4254 |-'S'
4255 |-SimpleDeclarator Declarator
4256 | `-UnknownExpression
4257 |   |-'s2'
4258 |   |-'('
4259 |   |-IntegerLiteralExpression
4260 |   | `-'1' LiteralToken
4261 |   |-','
4262 |   |-FloatingLiteralExpression
4263 |   | `-'2.' LiteralToken
4264 |   `-')'
4265 `-';'
4266 )txt"}));
4267 }
4268 
4269 TEST_P(BuildSyntaxTreeTest, InitDeclarator_Paren_DefaultArguments) {
4270   if (!GetParam().isCXX()) {
4271     return;
4272   }
4273   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4274       R"cpp(
4275 struct S {
4276   S(int i = 1, float = 2.);
4277 };
4278 [[S s0;]]
4279 // FIXME: 's...' is a declarator and '(...)' is initializer
4280 [[S s1(1);]]
4281 [[S s2(1, 2.);]]
4282 )cpp",
4283       {R"txt(
4284 SimpleDeclaration
4285 |-'S'
4286 |-SimpleDeclarator Declarator
4287 | `-'s0'
4288 `-';'
4289   )txt",
4290        R"txt(
4291 SimpleDeclaration
4292 |-'S'
4293 |-SimpleDeclarator Declarator
4294 | `-UnknownExpression
4295 |   |-'s1'
4296 |   |-'('
4297 |   |-IntegerLiteralExpression
4298 |   | `-'1' LiteralToken
4299 |   `-')'
4300 `-';'
4301   )txt",
4302        R"txt(
4303 SimpleDeclaration
4304 |-'S'
4305 |-SimpleDeclarator Declarator
4306 | `-UnknownExpression
4307 |   |-'s2'
4308 |   |-'('
4309 |   |-IntegerLiteralExpression
4310 |   | `-'1' LiteralToken
4311 |   |-','
4312 |   |-FloatingLiteralExpression
4313 |   | `-'2.' LiteralToken
4314 |   `-')'
4315 `-';'
4316 )txt"}));
4317 }
4318 
4319 TEST_P(BuildSyntaxTreeTest, ImplicitConversion_Argument) {
4320   if (!GetParam().isCXX()) {
4321     return;
4322   }
4323   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4324       R"cpp(
4325 struct X {
4326   X(int);
4327 };
4328 void TakeX(const X&);
4329 void test() {
4330   [[TakeX(1)]];
4331 }
4332 )cpp",
4333       {R"txt(
4334 CallExpression Expression
4335 |-IdExpression Callee
4336 | `-UnqualifiedId UnqualifiedId
4337 |   `-'TakeX'
4338 |-'(' OpenParen
4339 |-CallArguments Arguments
4340 | `-IntegerLiteralExpression ListElement
4341 |   `-'1' LiteralToken
4342 `-')' CloseParen
4343 )txt"}));
4344 }
4345 
4346 TEST_P(BuildSyntaxTreeTest, ImplicitConversion_Return) {
4347   if (!GetParam().isCXX()) {
4348     return;
4349   }
4350   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4351       R"cpp(
4352 struct X {
4353   X(int);
4354 };
4355 X CreateX(){
4356   [[return 1;]]
4357 }
4358 )cpp",
4359       {R"txt(
4360 ReturnStatement Statement
4361 |-'return' IntroducerKeyword
4362 |-IntegerLiteralExpression ReturnValue
4363 | `-'1' LiteralToken
4364 `-';'
4365 )txt"}));
4366 }
4367 
4368 TEST_P(BuildSyntaxTreeTest, ConstructorCall_ZeroArguments) {
4369   if (!GetParam().isCXX()) {
4370     return;
4371   }
4372   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4373       R"cpp(
4374 struct X {
4375   X();
4376 };
4377 X test() {
4378   [[return X();]]
4379 }
4380 )cpp",
4381       {R"txt(
4382 ReturnStatement Statement
4383 |-'return' IntroducerKeyword
4384 |-UnknownExpression ReturnValue
4385 | |-'X'
4386 | |-'('
4387 | `-')'
4388 `-';'
4389 )txt"}));
4390 }
4391 
4392 TEST_P(BuildSyntaxTreeTest, ConstructorCall_OneArgument) {
4393   if (!GetParam().isCXX()) {
4394     return;
4395   }
4396   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4397       R"cpp(
4398 struct X {
4399   X(int);
4400 };
4401 X test() {
4402   [[return X(1);]]
4403 }
4404 )cpp",
4405       {R"txt(
4406 ReturnStatement Statement
4407 |-'return' IntroducerKeyword
4408 |-UnknownExpression ReturnValue
4409 | |-'X'
4410 | |-'('
4411 | |-IntegerLiteralExpression
4412 | | `-'1' LiteralToken
4413 | `-')'
4414 `-';'
4415 )txt"}));
4416 }
4417 
4418 TEST_P(BuildSyntaxTreeTest, ConstructorCall_MultipleArguments) {
4419   if (!GetParam().isCXX()) {
4420     return;
4421   }
4422   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4423       R"cpp(
4424 struct X {
4425   X(int, char);
4426 };
4427 X test() {
4428   [[return X(1, '2');]]
4429 }
4430 )cpp",
4431       {R"txt(
4432 ReturnStatement Statement
4433 |-'return' IntroducerKeyword
4434 |-UnknownExpression ReturnValue
4435 | |-'X'
4436 | |-'('
4437 | |-IntegerLiteralExpression
4438 | | `-'1' LiteralToken
4439 | |-','
4440 | |-CharacterLiteralExpression
4441 | | `-''2'' LiteralToken
4442 | `-')'
4443 `-';'
4444 )txt"}));
4445 }
4446 
4447 TEST_P(BuildSyntaxTreeTest, ConstructorCall_DefaultArguments) {
4448   if (!GetParam().isCXX()) {
4449     return;
4450   }
4451   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4452       R"cpp(
4453 struct X {
4454   X(int i = 1, char c = '2');
4455 };
4456 X test() {
4457   auto x0 = [[X()]];
4458   auto x1 = [[X(1)]];
4459   auto x2 = [[X(1, '2')]];
4460 }
4461 )cpp",
4462       {R"txt(
4463 UnknownExpression
4464 |-'X'
4465 |-'('
4466 `-')'
4467 )txt",
4468        R"txt(
4469 UnknownExpression
4470 |-'X'
4471 |-'('
4472 |-IntegerLiteralExpression
4473 | `-'1' LiteralToken
4474 `-')'
4475 )txt",
4476        R"txt(
4477 UnknownExpression
4478 |-'X'
4479 |-'('
4480 |-IntegerLiteralExpression
4481 | `-'1' LiteralToken
4482 |-','
4483 |-CharacterLiteralExpression
4484 | `-''2'' LiteralToken
4485 `-')'
4486 )txt"}));
4487 }
4488 
4489 TEST_P(BuildSyntaxTreeTest, TypeConversion_FunctionalNotation) {
4490   if (!GetParam().isCXX()) {
4491     return;
4492   }
4493   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4494       R"cpp(
4495 float test() {
4496   [[return float(1);]]
4497 }
4498 )cpp",
4499       {R"txt(
4500 ReturnStatement Statement
4501 |-'return' IntroducerKeyword
4502 |-UnknownExpression ReturnValue
4503 | |-'float'
4504 | |-'('
4505 | |-IntegerLiteralExpression
4506 | | `-'1' LiteralToken
4507 | `-')'
4508 `-';'
4509 )txt"}));
4510 }
4511 
4512 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Simple) {
4513   EXPECT_TRUE(treeDumpEqual(
4514       R"cpp(
4515 int a[10];
4516 )cpp",
4517       R"txt(
4518 TranslationUnit Detached
4519 `-SimpleDeclaration
4520   |-'int'
4521   |-SimpleDeclarator Declarator
4522   | |-'a'
4523   | `-ArraySubscript
4524   |   |-'[' OpenParen
4525   |   |-IntegerLiteralExpression Size
4526   |   | `-'10' LiteralToken
4527   |   `-']' CloseParen
4528   `-';'
4529 )txt"));
4530 }
4531 
4532 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Multidimensional) {
4533   EXPECT_TRUE(treeDumpEqual(
4534       R"cpp(
4535 int b[1][2][3];
4536 )cpp",
4537       R"txt(
4538 TranslationUnit Detached
4539 `-SimpleDeclaration
4540   |-'int'
4541   |-SimpleDeclarator Declarator
4542   | |-'b'
4543   | |-ArraySubscript
4544   | | |-'[' OpenParen
4545   | | |-IntegerLiteralExpression Size
4546   | | | `-'1' LiteralToken
4547   | | `-']' CloseParen
4548   | |-ArraySubscript
4549   | | |-'[' OpenParen
4550   | | |-IntegerLiteralExpression Size
4551   | | | `-'2' LiteralToken
4552   | | `-']' CloseParen
4553   | `-ArraySubscript
4554   |   |-'[' OpenParen
4555   |   |-IntegerLiteralExpression Size
4556   |   | `-'3' LiteralToken
4557   |   `-']' CloseParen
4558   `-';'
4559 )txt"));
4560 }
4561 
4562 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_UnknownBound) {
4563   EXPECT_TRUE(treeDumpEqual(
4564       R"cpp(
4565 int c[] = {1,2,3};
4566 )cpp",
4567       R"txt(
4568 TranslationUnit Detached
4569 `-SimpleDeclaration
4570   |-'int'
4571   |-SimpleDeclarator Declarator
4572   | |-'c'
4573   | |-ArraySubscript
4574   | | |-'[' OpenParen
4575   | | `-']' CloseParen
4576   | |-'='
4577   | `-UnknownExpression
4578   |   `-UnknownExpression
4579   |     |-'{'
4580   |     |-IntegerLiteralExpression
4581   |     | `-'1' LiteralToken
4582   |     |-','
4583   |     |-IntegerLiteralExpression
4584   |     | `-'2' LiteralToken
4585   |     |-','
4586   |     |-IntegerLiteralExpression
4587   |     | `-'3' LiteralToken
4588   |     `-'}'
4589   `-';'
4590 )txt"));
4591 }
4592 
4593 TEST_P(BuildSyntaxTreeTest, ArrayDeclarator_Static) {
4594   if (!GetParam().isC99OrLater()) {
4595     return;
4596   }
4597   EXPECT_TRUE(treeDumpEqual(
4598       R"cpp(
4599 void f(int xs[static 10]);
4600 )cpp",
4601       R"txt(
4602 TranslationUnit Detached
4603 `-SimpleDeclaration
4604   |-'void'
4605   |-SimpleDeclarator Declarator
4606   | |-'f'
4607   | `-ParametersAndQualifiers
4608   |   |-'(' OpenParen
4609   |   |-ParameterDeclarationList Parameters
4610   |   | `-SimpleDeclaration ListElement
4611   |   |   |-'int'
4612   |   |   `-SimpleDeclarator Declarator
4613   |   |     |-'xs'
4614   |   |     `-ArraySubscript
4615   |   |       |-'[' OpenParen
4616   |   |       |-'static'
4617   |   |       |-IntegerLiteralExpression Size
4618   |   |       | `-'10' LiteralToken
4619   |   |       `-']' CloseParen
4620   |   `-')' CloseParen
4621   `-';'
4622 )txt"));
4623 }
4624 
4625 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Empty) {
4626   EXPECT_TRUE(treeDumpEqual(
4627       R"cpp(
4628 int func();
4629 )cpp",
4630       R"txt(
4631 TranslationUnit Detached
4632 `-SimpleDeclaration
4633   |-'int'
4634   |-SimpleDeclarator Declarator
4635   | |-'func'
4636   | `-ParametersAndQualifiers
4637   |   |-'(' OpenParen
4638   |   `-')' CloseParen
4639   `-';'
4640 )txt"));
4641 }
4642 
4643 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Named) {
4644   EXPECT_TRUE(treeDumpEqual(
4645       R"cpp(
4646 int func1(int a);
4647 int func2(int *ap);
4648 int func3(int a, float b);
4649 )cpp",
4650       R"txt(
4651 TranslationUnit Detached
4652 |-SimpleDeclaration
4653 | |-'int'
4654 | |-SimpleDeclarator Declarator
4655 | | |-'func1'
4656 | | `-ParametersAndQualifiers
4657 | |   |-'(' OpenParen
4658 | |   |-ParameterDeclarationList Parameters
4659 | |   | `-SimpleDeclaration ListElement
4660 | |   |   |-'int'
4661 | |   |   `-SimpleDeclarator Declarator
4662 | |   |     `-'a'
4663 | |   `-')' CloseParen
4664 | `-';'
4665 |-SimpleDeclaration
4666 | |-'int'
4667 | |-SimpleDeclarator Declarator
4668 | | |-'func2'
4669 | | `-ParametersAndQualifiers
4670 | |   |-'(' OpenParen
4671 | |   |-ParameterDeclarationList Parameters
4672 | |   | `-SimpleDeclaration ListElement
4673 | |   |   |-'int'
4674 | |   |   `-SimpleDeclarator Declarator
4675 | |   |     |-'*'
4676 | |   |     `-'ap'
4677 | |   `-')' CloseParen
4678 | `-';'
4679 `-SimpleDeclaration
4680   |-'int'
4681   |-SimpleDeclarator Declarator
4682   | |-'func3'
4683   | `-ParametersAndQualifiers
4684   |   |-'(' OpenParen
4685   |   |-ParameterDeclarationList Parameters
4686   |   | |-SimpleDeclaration ListElement
4687   |   | | |-'int'
4688   |   | | `-SimpleDeclarator Declarator
4689   |   | |   `-'a'
4690   |   | |-',' ListDelimiter
4691   |   | `-SimpleDeclaration ListElement
4692   |   |   |-'float'
4693   |   |   `-SimpleDeclarator Declarator
4694   |   |     `-'b'
4695   |   `-')' CloseParen
4696   `-';'
4697 )txt"));
4698 }
4699 
4700 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Unnamed) {
4701   EXPECT_TRUE(treeDumpEqual(
4702       R"cpp(
4703 int func1(int);
4704 int func2(int *);
4705 int func3(int, float);
4706 )cpp",
4707       R"txt(
4708 TranslationUnit Detached
4709 |-SimpleDeclaration
4710 | |-'int'
4711 | |-SimpleDeclarator Declarator
4712 | | |-'func1'
4713 | | `-ParametersAndQualifiers
4714 | |   |-'(' OpenParen
4715 | |   |-ParameterDeclarationList Parameters
4716 | |   | `-SimpleDeclaration ListElement
4717 | |   |   `-'int'
4718 | |   `-')' CloseParen
4719 | `-';'
4720 |-SimpleDeclaration
4721 | |-'int'
4722 | |-SimpleDeclarator Declarator
4723 | | |-'func2'
4724 | | `-ParametersAndQualifiers
4725 | |   |-'(' OpenParen
4726 | |   |-ParameterDeclarationList Parameters
4727 | |   | `-SimpleDeclaration ListElement
4728 | |   |   |-'int'
4729 | |   |   `-SimpleDeclarator Declarator
4730 | |   |     `-'*'
4731 | |   `-')' CloseParen
4732 | `-';'
4733 `-SimpleDeclaration
4734   |-'int'
4735   |-SimpleDeclarator Declarator
4736   | |-'func3'
4737   | `-ParametersAndQualifiers
4738   |   |-'(' OpenParen
4739   |   |-ParameterDeclarationList Parameters
4740   |   | |-SimpleDeclaration ListElement
4741   |   | | `-'int'
4742   |   | |-',' ListDelimiter
4743   |   | `-SimpleDeclaration ListElement
4744   |   |   `-'float'
4745   |   `-')' CloseParen
4746   `-';'
4747 )txt"));
4748 }
4749 
4750 TEST_P(BuildSyntaxTreeTest,
4751        ParametersAndQualifiers_InFreeFunctions_Default_One) {
4752   if (!GetParam().isCXX()) {
4753     return;
4754   }
4755   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4756       R"cpp(
4757 int func1([[int a = 1]]);
4758 )cpp",
4759       {R"txt(
4760 ParameterDeclarationList Parameters
4761 `-SimpleDeclaration ListElement
4762   |-'int'
4763   `-SimpleDeclarator Declarator
4764     |-'a'
4765     |-'='
4766     `-IntegerLiteralExpression
4767       `-'1' LiteralToken
4768 )txt"}));
4769 }
4770 
4771 TEST_P(BuildSyntaxTreeTest,
4772        ParametersAndQualifiers_InFreeFunctions_Default_Multiple) {
4773   if (!GetParam().isCXX()) {
4774     return;
4775   }
4776   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4777       R"cpp(
4778 int func2([[int *ap, int a = 1, char c = '2']]);
4779 )cpp",
4780       {R"txt(
4781 ParameterDeclarationList Parameters
4782 |-SimpleDeclaration ListElement
4783 | |-'int'
4784 | `-SimpleDeclarator Declarator
4785 |   |-'*'
4786 |   `-'ap'
4787 |-',' ListDelimiter
4788 |-SimpleDeclaration ListElement
4789 | |-'int'
4790 | `-SimpleDeclarator Declarator
4791 |   |-'a'
4792 |   |-'='
4793 |   `-IntegerLiteralExpression
4794 |     `-'1' LiteralToken
4795 |-',' ListDelimiter
4796 `-SimpleDeclaration ListElement
4797   |-'char'
4798   `-SimpleDeclarator Declarator
4799     |-'c'
4800     |-'='
4801     `-CharacterLiteralExpression
4802       `-''2'' LiteralToken
4803 )txt"}));
4804 }
4805 
4806 TEST_P(BuildSyntaxTreeTest,
4807        ParametersAndQualifiers_InVariadicFunctionTemplate_ParameterPack) {
4808   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4809     return;
4810   }
4811   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4812       R"cpp(
4813 template<typename T, typename... Args>
4814 [[void test(T , Args... );]]
4815 )cpp",
4816       {R"txt(
4817 SimpleDeclaration
4818 |-'void'
4819 |-SimpleDeclarator Declarator
4820 | |-'test'
4821 | `-ParametersAndQualifiers
4822 |   |-'(' OpenParen
4823 |   |-ParameterDeclarationList Parameters
4824 |   | |-SimpleDeclaration ListElement
4825 |   | | `-'T'
4826 |   | |-',' ListDelimiter
4827 |   | `-SimpleDeclaration ListElement
4828 |   |   |-'Args'
4829 |   |   `-'...'
4830 |   `-')' CloseParen
4831 `-';'
4832 )txt"}));
4833 }
4834 
4835 TEST_P(BuildSyntaxTreeTest,
4836        ParametersAndQualifiers_InVariadicFunctionTemplate_NamedParameterPack) {
4837   if (!GetParam().isCXX11OrLater() || GetParam().hasDelayedTemplateParsing()) {
4838     return;
4839   }
4840   EXPECT_TRUE(treeDumpEqualOnAnnotations(
4841       R"cpp(
4842 template<typename T, typename... Args>
4843 [[void test(T t, Args... args);]]
4844 )cpp",
4845       {R"txt(
4846 SimpleDeclaration
4847 |-'void'
4848 |-SimpleDeclarator Declarator
4849 | |-'test'
4850 | `-ParametersAndQualifiers
4851 |   |-'(' OpenParen
4852 |   |-ParameterDeclarationList Parameters
4853 |   | |-SimpleDeclaration ListElement
4854 |   | | |-'T'
4855 |   | | `-SimpleDeclarator Declarator
4856 |   | |   `-'t'
4857 |   | |-',' ListDelimiter
4858 |   | `-SimpleDeclaration ListElement
4859 |   |   |-'Args'
4860 |   |   |-'...'
4861 |   |   `-SimpleDeclarator Declarator
4862 |   |     `-'args'
4863 |   `-')' CloseParen
4864 `-';'
4865 )txt"}));
4866 }
4867 
4868 TEST_P(BuildSyntaxTreeTest,
4869        ParametersAndQualifiers_InFreeFunctions_VariadicArguments) {
4870   if (!GetParam().isCXX11OrLater()) {
4871     return;
4872   }
4873   EXPECT_TRUE(treeDumpEqual(
4874       R"cpp(
4875 void test(int , char ...);
4876 )cpp",
4877       R"txt(
4878 TranslationUnit Detached
4879 `-SimpleDeclaration
4880   |-'void'
4881   |-SimpleDeclarator Declarator
4882   | |-'test'
4883   | `-ParametersAndQualifiers
4884   |   |-'(' OpenParen
4885   |   |-ParameterDeclarationList Parameters
4886   |   | |-SimpleDeclaration ListElement
4887   |   | | `-'int'
4888   |   | |-',' ListDelimiter
4889   |   | `-SimpleDeclaration ListElement
4890   |   |   `-'char'
4891   |   |-'...'
4892   |   `-')' CloseParen
4893   `-';'
4894 )txt"));
4895 }
4896 
4897 TEST_P(BuildSyntaxTreeTest,
4898        ParametersAndQualifiers_InFreeFunctions_Cxx_CvQualifiers) {
4899   if (!GetParam().isCXX()) {
4900     return;
4901   }
4902   EXPECT_TRUE(treeDumpEqual(
4903       R"cpp(
4904 int func(const int a, volatile int b, const volatile int c);
4905 )cpp",
4906       R"txt(
4907 TranslationUnit Detached
4908 `-SimpleDeclaration
4909   |-'int'
4910   |-SimpleDeclarator Declarator
4911   | |-'func'
4912   | `-ParametersAndQualifiers
4913   |   |-'(' OpenParen
4914   |   |-ParameterDeclarationList Parameters
4915   |   | |-SimpleDeclaration ListElement
4916   |   | | |-'const'
4917   |   | | |-'int'
4918   |   | | `-SimpleDeclarator Declarator
4919   |   | |   `-'a'
4920   |   | |-',' ListDelimiter
4921   |   | |-SimpleDeclaration ListElement
4922   |   | | |-'volatile'
4923   |   | | |-'int'
4924   |   | | `-SimpleDeclarator Declarator
4925   |   | |   `-'b'
4926   |   | |-',' ListDelimiter
4927   |   | `-SimpleDeclaration ListElement
4928   |   |   |-'const'
4929   |   |   |-'volatile'
4930   |   |   |-'int'
4931   |   |   `-SimpleDeclarator Declarator
4932   |   |     `-'c'
4933   |   `-')' CloseParen
4934   `-';'
4935 )txt"));
4936 }
4937 
4938 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InFreeFunctions_Cxx_Ref) {
4939   if (!GetParam().isCXX()) {
4940     return;
4941   }
4942   EXPECT_TRUE(treeDumpEqual(
4943       R"cpp(
4944 int func(int& a);
4945 )cpp",
4946       R"txt(
4947 TranslationUnit Detached
4948 `-SimpleDeclaration
4949   |-'int'
4950   |-SimpleDeclarator Declarator
4951   | |-'func'
4952   | `-ParametersAndQualifiers
4953   |   |-'(' OpenParen
4954   |   |-ParameterDeclarationList Parameters
4955   |   | `-SimpleDeclaration ListElement
4956   |   |   |-'int'
4957   |   |   `-SimpleDeclarator Declarator
4958   |   |     |-'&'
4959   |   |     `-'a'
4960   |   `-')' CloseParen
4961   `-';'
4962 )txt"));
4963 }
4964 
4965 TEST_P(BuildSyntaxTreeTest,
4966        ParametersAndQualifiers_InFreeFunctions_Cxx11_RefRef) {
4967   if (!GetParam().isCXX11OrLater()) {
4968     return;
4969   }
4970   EXPECT_TRUE(treeDumpEqual(
4971       R"cpp(
4972 int func(int&& a);
4973 )cpp",
4974       R"txt(
4975 TranslationUnit Detached
4976 `-SimpleDeclaration
4977   |-'int'
4978   |-SimpleDeclarator Declarator
4979   | |-'func'
4980   | `-ParametersAndQualifiers
4981   |   |-'(' OpenParen
4982   |   |-ParameterDeclarationList Parameters
4983   |   | `-SimpleDeclaration ListElement
4984   |   |   |-'int'
4985   |   |   `-SimpleDeclarator Declarator
4986   |   |     |-'&&'
4987   |   |     `-'a'
4988   |   `-')' CloseParen
4989   `-';'
4990 )txt"));
4991 }
4992 
4993 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Simple) {
4994   if (!GetParam().isCXX()) {
4995     return;
4996   }
4997   EXPECT_TRUE(treeDumpEqual(
4998       R"cpp(
4999 struct Test {
5000   int a();
5001 };
5002 )cpp",
5003       R"txt(
5004 TranslationUnit Detached
5005 `-SimpleDeclaration
5006   |-'struct'
5007   |-'Test'
5008   |-'{'
5009   |-SimpleDeclaration
5010   | |-'int'
5011   | |-SimpleDeclarator Declarator
5012   | | |-'a'
5013   | | `-ParametersAndQualifiers
5014   | |   |-'(' OpenParen
5015   | |   `-')' CloseParen
5016   | `-';'
5017   |-'}'
5018   `-';'
5019 )txt"));
5020 }
5021 
5022 TEST_P(BuildSyntaxTreeTest,
5023        ParametersAndQualifiers_InMemberFunctions_CvQualifiers) {
5024   if (!GetParam().isCXX()) {
5025     return;
5026   }
5027   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5028       R"cpp(
5029 struct Test {
5030   [[int b() const;]]
5031   [[int c() volatile;]]
5032   [[int d() const volatile;]]
5033 };
5034 )cpp",
5035       {R"txt(
5036 SimpleDeclaration
5037 |-'int'
5038 |-SimpleDeclarator Declarator
5039 | |-'b'
5040 | `-ParametersAndQualifiers
5041 |   |-'(' OpenParen
5042 |   |-')' CloseParen
5043 |   `-'const'
5044 `-';'
5045 )txt",
5046        R"txt(
5047 SimpleDeclaration
5048 |-'int'
5049 |-SimpleDeclarator Declarator
5050 | |-'c'
5051 | `-ParametersAndQualifiers
5052 |   |-'(' OpenParen
5053 |   |-')' CloseParen
5054 |   `-'volatile'
5055 `-';'
5056 )txt",
5057        R"txt(
5058 SimpleDeclaration
5059 |-'int'
5060 |-SimpleDeclarator Declarator
5061 | |-'d'
5062 | `-ParametersAndQualifiers
5063 |   |-'(' OpenParen
5064 |   |-')' CloseParen
5065 |   |-'const'
5066 |   `-'volatile'
5067 `-';'
5068 )txt"}));
5069 }
5070 
5071 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_Ref) {
5072   if (!GetParam().isCXX11OrLater()) {
5073     return;
5074   }
5075   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5076       R"cpp(
5077 struct Test {
5078   [[int e() &;]]
5079 };
5080 )cpp",
5081       {R"txt(
5082 SimpleDeclaration
5083 |-'int'
5084 |-SimpleDeclarator Declarator
5085 | |-'e'
5086 | `-ParametersAndQualifiers
5087 |   |-'(' OpenParen
5088 |   |-')' CloseParen
5089 |   `-'&'
5090 `-';'
5091 )txt"}));
5092 }
5093 
5094 TEST_P(BuildSyntaxTreeTest, ParametersAndQualifiers_InMemberFunctions_RefRef) {
5095   if (!GetParam().isCXX11OrLater()) {
5096     return;
5097   }
5098   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5099       R"cpp(
5100 struct Test {
5101   [[int f() &&;]]
5102 };
5103 )cpp",
5104       {R"txt(
5105 SimpleDeclaration
5106 |-'int'
5107 |-SimpleDeclarator Declarator
5108 | |-'f'
5109 | `-ParametersAndQualifiers
5110 |   |-'(' OpenParen
5111 |   |-')' CloseParen
5112 |   `-'&&'
5113 `-';'
5114 )txt"}));
5115 }
5116 
5117 TEST_P(BuildSyntaxTreeTest, TrailingReturn) {
5118   if (!GetParam().isCXX11OrLater()) {
5119     return;
5120   }
5121   EXPECT_TRUE(treeDumpEqual(
5122       R"cpp(
5123 auto foo() -> int;
5124 )cpp",
5125       R"txt(
5126 TranslationUnit Detached
5127 `-SimpleDeclaration
5128   |-'auto'
5129   |-SimpleDeclarator Declarator
5130   | |-'foo'
5131   | `-ParametersAndQualifiers
5132   |   |-'(' OpenParen
5133   |   |-')' CloseParen
5134   |   `-TrailingReturnType TrailingReturn
5135   |     |-'->' ArrowToken
5136   |     `-'int'
5137   `-';'
5138 )txt"));
5139 }
5140 
5141 TEST_P(BuildSyntaxTreeTest, DynamicExceptionSpecification) {
5142   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
5143     return;
5144   }
5145   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5146       R"cpp(
5147 struct MyException1 {};
5148 struct MyException2 {};
5149 [[int a() throw();]]
5150 [[int b() throw(...);]]
5151 [[int c() throw(MyException1);]]
5152 [[int d() throw(MyException1, MyException2);]]
5153 )cpp",
5154       {R"txt(
5155 SimpleDeclaration
5156 |-'int'
5157 |-SimpleDeclarator Declarator
5158 | |-'a'
5159 | `-ParametersAndQualifiers
5160 |   |-'(' OpenParen
5161 |   |-')' CloseParen
5162 |   |-'throw'
5163 |   |-'('
5164 |   `-')'
5165 `-';'
5166 )txt",
5167        R"txt(
5168 SimpleDeclaration
5169 |-'int'
5170 |-SimpleDeclarator Declarator
5171 | |-'b'
5172 | `-ParametersAndQualifiers
5173 |   |-'(' OpenParen
5174 |   |-')' CloseParen
5175 |   |-'throw'
5176 |   |-'('
5177 |   |-'...'
5178 |   `-')'
5179 `-';'
5180 )txt",
5181        R"txt(
5182 SimpleDeclaration
5183 |-'int'
5184 |-SimpleDeclarator Declarator
5185 | |-'c'
5186 | `-ParametersAndQualifiers
5187 |   |-'(' OpenParen
5188 |   |-')' CloseParen
5189 |   |-'throw'
5190 |   |-'('
5191 |   |-'MyException1'
5192 |   `-')'
5193 `-';'
5194 )txt",
5195        R"txt(
5196 SimpleDeclaration
5197 |-'int'
5198 |-SimpleDeclarator Declarator
5199 | |-'d'
5200 | `-ParametersAndQualifiers
5201 |   |-'(' OpenParen
5202 |   |-')' CloseParen
5203 |   |-'throw'
5204 |   |-'('
5205 |   |-'MyException1'
5206 |   |-','
5207 |   |-'MyException2'
5208 |   `-')'
5209 `-';'
5210 )txt"}));
5211 }
5212 
5213 TEST_P(BuildSyntaxTreeTest, NoexceptExceptionSpecification) {
5214   if (!GetParam().isCXX11OrLater()) {
5215     return;
5216   }
5217   EXPECT_TRUE(treeDumpEqual(
5218       R"cpp(
5219 int a() noexcept;
5220 int b() noexcept(true);
5221 )cpp",
5222       R"txt(
5223 TranslationUnit Detached
5224 |-SimpleDeclaration
5225 | |-'int'
5226 | |-SimpleDeclarator Declarator
5227 | | |-'a'
5228 | | `-ParametersAndQualifiers
5229 | |   |-'(' OpenParen
5230 | |   |-')' CloseParen
5231 | |   `-'noexcept'
5232 | `-';'
5233 `-SimpleDeclaration
5234   |-'int'
5235   |-SimpleDeclarator Declarator
5236   | |-'b'
5237   | `-ParametersAndQualifiers
5238   |   |-'(' OpenParen
5239   |   |-')' CloseParen
5240   |   |-'noexcept'
5241   |   |-'('
5242   |   |-BoolLiteralExpression
5243   |   | `-'true' LiteralToken
5244   |   `-')'
5245   `-';'
5246 )txt"));
5247 }
5248 
5249 TEST_P(BuildSyntaxTreeTest, DeclaratorsInParentheses) {
5250   EXPECT_TRUE(treeDumpEqual(
5251       R"cpp(
5252 int (a);
5253 int *(b);
5254 int (*c)(int);
5255 int *(d)(int);
5256 )cpp",
5257       R"txt(
5258 TranslationUnit Detached
5259 |-SimpleDeclaration
5260 | |-'int'
5261 | |-SimpleDeclarator Declarator
5262 | | `-ParenDeclarator
5263 | |   |-'(' OpenParen
5264 | |   |-'a'
5265 | |   `-')' CloseParen
5266 | `-';'
5267 |-SimpleDeclaration
5268 | |-'int'
5269 | |-SimpleDeclarator Declarator
5270 | | |-'*'
5271 | | `-ParenDeclarator
5272 | |   |-'(' OpenParen
5273 | |   |-'b'
5274 | |   `-')' CloseParen
5275 | `-';'
5276 |-SimpleDeclaration
5277 | |-'int'
5278 | |-SimpleDeclarator Declarator
5279 | | |-ParenDeclarator
5280 | | | |-'(' OpenParen
5281 | | | |-'*'
5282 | | | |-'c'
5283 | | | `-')' CloseParen
5284 | | `-ParametersAndQualifiers
5285 | |   |-'(' OpenParen
5286 | |   |-ParameterDeclarationList Parameters
5287 | |   | `-SimpleDeclaration ListElement
5288 | |   |   `-'int'
5289 | |   `-')' CloseParen
5290 | `-';'
5291 `-SimpleDeclaration
5292   |-'int'
5293   |-SimpleDeclarator Declarator
5294   | |-'*'
5295   | |-ParenDeclarator
5296   | | |-'(' OpenParen
5297   | | |-'d'
5298   | | `-')' CloseParen
5299   | `-ParametersAndQualifiers
5300   |   |-'(' OpenParen
5301   |   |-ParameterDeclarationList Parameters
5302   |   | `-SimpleDeclaration ListElement
5303   |   |   `-'int'
5304   |   `-')' CloseParen
5305   `-';'
5306 )txt"));
5307 }
5308 
5309 TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_SimpleConst) {
5310   EXPECT_TRUE(treeDumpEqual(
5311       R"cpp(
5312 const int west = -1;
5313 int const east = 1;
5314 )cpp",
5315       R"txt(
5316 TranslationUnit Detached
5317 |-SimpleDeclaration
5318 | |-'const'
5319 | |-'int'
5320 | |-SimpleDeclarator Declarator
5321 | | |-'west'
5322 | | |-'='
5323 | | `-PrefixUnaryOperatorExpression
5324 | |   |-'-' OperatorToken
5325 | |   `-IntegerLiteralExpression Operand
5326 | |     `-'1' LiteralToken
5327 | `-';'
5328 `-SimpleDeclaration
5329   |-'int'
5330   |-'const'
5331   |-SimpleDeclarator Declarator
5332   | |-'east'
5333   | |-'='
5334   | `-IntegerLiteralExpression
5335   |   `-'1' LiteralToken
5336   `-';'
5337 )txt"));
5338 }
5339 
5340 TEST_P(BuildSyntaxTreeTest, Declaration_ConstVolatileQualifiers_MultipleConst) {
5341   EXPECT_TRUE(treeDumpEqual(
5342       R"cpp(
5343 const int const universal = 0;
5344 )cpp",
5345       R"txt(
5346 TranslationUnit Detached
5347 `-SimpleDeclaration
5348   |-'const'
5349   |-'int'
5350   |-'const'
5351   |-SimpleDeclarator Declarator
5352   | |-'universal'
5353   | |-'='
5354   | `-IntegerLiteralExpression
5355   |   `-'0' LiteralToken
5356   `-';'
5357 )txt"));
5358 }
5359 
5360 TEST_P(BuildSyntaxTreeTest,
5361        Declaration_ConstVolatileQualifiers_ConstAndVolatile) {
5362   EXPECT_TRUE(treeDumpEqual(
5363       R"cpp(
5364 const int const *const *volatile b;
5365 )cpp",
5366       R"txt(
5367 TranslationUnit Detached
5368 `-SimpleDeclaration
5369   |-'const'
5370   |-'int'
5371   |-'const'
5372   |-SimpleDeclarator Declarator
5373   | |-'*'
5374   | |-'const'
5375   | |-'*'
5376   | |-'volatile'
5377   | `-'b'
5378   `-';'
5379 )txt"));
5380 }
5381 
5382 TEST_P(BuildSyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
5383   if (!GetParam().isCXX11OrLater()) {
5384     return;
5385   }
5386   EXPECT_TRUE(treeDumpEqual(
5387       R"cpp(
5388 auto foo() -> auto(*)(int) -> double*;
5389 )cpp",
5390       R"txt(
5391 TranslationUnit Detached
5392 `-SimpleDeclaration
5393   |-'auto'
5394   |-SimpleDeclarator Declarator
5395   | |-'foo'
5396   | `-ParametersAndQualifiers
5397   |   |-'(' OpenParen
5398   |   |-')' CloseParen
5399   |   `-TrailingReturnType TrailingReturn
5400   |     |-'->' ArrowToken
5401   |     |-'auto'
5402   |     `-SimpleDeclarator Declarator
5403   |       |-ParenDeclarator
5404   |       | |-'(' OpenParen
5405   |       | |-'*'
5406   |       | `-')' CloseParen
5407   |       `-ParametersAndQualifiers
5408   |         |-'(' OpenParen
5409   |         |-ParameterDeclarationList Parameters
5410   |         | `-SimpleDeclaration ListElement
5411   |         |   `-'int'
5412   |         |-')' CloseParen
5413   |         `-TrailingReturnType TrailingReturn
5414   |           |-'->' ArrowToken
5415   |           |-'double'
5416   |           `-SimpleDeclarator Declarator
5417   |             `-'*'
5418   `-';'
5419 )txt"));
5420 }
5421 
5422 TEST_P(BuildSyntaxTreeTest, MemberPointers) {
5423   if (!GetParam().isCXX()) {
5424     return;
5425   }
5426   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5427       R"cpp(
5428 struct X {};
5429 [[int X::* a;]]
5430 [[const int X::* b;]]
5431 )cpp",
5432       {R"txt(
5433 SimpleDeclaration
5434 |-'int'
5435 |-SimpleDeclarator Declarator
5436 | |-MemberPointer
5437 | | |-'X'
5438 | | |-'::'
5439 | | `-'*'
5440 | `-'a'
5441 `-';'
5442 )txt",
5443        R"txt(
5444 SimpleDeclaration
5445 |-'const'
5446 |-'int'
5447 |-SimpleDeclarator Declarator
5448 | |-MemberPointer
5449 | | |-'X'
5450 | | |-'::'
5451 | | `-'*'
5452 | `-'b'
5453 `-';'
5454 )txt"}));
5455 }
5456 
5457 TEST_P(BuildSyntaxTreeTest, MemberFunctionPointer) {
5458   if (!GetParam().isCXX()) {
5459     return;
5460   }
5461   EXPECT_TRUE(treeDumpEqualOnAnnotations(
5462       R"cpp(
5463 struct X {
5464   struct Y {};
5465 };
5466 [[void (X::*xp)();]]
5467 [[void (X::**xpp)(const int*);]]
5468 // FIXME: Generate the right syntax tree for this type,
5469 // i.e. create a syntax node for the outer member pointer
5470 [[void (X::Y::*xyp)(const int*, char);]]
5471 )cpp",
5472       {R"txt(
5473 SimpleDeclaration
5474 |-'void'
5475 |-SimpleDeclarator Declarator
5476 | |-ParenDeclarator
5477 | | |-'(' OpenParen
5478 | | |-MemberPointer
5479 | | | |-'X'
5480 | | | |-'::'
5481 | | | `-'*'
5482 | | |-'xp'
5483 | | `-')' CloseParen
5484 | `-ParametersAndQualifiers
5485 |   |-'(' OpenParen
5486 |   `-')' CloseParen
5487 `-';'
5488 )txt",
5489        R"txt(
5490 SimpleDeclaration
5491 |-'void'
5492 |-SimpleDeclarator Declarator
5493 | |-ParenDeclarator
5494 | | |-'(' OpenParen
5495 | | |-MemberPointer
5496 | | | |-'X'
5497 | | | |-'::'
5498 | | | `-'*'
5499 | | |-'*'
5500 | | |-'xpp'
5501 | | `-')' CloseParen
5502 | `-ParametersAndQualifiers
5503 |   |-'(' OpenParen
5504 |   |-ParameterDeclarationList Parameters
5505 |   | `-SimpleDeclaration ListElement
5506 |   |   |-'const'
5507 |   |   |-'int'
5508 |   |   `-SimpleDeclarator Declarator
5509 |   |     `-'*'
5510 |   `-')' CloseParen
5511 `-';'
5512 )txt",
5513        R"txt(
5514 SimpleDeclaration
5515 |-'void'
5516 |-SimpleDeclarator Declarator
5517 | |-ParenDeclarator
5518 | | |-'(' OpenParen
5519 | | |-'X'
5520 | | |-'::'
5521 | | |-MemberPointer
5522 | | | |-'Y'
5523 | | | |-'::'
5524 | | | `-'*'
5525 | | |-'xyp'
5526 | | `-')' CloseParen
5527 | `-ParametersAndQualifiers
5528 |   |-'(' OpenParen
5529 |   |-ParameterDeclarationList Parameters
5530 |   | |-SimpleDeclaration ListElement
5531 |   | | |-'const'
5532 |   | | |-'int'
5533 |   | | `-SimpleDeclarator Declarator
5534 |   | |   `-'*'
5535 |   | |-',' ListDelimiter
5536 |   | `-SimpleDeclaration ListElement
5537 |   |   `-'char'
5538 |   `-')' CloseParen
5539 `-';'
5540 )txt"}));
5541 }
5542 
5543 TEST_P(BuildSyntaxTreeTest, ComplexDeclarator) {
5544   EXPECT_TRUE(treeDumpEqual(
5545       R"cpp(
5546 void x(char a, short (*b)(int));
5547 )cpp",
5548       R"txt(
5549 TranslationUnit Detached
5550 `-SimpleDeclaration
5551   |-'void'
5552   |-SimpleDeclarator Declarator
5553   | |-'x'
5554   | `-ParametersAndQualifiers
5555   |   |-'(' OpenParen
5556   |   |-ParameterDeclarationList Parameters
5557   |   | |-SimpleDeclaration ListElement
5558   |   | | |-'char'
5559   |   | | `-SimpleDeclarator Declarator
5560   |   | |   `-'a'
5561   |   | |-',' ListDelimiter
5562   |   | `-SimpleDeclaration ListElement
5563   |   |   |-'short'
5564   |   |   `-SimpleDeclarator Declarator
5565   |   |     |-ParenDeclarator
5566   |   |     | |-'(' OpenParen
5567   |   |     | |-'*'
5568   |   |     | |-'b'
5569   |   |     | `-')' CloseParen
5570   |   |     `-ParametersAndQualifiers
5571   |   |       |-'(' OpenParen
5572   |   |       |-ParameterDeclarationList Parameters
5573   |   |       | `-SimpleDeclaration ListElement
5574   |   |       |   `-'int'
5575   |   |       `-')' CloseParen
5576   |   `-')' CloseParen
5577   `-';'
5578 )txt"));
5579 }
5580 
5581 TEST_P(BuildSyntaxTreeTest, ComplexDeclarator2) {
5582   EXPECT_TRUE(treeDumpEqual(
5583       R"cpp(
5584 void x(char a, short (*b)(int), long (**c)(long long));
5585 )cpp",
5586       R"txt(
5587 TranslationUnit Detached
5588 `-SimpleDeclaration
5589   |-'void'
5590   |-SimpleDeclarator Declarator
5591   | |-'x'
5592   | `-ParametersAndQualifiers
5593   |   |-'(' OpenParen
5594   |   |-ParameterDeclarationList Parameters
5595   |   | |-SimpleDeclaration ListElement
5596   |   | | |-'char'
5597   |   | | `-SimpleDeclarator Declarator
5598   |   | |   `-'a'
5599   |   | |-',' ListDelimiter
5600   |   | |-SimpleDeclaration ListElement
5601   |   | | |-'short'
5602   |   | | `-SimpleDeclarator Declarator
5603   |   | |   |-ParenDeclarator
5604   |   | |   | |-'(' OpenParen
5605   |   | |   | |-'*'
5606   |   | |   | |-'b'
5607   |   | |   | `-')' CloseParen
5608   |   | |   `-ParametersAndQualifiers
5609   |   | |     |-'(' OpenParen
5610   |   | |     |-ParameterDeclarationList Parameters
5611   |   | |     | `-SimpleDeclaration ListElement
5612   |   | |     |   `-'int'
5613   |   | |     `-')' CloseParen
5614   |   | |-',' ListDelimiter
5615   |   | `-SimpleDeclaration ListElement
5616   |   |   |-'long'
5617   |   |   `-SimpleDeclarator Declarator
5618   |   |     |-ParenDeclarator
5619   |   |     | |-'(' OpenParen
5620   |   |     | |-'*'
5621   |   |     | |-'*'
5622   |   |     | |-'c'
5623   |   |     | `-')' CloseParen
5624   |   |     `-ParametersAndQualifiers
5625   |   |       |-'(' OpenParen
5626   |   |       |-ParameterDeclarationList Parameters
5627   |   |       | `-SimpleDeclaration ListElement
5628   |   |       |   |-'long'
5629   |   |       |   `-'long'
5630   |   |       `-')' CloseParen
5631   |   `-')' CloseParen
5632   `-';'
5633 )txt"));
5634 }
5635 
5636 } // namespace
5637