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