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