1 //===- TreeTest.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 #include "clang/Tooling/Syntax/Tree.h"
10 #include "clang/AST/ASTConsumer.h"
11 #include "clang/AST/Decl.h"
12 #include "clang/AST/Stmt.h"
13 #include "clang/Basic/LLVM.h"
14 #include "clang/Basic/TokenKinds.h"
15 #include "clang/Frontend/CompilerInstance.h"
16 #include "clang/Frontend/CompilerInvocation.h"
17 #include "clang/Frontend/FrontendAction.h"
18 #include "clang/Frontend/TextDiagnosticPrinter.h"
19 #include "clang/Lex/PreprocessorOptions.h"
20 #include "clang/Testing/CommandLineArgs.h"
21 #include "clang/Testing/TestClangConfig.h"
22 #include "clang/Tooling/Core/Replacement.h"
23 #include "clang/Tooling/Syntax/BuildTree.h"
24 #include "clang/Tooling/Syntax/Mutations.h"
25 #include "clang/Tooling/Syntax/Nodes.h"
26 #include "clang/Tooling/Syntax/Tokens.h"
27 #include "clang/Tooling/Tooling.h"
28 #include "llvm/ADT/ArrayRef.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/ADT/StringExtras.h"
31 #include "llvm/ADT/StringRef.h"
32 #include "llvm/Support/Casting.h"
33 #include "llvm/Support/Error.h"
34 #include "llvm/Testing/Support/Annotations.h"
35 #include "gmock/gmock.h"
36 #include "gtest/gtest.h"
37 #include <cstdlib>
38 #include <memory>
39 
40 using namespace clang;
41 
42 namespace {
43 static ArrayRef<syntax::Token> tokens(syntax::Node *N) {
44   assert(N->isOriginal() && "tokens of modified nodes are not well-defined");
45   if (auto *L = dyn_cast<syntax::Leaf>(N))
46     return llvm::makeArrayRef(L->token(), 1);
47   auto *T = cast<syntax::Tree>(N);
48   return llvm::makeArrayRef(T->firstLeaf()->token(),
49                             T->lastLeaf()->token() + 1);
50 }
51 
52 class SyntaxTreeTest : public ::testing::Test,
53                        public ::testing::WithParamInterface<TestClangConfig> {
54 protected:
55   // Build a syntax tree for the code.
56   syntax::TranslationUnit *buildTree(StringRef Code,
57                                      const TestClangConfig &ClangConfig) {
58     // FIXME: this code is almost the identical to the one in TokensTest. Share
59     //        it.
60     class BuildSyntaxTree : public ASTConsumer {
61     public:
62       BuildSyntaxTree(syntax::TranslationUnit *&Root,
63                       std::unique_ptr<syntax::TokenBuffer> &TB,
64                       std::unique_ptr<syntax::Arena> &Arena,
65                       std::unique_ptr<syntax::TokenCollector> Tokens)
66           : Root(Root), TB(TB), Arena(Arena), Tokens(std::move(Tokens)) {
67         assert(this->Tokens);
68       }
69 
70       void HandleTranslationUnit(ASTContext &Ctx) override {
71         TB =
72             std::make_unique<syntax::TokenBuffer>(std::move(*Tokens).consume());
73         Tokens = nullptr; // make sure we fail if this gets called twice.
74         Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(),
75                                                 Ctx.getLangOpts(), *TB);
76         Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl());
77       }
78 
79     private:
80       syntax::TranslationUnit *&Root;
81       std::unique_ptr<syntax::TokenBuffer> &TB;
82       std::unique_ptr<syntax::Arena> &Arena;
83       std::unique_ptr<syntax::TokenCollector> Tokens;
84     };
85 
86     class BuildSyntaxTreeAction : public ASTFrontendAction {
87     public:
88       BuildSyntaxTreeAction(syntax::TranslationUnit *&Root,
89                             std::unique_ptr<syntax::TokenBuffer> &TB,
90                             std::unique_ptr<syntax::Arena> &Arena)
91           : Root(Root), TB(TB), Arena(Arena) {}
92 
93       std::unique_ptr<ASTConsumer>
94       CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
95         // We start recording the tokens, ast consumer will take on the result.
96         auto Tokens =
97             std::make_unique<syntax::TokenCollector>(CI.getPreprocessor());
98         return std::make_unique<BuildSyntaxTree>(Root, TB, Arena,
99                                                  std::move(Tokens));
100       }
101 
102     private:
103       syntax::TranslationUnit *&Root;
104       std::unique_ptr<syntax::TokenBuffer> &TB;
105       std::unique_ptr<syntax::Arena> &Arena;
106     };
107 
108     constexpr const char *FileName = "./input.cpp";
109     FS->addFile(FileName, time_t(), llvm::MemoryBuffer::getMemBufferCopy(""));
110 
111     if (!Diags->getClient())
112       Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), DiagOpts.get()));
113     Diags->setSeverityForGroup(diag::Flavor::WarningOrError, "unused-value",
114                                diag::Severity::Ignored, SourceLocation());
115 
116     // Prepare to run a compiler.
117     std::vector<std::string> Args = {
118         "syntax-test",
119         "-fsyntax-only",
120     };
121     llvm::copy(ClangConfig.getCommandLineArgs(), std::back_inserter(Args));
122     Args.push_back(FileName);
123 
124     std::vector<const char *> ArgsCStr;
125     for (const std::string &arg : Args) {
126       ArgsCStr.push_back(arg.c_str());
127     }
128 
129     Invocation = createInvocationFromCommandLine(ArgsCStr, Diags, FS);
130     assert(Invocation);
131     Invocation->getFrontendOpts().DisableFree = false;
132     Invocation->getPreprocessorOpts().addRemappedFile(
133         FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release());
134     CompilerInstance Compiler;
135     Compiler.setInvocation(Invocation);
136     Compiler.setDiagnostics(Diags.get());
137     Compiler.setFileManager(FileMgr.get());
138     Compiler.setSourceManager(SourceMgr.get());
139 
140     syntax::TranslationUnit *Root = nullptr;
141     BuildSyntaxTreeAction Recorder(Root, this->TB, this->Arena);
142 
143     // Action could not be executed but the frontend didn't identify any errors
144     // in the code ==> problem in setting up the action.
145     if (!Compiler.ExecuteAction(Recorder) &&
146         Diags->getClient()->getNumErrors() == 0) {
147       ADD_FAILURE() << "failed to run the frontend";
148       std::abort();
149     }
150     return Root;
151   }
152 
153   ::testing::AssertionResult treeDumpEqual(StringRef Code, StringRef Tree) {
154     SCOPED_TRACE(llvm::join(GetParam().getCommandLineArgs(), " "));
155 
156     auto *Root = buildTree(Code, GetParam());
157     if (Diags->getClient()->getNumErrors() != 0) {
158       return ::testing::AssertionFailure()
159              << "Source file has syntax errors, they were printed to the test "
160                 "log";
161     }
162     std::string Actual = std::string(StringRef(Root->dump(*Arena)).trim());
163     // EXPECT_EQ shows the diff between the two strings if they are different.
164     EXPECT_EQ(Tree.trim().str(), Actual);
165     if (Actual != Tree.trim().str()) {
166       return ::testing::AssertionFailure();
167     }
168     return ::testing::AssertionSuccess();
169   }
170 
171   // Adds a file to the test VFS.
172   void addFile(StringRef Path, StringRef Contents) {
173     if (!FS->addFile(Path, time_t(),
174                      llvm::MemoryBuffer::getMemBufferCopy(Contents))) {
175       ADD_FAILURE() << "could not add a file to VFS: " << Path;
176     }
177   }
178 
179   /// Finds the deepest node in the tree that covers exactly \p R.
180   /// FIXME: implement this efficiently and move to public syntax tree API.
181   syntax::Node *nodeByRange(llvm::Annotations::Range R, syntax::Node *Root) {
182     ArrayRef<syntax::Token> Toks = tokens(Root);
183 
184     if (Toks.front().location().isFileID() &&
185         Toks.back().location().isFileID() &&
186         syntax::Token::range(*SourceMgr, Toks.front(), Toks.back()) ==
187             syntax::FileRange(SourceMgr->getMainFileID(), R.Begin, R.End))
188       return Root;
189 
190     auto *T = dyn_cast<syntax::Tree>(Root);
191     if (!T)
192       return nullptr;
193     for (auto *C = T->firstChild(); C != nullptr; C = C->nextSibling()) {
194       if (auto *Result = nodeByRange(R, C))
195         return Result;
196     }
197     return nullptr;
198   }
199 
200   // Data fields.
201   IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
202   IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
203       new DiagnosticsEngine(new DiagnosticIDs, DiagOpts.get());
204   IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS =
205       new llvm::vfs::InMemoryFileSystem;
206   IntrusiveRefCntPtr<FileManager> FileMgr =
207       new FileManager(FileSystemOptions(), FS);
208   IntrusiveRefCntPtr<SourceManager> SourceMgr =
209       new SourceManager(*Diags, *FileMgr);
210   std::shared_ptr<CompilerInvocation> Invocation;
211   // Set after calling buildTree().
212   std::unique_ptr<syntax::TokenBuffer> TB;
213   std::unique_ptr<syntax::Arena> Arena;
214 };
215 
216 TEST_P(SyntaxTreeTest, Simple) {
217   EXPECT_TRUE(treeDumpEqual(
218       R"cpp(
219 int main() {}
220 void foo() {}
221 )cpp",
222       R"txt(
223 *: TranslationUnit
224 |-SimpleDeclaration
225 | |-int
226 | |-SimpleDeclarator
227 | | |-main
228 | | `-ParametersAndQualifiers
229 | |   |-(
230 | |   `-)
231 | `-CompoundStatement
232 |   |-{
233 |   `-}
234 `-SimpleDeclaration
235   |-void
236   |-SimpleDeclarator
237   | |-foo
238   | `-ParametersAndQualifiers
239   |   |-(
240   |   `-)
241   `-CompoundStatement
242     |-{
243     `-}
244 )txt"));
245 }
246 
247 TEST_P(SyntaxTreeTest, SimpleVariable) {
248   EXPECT_TRUE(treeDumpEqual(
249       R"cpp(
250 int a;
251 int b = 42;
252 )cpp",
253       R"txt(
254 *: TranslationUnit
255 |-SimpleDeclaration
256 | |-int
257 | |-SimpleDeclarator
258 | | `-a
259 | `-;
260 `-SimpleDeclaration
261   |-int
262   |-SimpleDeclarator
263   | |-b
264   | |-=
265   | `-IntegerLiteralExpression
266   |   `-42
267   `-;
268 )txt"));
269 }
270 
271 TEST_P(SyntaxTreeTest, SimpleFunction) {
272   EXPECT_TRUE(treeDumpEqual(
273       R"cpp(
274 void foo(int a, int b) {}
275 )cpp",
276       R"txt(
277 *: TranslationUnit
278 `-SimpleDeclaration
279   |-void
280   |-SimpleDeclarator
281   | |-foo
282   | `-ParametersAndQualifiers
283   |   |-(
284   |   |-SimpleDeclaration
285   |   | |-int
286   |   | `-SimpleDeclarator
287   |   |   `-a
288   |   |-,
289   |   |-SimpleDeclaration
290   |   | |-int
291   |   | `-SimpleDeclarator
292   |   |   `-b
293   |   `-)
294   `-CompoundStatement
295     |-{
296     `-}
297 )txt"));
298 }
299 
300 TEST_P(SyntaxTreeTest, If) {
301   EXPECT_TRUE(treeDumpEqual(
302       R"cpp(
303 int main() {
304   if (1) {}
305   if (1) {} else if (0) {}
306 }
307 )cpp",
308       R"txt(
309 *: TranslationUnit
310 `-SimpleDeclaration
311   |-int
312   |-SimpleDeclarator
313   | |-main
314   | `-ParametersAndQualifiers
315   |   |-(
316   |   `-)
317   `-CompoundStatement
318     |-{
319     |-IfStatement
320     | |-if
321     | |-(
322     | |-IntegerLiteralExpression
323     | | `-1
324     | |-)
325     | `-CompoundStatement
326     |   |-{
327     |   `-}
328     |-IfStatement
329     | |-if
330     | |-(
331     | |-IntegerLiteralExpression
332     | | `-1
333     | |-)
334     | |-CompoundStatement
335     | | |-{
336     | | `-}
337     | |-else
338     | `-IfStatement
339     |   |-if
340     |   |-(
341     |   |-IntegerLiteralExpression
342     |   | `-0
343     |   |-)
344     |   `-CompoundStatement
345     |     |-{
346     |     `-}
347     `-}
348 )txt"));
349 }
350 
351 TEST_P(SyntaxTreeTest, For) {
352   EXPECT_TRUE(treeDumpEqual(
353       R"cpp(
354 void test() {
355   for (;;)  {}
356 }
357 )cpp",
358       R"txt(
359 *: TranslationUnit
360 `-SimpleDeclaration
361   |-void
362   |-SimpleDeclarator
363   | |-test
364   | `-ParametersAndQualifiers
365   |   |-(
366   |   `-)
367   `-CompoundStatement
368     |-{
369     |-ForStatement
370     | |-for
371     | |-(
372     | |-;
373     | |-;
374     | |-)
375     | `-CompoundStatement
376     |   |-{
377     |   `-}
378     `-}
379 )txt"));
380 }
381 
382 TEST_P(SyntaxTreeTest, RangeBasedFor) {
383   if (!GetParam().isCXX11OrLater()) {
384     return;
385   }
386   EXPECT_TRUE(treeDumpEqual(
387       R"cpp(
388 void test() {
389   int a[3];
390   for (int x : a)
391     ;
392 }
393 )cpp",
394       R"txt(
395 *: TranslationUnit
396 `-SimpleDeclaration
397   |-void
398   |-SimpleDeclarator
399   | |-test
400   | `-ParametersAndQualifiers
401   |   |-(
402   |   `-)
403   `-CompoundStatement
404     |-{
405     |-DeclarationStatement
406     | |-SimpleDeclaration
407     | | |-int
408     | | `-SimpleDeclarator
409     | |   |-a
410     | |   `-ArraySubscript
411     | |     |-[
412     | |     |-IntegerLiteralExpression
413     | |     | `-3
414     | |     `-]
415     | `-;
416     |-RangeBasedForStatement
417     | |-for
418     | |-(
419     | |-SimpleDeclaration
420     | | |-int
421     | | |-SimpleDeclarator
422     | | | `-x
423     | | `-:
424     | |-IdExpression
425     | | `-UnqualifiedId
426     | |   `-a
427     | |-)
428     | `-EmptyStatement
429     |   `-;
430     `-}
431 )txt"));
432 }
433 
434 TEST_P(SyntaxTreeTest, DeclarationStatement) {
435   EXPECT_TRUE(treeDumpEqual(
436       R"cpp(
437 void test() {
438   int a = 10;
439 }
440 )cpp",
441       R"txt(
442 *: TranslationUnit
443 `-SimpleDeclaration
444   |-void
445   |-SimpleDeclarator
446   | |-test
447   | `-ParametersAndQualifiers
448   |   |-(
449   |   `-)
450   `-CompoundStatement
451     |-{
452     |-DeclarationStatement
453     | |-SimpleDeclaration
454     | | |-int
455     | | `-SimpleDeclarator
456     | |   |-a
457     | |   |-=
458     | |   `-IntegerLiteralExpression
459     | |     `-10
460     | `-;
461     `-}
462 )txt"));
463 }
464 
465 TEST_P(SyntaxTreeTest, Switch) {
466   EXPECT_TRUE(treeDumpEqual(
467       R"cpp(
468 void test() {
469   switch (1) {
470     case 0:
471     default:;
472   }
473 }
474 )cpp",
475       R"txt(
476 *: TranslationUnit
477 `-SimpleDeclaration
478   |-void
479   |-SimpleDeclarator
480   | |-test
481   | `-ParametersAndQualifiers
482   |   |-(
483   |   `-)
484   `-CompoundStatement
485     |-{
486     |-SwitchStatement
487     | |-switch
488     | |-(
489     | |-IntegerLiteralExpression
490     | | `-1
491     | |-)
492     | `-CompoundStatement
493     |   |-{
494     |   |-CaseStatement
495     |   | |-case
496     |   | |-IntegerLiteralExpression
497     |   | | `-0
498     |   | |-:
499     |   | `-DefaultStatement
500     |   |   |-default
501     |   |   |-:
502     |   |   `-EmptyStatement
503     |   |     `-;
504     |   `-}
505     `-}
506 )txt"));
507 }
508 
509 TEST_P(SyntaxTreeTest, While) {
510   EXPECT_TRUE(treeDumpEqual(
511       R"cpp(
512 void test() {
513   while (1) { continue; break; }
514 }
515 )cpp",
516       R"txt(
517 *: TranslationUnit
518 `-SimpleDeclaration
519   |-void
520   |-SimpleDeclarator
521   | |-test
522   | `-ParametersAndQualifiers
523   |   |-(
524   |   `-)
525   `-CompoundStatement
526     |-{
527     |-WhileStatement
528     | |-while
529     | |-(
530     | |-IntegerLiteralExpression
531     | | `-1
532     | |-)
533     | `-CompoundStatement
534     |   |-{
535     |   |-ContinueStatement
536     |   | |-continue
537     |   | `-;
538     |   |-BreakStatement
539     |   | |-break
540     |   | `-;
541     |   `-}
542     `-}
543 )txt"));
544 }
545 
546 TEST_P(SyntaxTreeTest, UnhandledStatement) {
547   // Unhandled statements should end up as 'unknown statement'.
548   // This example uses a 'label statement', which does not yet have a syntax
549   // counterpart.
550   EXPECT_TRUE(treeDumpEqual(
551       R"cpp(
552 int main() {
553   foo: return 100;
554 }
555 )cpp",
556       R"txt(
557 *: TranslationUnit
558 `-SimpleDeclaration
559   |-int
560   |-SimpleDeclarator
561   | |-main
562   | `-ParametersAndQualifiers
563   |   |-(
564   |   `-)
565   `-CompoundStatement
566     |-{
567     |-UnknownStatement
568     | |-foo
569     | |-:
570     | `-ReturnStatement
571     |   |-return
572     |   |-IntegerLiteralExpression
573     |   | `-100
574     |   `-;
575     `-}
576 )txt"));
577 }
578 
579 TEST_P(SyntaxTreeTest, Expressions) {
580   // expressions should be wrapped in 'ExpressionStatement' when they appear
581   // in a statement position.
582   EXPECT_TRUE(treeDumpEqual(
583       R"cpp(
584 void test() {
585   test();
586   if (1) test(); else test();
587 }
588 )cpp",
589       R"txt(
590 *: TranslationUnit
591 `-SimpleDeclaration
592   |-void
593   |-SimpleDeclarator
594   | |-test
595   | `-ParametersAndQualifiers
596   |   |-(
597   |   `-)
598   `-CompoundStatement
599     |-{
600     |-ExpressionStatement
601     | |-UnknownExpression
602     | | |-IdExpression
603     | | | `-UnqualifiedId
604     | | |   `-test
605     | | |-(
606     | | `-)
607     | `-;
608     |-IfStatement
609     | |-if
610     | |-(
611     | |-IntegerLiteralExpression
612     | | `-1
613     | |-)
614     | |-ExpressionStatement
615     | | |-UnknownExpression
616     | | | |-IdExpression
617     | | | | `-UnqualifiedId
618     | | | |   `-test
619     | | | |-(
620     | | | `-)
621     | | `-;
622     | |-else
623     | `-ExpressionStatement
624     |   |-UnknownExpression
625     |   | |-IdExpression
626     |   | | `-UnqualifiedId
627     |   | |   `-test
628     |   | |-(
629     |   | `-)
630     |   `-;
631     `-}
632 )txt"));
633 }
634 
635 TEST_P(SyntaxTreeTest, UnqualifiedId) {
636   if (!GetParam().isCXX()) {
637     return;
638   }
639   EXPECT_TRUE(treeDumpEqual(
640       R"cpp(
641 struct X {
642   // TODO: Expose `id-expression` from `Declarator`
643   friend X operator+(const X&, const X&);
644   operator int();
645 };
646 template<typename T>
647 void f(T&);
648 void test(X x) {
649   x;                      // identifier
650   operator+(x, x);        // operator-function-id
651   f<X>(x);                // template-id
652   // TODO: Expose `id-expression` from `MemberExpr`
653   x.operator int();       // conversion-funtion-id
654   x.~X();                 // ~type-name
655 }
656 )cpp",
657       R"txt(
658 *: TranslationUnit
659 |-SimpleDeclaration
660 | |-struct
661 | |-X
662 | |-{
663 | |-UnknownDeclaration
664 | | `-SimpleDeclaration
665 | |   |-friend
666 | |   |-X
667 | |   |-SimpleDeclarator
668 | |   | |-operator
669 | |   | |-+
670 | |   | `-ParametersAndQualifiers
671 | |   |   |-(
672 | |   |   |-SimpleDeclaration
673 | |   |   | |-const
674 | |   |   | |-X
675 | |   |   | `-SimpleDeclarator
676 | |   |   |   `-&
677 | |   |   |-,
678 | |   |   |-SimpleDeclaration
679 | |   |   | |-const
680 | |   |   | |-X
681 | |   |   | `-SimpleDeclarator
682 | |   |   |   `-&
683 | |   |   `-)
684 | |   `-;
685 | |-SimpleDeclaration
686 | | |-SimpleDeclarator
687 | | | |-operator
688 | | | |-int
689 | | | `-ParametersAndQualifiers
690 | | |   |-(
691 | | |   `-)
692 | | `-;
693 | |-}
694 | `-;
695 |-TemplateDeclaration
696 | |-template
697 | |-<
698 | |-UnknownDeclaration
699 | | |-typename
700 | | `-T
701 | |->
702 | `-SimpleDeclaration
703 |   |-void
704 |   |-SimpleDeclarator
705 |   | |-f
706 |   | `-ParametersAndQualifiers
707 |   |   |-(
708 |   |   |-SimpleDeclaration
709 |   |   | |-T
710 |   |   | `-SimpleDeclarator
711 |   |   |   `-&
712 |   |   `-)
713 |   `-;
714 `-SimpleDeclaration
715   |-void
716   |-SimpleDeclarator
717   | |-test
718   | `-ParametersAndQualifiers
719   |   |-(
720   |   |-SimpleDeclaration
721   |   | |-X
722   |   | `-SimpleDeclarator
723   |   |   `-x
724   |   `-)
725   `-CompoundStatement
726     |-{
727     |-ExpressionStatement
728     | |-IdExpression
729     | | `-UnqualifiedId
730     | |   `-x
731     | `-;
732     |-ExpressionStatement
733     | |-UnknownExpression
734     | | |-IdExpression
735     | | | `-UnqualifiedId
736     | | |   |-operator
737     | | |   `-+
738     | | |-(
739     | | |-IdExpression
740     | | | `-UnqualifiedId
741     | | |   `-x
742     | | |-,
743     | | |-IdExpression
744     | | | `-UnqualifiedId
745     | | |   `-x
746     | | `-)
747     | `-;
748     |-ExpressionStatement
749     | |-UnknownExpression
750     | | |-IdExpression
751     | | | `-UnqualifiedId
752     | | |   |-f
753     | | |   |-<
754     | | |   |-X
755     | | |   `->
756     | | |-(
757     | | |-IdExpression
758     | | | `-UnqualifiedId
759     | | |   `-x
760     | | `-)
761     | `-;
762     |-ExpressionStatement
763     | |-UnknownExpression
764     | | |-UnknownExpression
765     | | | |-IdExpression
766     | | | | `-UnqualifiedId
767     | | | |   `-x
768     | | | |-.
769     | | | |-operator
770     | | | `-int
771     | | |-(
772     | | `-)
773     | `-;
774     |-ExpressionStatement
775     | |-UnknownExpression
776     | | |-UnknownExpression
777     | | | |-IdExpression
778     | | | | `-UnqualifiedId
779     | | | |   `-x
780     | | | |-.
781     | | | |-~
782     | | | `-X
783     | | |-(
784     | | `-)
785     | `-;
786     `-}
787 )txt"));
788 }
789 
790 TEST_P(SyntaxTreeTest, UnqualifiedIdCxx11OrLater) {
791   if (!GetParam().isCXX11OrLater()) {
792     return;
793   }
794   EXPECT_TRUE(treeDumpEqual(
795       R"cpp(
796 struct X { };
797 unsigned operator "" _w(long long unsigned);
798 void test(X x) {
799   operator "" _w(1llu);   // literal-operator-id
800   // TODO: Expose `id-expression` from `MemberExpr`
801   x.~decltype(x)();       // ~decltype-specifier
802 }
803 )cpp",
804       R"txt(
805 *: TranslationUnit
806 |-SimpleDeclaration
807 | |-struct
808 | |-X
809 | |-{
810 | |-}
811 | `-;
812 |-SimpleDeclaration
813 | |-unsigned
814 | |-SimpleDeclarator
815 | | |-operator
816 | | |-""
817 | | |-_w
818 | | `-ParametersAndQualifiers
819 | |   |-(
820 | |   |-SimpleDeclaration
821 | |   | |-long
822 | |   | |-long
823 | |   | `-unsigned
824 | |   `-)
825 | `-;
826 `-SimpleDeclaration
827   |-void
828   |-SimpleDeclarator
829   | |-test
830   | `-ParametersAndQualifiers
831   |   |-(
832   |   |-SimpleDeclaration
833   |   | |-X
834   |   | `-SimpleDeclarator
835   |   |   `-x
836   |   `-)
837   `-CompoundStatement
838     |-{
839     |-ExpressionStatement
840     | |-UnknownExpression
841     | | |-IdExpression
842     | | | `-UnqualifiedId
843     | | |   |-operator
844     | | |   |-""
845     | | |   `-_w
846     | | |-(
847     | | |-IntegerLiteralExpression
848     | | | `-1llu
849     | | `-)
850     | `-;
851     |-ExpressionStatement
852     | |-UnknownExpression
853     | | |-UnknownExpression
854     | | | |-IdExpression
855     | | | | `-UnqualifiedId
856     | | | |   `-x
857     | | | |-.
858     | | | `-~
859     | | |-decltype
860     | | |-(
861     | | |-x
862     | | |-)
863     | | |-(
864     | | `-)
865     | `-;
866     `-}
867 )txt"));
868 }
869 
870 TEST_P(SyntaxTreeTest, QualifiedId) {
871   if (!GetParam().isCXX()) {
872     return;
873   }
874   EXPECT_TRUE(treeDumpEqual(
875       R"cpp(
876 namespace n {
877   struct S {
878     template<typename T>
879     struct ST {
880       static void f();
881     };
882   };
883 }
884 template<typename T>
885 struct ST {
886   struct S {
887     template<typename U>
888     static U f();
889   };
890 };
891 void test() {
892   ::                 // global-namespace-specifier
893   n::                // namespace-specifier
894   S::                // type-name-specifier
895   template ST<int>:: // type-template-instantiation-specifier
896   f();
897 
898   n::                // namespace-specifier
899   S::                // type-name-specifier
900   ST<int>::          // type-template-instantiation-specifier
901   f();
902 
903   ST<int>::         // type-name-specifier
904   S::               // type-name-specifier
905   f<int>();
906 
907   ST<int>::         // type-name-specifier
908   S::               // type-name-specifier
909   template f<int>();
910 }
911 )cpp",
912       R"txt(
913 *: TranslationUnit
914 |-NamespaceDefinition
915 | |-namespace
916 | |-n
917 | |-{
918 | |-SimpleDeclaration
919 | | |-struct
920 | | |-S
921 | | |-{
922 | | |-TemplateDeclaration
923 | | | |-template
924 | | | |-<
925 | | | |-UnknownDeclaration
926 | | | | |-typename
927 | | | | `-T
928 | | | |->
929 | | | `-SimpleDeclaration
930 | | |   |-struct
931 | | |   |-ST
932 | | |   |-{
933 | | |   |-SimpleDeclaration
934 | | |   | |-static
935 | | |   | |-void
936 | | |   | |-SimpleDeclarator
937 | | |   | | |-f
938 | | |   | | `-ParametersAndQualifiers
939 | | |   | |   |-(
940 | | |   | |   `-)
941 | | |   | `-;
942 | | |   |-}
943 | | |   `-;
944 | | |-}
945 | | `-;
946 | `-}
947 |-TemplateDeclaration
948 | |-template
949 | |-<
950 | |-UnknownDeclaration
951 | | |-typename
952 | | `-T
953 | |->
954 | `-SimpleDeclaration
955 |   |-struct
956 |   |-ST
957 |   |-{
958 |   |-SimpleDeclaration
959 |   | |-struct
960 |   | |-S
961 |   | |-{
962 |   | |-TemplateDeclaration
963 |   | | |-template
964 |   | | |-<
965 |   | | |-UnknownDeclaration
966 |   | | | |-typename
967 |   | | | `-U
968 |   | | |->
969 |   | | `-SimpleDeclaration
970 |   | |   |-static
971 |   | |   |-U
972 |   | |   |-SimpleDeclarator
973 |   | |   | |-f
974 |   | |   | `-ParametersAndQualifiers
975 |   | |   |   |-(
976 |   | |   |   `-)
977 |   | |   `-;
978 |   | |-}
979 |   | `-;
980 |   |-}
981 |   `-;
982 `-SimpleDeclaration
983   |-void
984   |-SimpleDeclarator
985   | |-test
986   | `-ParametersAndQualifiers
987   |   |-(
988   |   `-)
989   `-CompoundStatement
990     |-{
991     |-ExpressionStatement
992     | |-UnknownExpression
993     | | |-IdExpression
994     | | | |-NestedNameSpecifier
995     | | | | |-::
996     | | | | |-IdentifierNameSpecifier
997     | | | | | `-n
998     | | | | |-::
999     | | | | |-IdentifierNameSpecifier
1000     | | | | | `-S
1001     | | | | |-::
1002     | | | | |-SimpleTemplateNameSpecifier
1003     | | | | | |-template
1004     | | | | | |-ST
1005     | | | | | |-<
1006     | | | | | |-int
1007     | | | | | `->
1008     | | | | `-::
1009     | | | `-UnqualifiedId
1010     | | |   `-f
1011     | | |-(
1012     | | `-)
1013     | `-;
1014     |-ExpressionStatement
1015     | |-UnknownExpression
1016     | | |-IdExpression
1017     | | | |-NestedNameSpecifier
1018     | | | | |-IdentifierNameSpecifier
1019     | | | | | `-n
1020     | | | | |-::
1021     | | | | |-IdentifierNameSpecifier
1022     | | | | | `-S
1023     | | | | |-::
1024     | | | | |-SimpleTemplateNameSpecifier
1025     | | | | | |-ST
1026     | | | | | |-<
1027     | | | | | |-int
1028     | | | | | `->
1029     | | | | `-::
1030     | | | `-UnqualifiedId
1031     | | |   `-f
1032     | | |-(
1033     | | `-)
1034     | `-;
1035     |-ExpressionStatement
1036     | |-UnknownExpression
1037     | | |-IdExpression
1038     | | | |-NestedNameSpecifier
1039     | | | | |-SimpleTemplateNameSpecifier
1040     | | | | | |-ST
1041     | | | | | |-<
1042     | | | | | |-int
1043     | | | | | `->
1044     | | | | |-::
1045     | | | | |-IdentifierNameSpecifier
1046     | | | | | `-S
1047     | | | | `-::
1048     | | | `-UnqualifiedId
1049     | | |   |-f
1050     | | |   |-<
1051     | | |   |-int
1052     | | |   `->
1053     | | |-(
1054     | | `-)
1055     | `-;
1056     |-ExpressionStatement
1057     | |-UnknownExpression
1058     | | |-IdExpression
1059     | | | |-NestedNameSpecifier
1060     | | | | |-SimpleTemplateNameSpecifier
1061     | | | | | |-ST
1062     | | | | | |-<
1063     | | | | | |-int
1064     | | | | | `->
1065     | | | | |-::
1066     | | | | |-IdentifierNameSpecifier
1067     | | | | | `-S
1068     | | | | `-::
1069     | | | |-template
1070     | | | `-UnqualifiedId
1071     | | |   |-f
1072     | | |   |-<
1073     | | |   |-int
1074     | | |   `->
1075     | | |-(
1076     | | `-)
1077     | `-;
1078     `-}
1079 )txt"));
1080 }
1081 
1082 TEST_P(SyntaxTreeTest, QualifiedIdWithDependentType) {
1083   if (!GetParam().isCXX()) {
1084     return;
1085   }
1086   if (GetParam().hasDelayedTemplateParsing()) {
1087     // FIXME: Make this test work on Windows by generating the expected syntax
1088     // tree when `-fdelayed-template-parsing` is active.
1089     return;
1090   }
1091   EXPECT_TRUE(treeDumpEqual(
1092       R"cpp(
1093 template <typename T>
1094 void test() {
1095   T::template U<int>::f();
1096 
1097   T::U::f();
1098 
1099   T::template f<0>();
1100 }
1101 )cpp",
1102       R"txt(
1103 *: TranslationUnit
1104 `-TemplateDeclaration
1105   |-template
1106   |-<
1107   |-UnknownDeclaration
1108   | |-typename
1109   | `-T
1110   |->
1111   `-SimpleDeclaration
1112     |-void
1113     |-SimpleDeclarator
1114     | |-test
1115     | `-ParametersAndQualifiers
1116     |   |-(
1117     |   `-)
1118     `-CompoundStatement
1119       |-{
1120       |-ExpressionStatement
1121       | |-UnknownExpression
1122       | | |-IdExpression
1123       | | | |-NestedNameSpecifier
1124       | | | | |-IdentifierNameSpecifier
1125       | | | | | `-T
1126       | | | | |-::
1127       | | | | |-SimpleTemplateNameSpecifier
1128       | | | | | |-template
1129       | | | | | |-U
1130       | | | | | |-<
1131       | | | | | |-int
1132       | | | | | `->
1133       | | | | `-::
1134       | | | `-UnqualifiedId
1135       | | |   `-f
1136       | | |-(
1137       | | `-)
1138       | `-;
1139       |-ExpressionStatement
1140       | |-UnknownExpression
1141       | | |-IdExpression
1142       | | | |-NestedNameSpecifier
1143       | | | | |-IdentifierNameSpecifier
1144       | | | | | `-T
1145       | | | | |-::
1146       | | | | |-IdentifierNameSpecifier
1147       | | | | | `-U
1148       | | | | `-::
1149       | | | `-UnqualifiedId
1150       | | |   `-f
1151       | | |-(
1152       | | `-)
1153       | `-;
1154       |-ExpressionStatement
1155       | |-UnknownExpression
1156       | | |-IdExpression
1157       | | | |-NestedNameSpecifier
1158       | | | | |-IdentifierNameSpecifier
1159       | | | | | `-T
1160       | | | | `-::
1161       | | | |-template
1162       | | | `-UnqualifiedId
1163       | | |   |-f
1164       | | |   |-<
1165       | | |   |-IntegerLiteralExpression
1166       | | |   | `-0
1167       | | |   `->
1168       | | |-(
1169       | | `-)
1170       | `-;
1171       `-}
1172 )txt"));
1173 }
1174 
1175 TEST_P(SyntaxTreeTest, QualifiedIdDecltype) {
1176   if (!GetParam().isCXX11OrLater()) {
1177     return;
1178   }
1179   EXPECT_TRUE(treeDumpEqual(
1180       R"cpp(
1181 struct S {
1182   static void f(){}
1183 };
1184 void test(S s) {
1185   decltype(s)::   // decltype-specifier
1186       f();
1187 }
1188 )cpp",
1189       R"txt(
1190 *: TranslationUnit
1191 |-SimpleDeclaration
1192 | |-struct
1193 | |-S
1194 | |-{
1195 | |-SimpleDeclaration
1196 | | |-static
1197 | | |-void
1198 | | |-SimpleDeclarator
1199 | | | |-f
1200 | | | `-ParametersAndQualifiers
1201 | | |   |-(
1202 | | |   `-)
1203 | | `-CompoundStatement
1204 | |   |-{
1205 | |   `-}
1206 | |-}
1207 | `-;
1208 `-SimpleDeclaration
1209   |-void
1210   |-SimpleDeclarator
1211   | |-test
1212   | `-ParametersAndQualifiers
1213   |   |-(
1214   |   |-SimpleDeclaration
1215   |   | |-S
1216   |   | `-SimpleDeclarator
1217   |   |   `-s
1218   |   `-)
1219   `-CompoundStatement
1220     |-{
1221     |-ExpressionStatement
1222     | |-UnknownExpression
1223     | | |-IdExpression
1224     | | | |-NestedNameSpecifier
1225     | | | | |-DecltypeNameSpecifier
1226     | | | | | |-decltype
1227     | | | | | |-(
1228     | | | | | |-IdExpression
1229     | | | | | | `-UnqualifiedId
1230     | | | | | |   `-s
1231     | | | | | `-)
1232     | | | | `-::
1233     | | | `-UnqualifiedId
1234     | | |   `-f
1235     | | |-(
1236     | | `-)
1237     | `-;
1238     `-}
1239 )txt"));
1240 }
1241 
1242 TEST_P(SyntaxTreeTest, ParenExpr) {
1243   EXPECT_TRUE(treeDumpEqual(
1244       R"cpp(
1245 void test() {
1246   (1);
1247   ((1));
1248   (1 + (2));
1249 }
1250 )cpp",
1251       R"txt(
1252 *: TranslationUnit
1253 `-SimpleDeclaration
1254   |-void
1255   |-SimpleDeclarator
1256   | |-test
1257   | `-ParametersAndQualifiers
1258   |   |-(
1259   |   `-)
1260   `-CompoundStatement
1261     |-{
1262     |-ExpressionStatement
1263     | |-ParenExpression
1264     | | |-(
1265     | | |-IntegerLiteralExpression
1266     | | | `-1
1267     | | `-)
1268     | `-;
1269     |-ExpressionStatement
1270     | |-ParenExpression
1271     | | |-(
1272     | | |-ParenExpression
1273     | | | |-(
1274     | | | |-IntegerLiteralExpression
1275     | | | | `-1
1276     | | | `-)
1277     | | `-)
1278     | `-;
1279     |-ExpressionStatement
1280     | |-ParenExpression
1281     | | |-(
1282     | | |-BinaryOperatorExpression
1283     | | | |-IntegerLiteralExpression
1284     | | | | `-1
1285     | | | |-+
1286     | | | `-ParenExpression
1287     | | |   |-(
1288     | | |   |-IntegerLiteralExpression
1289     | | |   | `-2
1290     | | |   `-)
1291     | | `-)
1292     | `-;
1293     `-}
1294 )txt"));
1295 }
1296 
1297 TEST_P(SyntaxTreeTest, UserDefinedLiteral) {
1298   if (!GetParam().isCXX11OrLater()) {
1299     return;
1300   }
1301   EXPECT_TRUE(treeDumpEqual(
1302       R"cpp(
1303 typedef decltype(sizeof(void *)) size_t;
1304 
1305 unsigned operator "" _i(unsigned long long);
1306 unsigned operator "" _f(long double);
1307 unsigned operator "" _c(char);
1308 unsigned operator "" _s(const char*, size_t);
1309 unsigned operator "" _r(const char*);
1310 template <char...>
1311 unsigned operator "" _t();
1312 
1313 void test() {
1314   12_i;   // call: operator "" _i(12uLL)      | kind: integer
1315   1.2_f;  // call: operator "" _f(1.2L)       | kind: float
1316   '2'_c;  // call: operator "" _c('2')        | kind: char
1317   "12"_s; // call: operator "" _s("12")       | kind: string
1318 
1319   12_r;   // call: operator "" _r("12")       | kind: integer
1320   1.2_r;  // call: operator "" _i("1.2")      | kind: float
1321   12_t;   // call: operator<'1', '2'> "" _x() | kind: integer
1322   1.2_t;  // call: operator<'1', '2'> "" _x() | kind: float
1323 }
1324     )cpp",
1325       R"txt(
1326 *: TranslationUnit
1327 |-SimpleDeclaration
1328 | |-typedef
1329 | |-decltype
1330 | |-(
1331 | |-UnknownExpression
1332 | | |-sizeof
1333 | | |-(
1334 | | |-void
1335 | | |-*
1336 | | `-)
1337 | |-)
1338 | |-SimpleDeclarator
1339 | | `-size_t
1340 | `-;
1341 |-SimpleDeclaration
1342 | |-unsigned
1343 | |-SimpleDeclarator
1344 | | |-operator
1345 | | |-""
1346 | | |-_i
1347 | | `-ParametersAndQualifiers
1348 | |   |-(
1349 | |   |-SimpleDeclaration
1350 | |   | |-unsigned
1351 | |   | |-long
1352 | |   | `-long
1353 | |   `-)
1354 | `-;
1355 |-SimpleDeclaration
1356 | |-unsigned
1357 | |-SimpleDeclarator
1358 | | |-operator
1359 | | |-""
1360 | | |-_f
1361 | | `-ParametersAndQualifiers
1362 | |   |-(
1363 | |   |-SimpleDeclaration
1364 | |   | |-long
1365 | |   | `-double
1366 | |   `-)
1367 | `-;
1368 |-SimpleDeclaration
1369 | |-unsigned
1370 | |-SimpleDeclarator
1371 | | |-operator
1372 | | |-""
1373 | | |-_c
1374 | | `-ParametersAndQualifiers
1375 | |   |-(
1376 | |   |-SimpleDeclaration
1377 | |   | `-char
1378 | |   `-)
1379 | `-;
1380 |-SimpleDeclaration
1381 | |-unsigned
1382 | |-SimpleDeclarator
1383 | | |-operator
1384 | | |-""
1385 | | |-_s
1386 | | `-ParametersAndQualifiers
1387 | |   |-(
1388 | |   |-SimpleDeclaration
1389 | |   | |-const
1390 | |   | |-char
1391 | |   | `-SimpleDeclarator
1392 | |   |   `-*
1393 | |   |-,
1394 | |   |-SimpleDeclaration
1395 | |   | `-size_t
1396 | |   `-)
1397 | `-;
1398 |-SimpleDeclaration
1399 | |-unsigned
1400 | |-SimpleDeclarator
1401 | | |-operator
1402 | | |-""
1403 | | |-_r
1404 | | `-ParametersAndQualifiers
1405 | |   |-(
1406 | |   |-SimpleDeclaration
1407 | |   | |-const
1408 | |   | |-char
1409 | |   | `-SimpleDeclarator
1410 | |   |   `-*
1411 | |   `-)
1412 | `-;
1413 |-TemplateDeclaration
1414 | |-template
1415 | |-<
1416 | |-SimpleDeclaration
1417 | | `-char
1418 | |-...
1419 | |->
1420 | `-SimpleDeclaration
1421 |   |-unsigned
1422 |   |-SimpleDeclarator
1423 |   | |-operator
1424 |   | |-""
1425 |   | |-_t
1426 |   | `-ParametersAndQualifiers
1427 |   |   |-(
1428 |   |   `-)
1429 |   `-;
1430 `-SimpleDeclaration
1431   |-void
1432   |-SimpleDeclarator
1433   | |-test
1434   | `-ParametersAndQualifiers
1435   |   |-(
1436   |   `-)
1437   `-CompoundStatement
1438     |-{
1439     |-ExpressionStatement
1440     | |-IntegerUserDefinedLiteralExpression
1441     | | `-12_i
1442     | `-;
1443     |-ExpressionStatement
1444     | |-FloatUserDefinedLiteralExpression
1445     | | `-1.2_f
1446     | `-;
1447     |-ExpressionStatement
1448     | |-CharUserDefinedLiteralExpression
1449     | | `-'2'_c
1450     | `-;
1451     |-ExpressionStatement
1452     | |-StringUserDefinedLiteralExpression
1453     | | `-"12"_s
1454     | `-;
1455     |-ExpressionStatement
1456     | |-IntegerUserDefinedLiteralExpression
1457     | | `-12_r
1458     | `-;
1459     |-ExpressionStatement
1460     | |-FloatUserDefinedLiteralExpression
1461     | | `-1.2_r
1462     | `-;
1463     |-ExpressionStatement
1464     | |-IntegerUserDefinedLiteralExpression
1465     | | `-12_t
1466     | `-;
1467     |-ExpressionStatement
1468     | |-FloatUserDefinedLiteralExpression
1469     | | `-1.2_t
1470     | `-;
1471     `-}
1472 )txt"));
1473 }
1474 
1475 TEST_P(SyntaxTreeTest, IntegerLiteralLongLong) {
1476   if (!GetParam().isCXX11OrLater()) {
1477     return;
1478   }
1479   EXPECT_TRUE(treeDumpEqual(
1480       R"cpp(
1481 void test() {
1482   12ll;
1483   12ull;
1484 }
1485 )cpp",
1486       R"txt(
1487 *: TranslationUnit
1488 `-SimpleDeclaration
1489   |-void
1490   |-SimpleDeclarator
1491   | |-test
1492   | `-ParametersAndQualifiers
1493   |   |-(
1494   |   `-)
1495   `-CompoundStatement
1496     |-{
1497     |-ExpressionStatement
1498     | |-IntegerLiteralExpression
1499     | | `-12ll
1500     | `-;
1501     |-ExpressionStatement
1502     | |-IntegerLiteralExpression
1503     | | `-12ull
1504     | `-;
1505     `-}
1506 )txt"));
1507 }
1508 
1509 TEST_P(SyntaxTreeTest, IntegerLiteralBinary) {
1510   if (!GetParam().isCXX14OrLater()) {
1511     return;
1512   }
1513   EXPECT_TRUE(treeDumpEqual(
1514       R"cpp(
1515 void test() {
1516   0b1100;
1517 }
1518 )cpp",
1519       R"txt(
1520 *: TranslationUnit
1521 `-SimpleDeclaration
1522   |-void
1523   |-SimpleDeclarator
1524   | |-test
1525   | `-ParametersAndQualifiers
1526   |   |-(
1527   |   `-)
1528   `-CompoundStatement
1529     |-{
1530     |-ExpressionStatement
1531     | |-IntegerLiteralExpression
1532     | | `-0b1100
1533     | `-;
1534     `-}
1535 )txt"));
1536 }
1537 
1538 TEST_P(SyntaxTreeTest, IntegerLiteralWithDigitSeparators) {
1539   if (!GetParam().isCXX14OrLater()) {
1540     return;
1541   }
1542   EXPECT_TRUE(treeDumpEqual(
1543       R"cpp(
1544 void test() {
1545   1'2'0ull;
1546 }
1547 )cpp",
1548       R"txt(
1549 *: TranslationUnit
1550 `-SimpleDeclaration
1551   |-void
1552   |-SimpleDeclarator
1553   | |-test
1554   | `-ParametersAndQualifiers
1555   |   |-(
1556   |   `-)
1557   `-CompoundStatement
1558     |-{
1559     |-ExpressionStatement
1560     | |-IntegerLiteralExpression
1561     | | `-1'2'0ull
1562     | `-;
1563     `-}
1564 )txt"));
1565 }
1566 
1567 TEST_P(SyntaxTreeTest, CharacterLiteral) {
1568   EXPECT_TRUE(treeDumpEqual(
1569       R"cpp(
1570 void test() {
1571   'a';
1572   '\n';
1573   '\x20';
1574   '\0';
1575   L'a';
1576   L'α';
1577 }
1578 )cpp",
1579       R"txt(
1580 *: TranslationUnit
1581 `-SimpleDeclaration
1582   |-void
1583   |-SimpleDeclarator
1584   | |-test
1585   | `-ParametersAndQualifiers
1586   |   |-(
1587   |   `-)
1588   `-CompoundStatement
1589     |-{
1590     |-ExpressionStatement
1591     | |-CharacterLiteralExpression
1592     | | `-'a'
1593     | `-;
1594     |-ExpressionStatement
1595     | |-CharacterLiteralExpression
1596     | | `-'\n'
1597     | `-;
1598     |-ExpressionStatement
1599     | |-CharacterLiteralExpression
1600     | | `-'\x20'
1601     | `-;
1602     |-ExpressionStatement
1603     | |-CharacterLiteralExpression
1604     | | `-'\0'
1605     | `-;
1606     |-ExpressionStatement
1607     | |-CharacterLiteralExpression
1608     | | `-L'a'
1609     | `-;
1610     |-ExpressionStatement
1611     | |-CharacterLiteralExpression
1612     | | `-L'α'
1613     | `-;
1614     `-}
1615 )txt"));
1616 }
1617 
1618 TEST_P(SyntaxTreeTest, CharacterLiteralUtf) {
1619   if (!GetParam().isCXX11OrLater()) {
1620     return;
1621   }
1622   EXPECT_TRUE(treeDumpEqual(
1623       R"cpp(
1624 void test() {
1625   u'a';
1626   u'構';
1627   U'a';
1628   U'��';
1629 }
1630 )cpp",
1631       R"txt(
1632 *: TranslationUnit
1633 `-SimpleDeclaration
1634   |-void
1635   |-SimpleDeclarator
1636   | |-test
1637   | `-ParametersAndQualifiers
1638   |   |-(
1639   |   `-)
1640   `-CompoundStatement
1641     |-{
1642     |-ExpressionStatement
1643     | |-CharacterLiteralExpression
1644     | | `-u'a'
1645     | `-;
1646     |-ExpressionStatement
1647     | |-CharacterLiteralExpression
1648     | | `-u'構'
1649     | `-;
1650     |-ExpressionStatement
1651     | |-CharacterLiteralExpression
1652     | | `-U'a'
1653     | `-;
1654     |-ExpressionStatement
1655     | |-CharacterLiteralExpression
1656     | | `-U'��'
1657     | `-;
1658     `-}
1659 )txt"));
1660 }
1661 
1662 TEST_P(SyntaxTreeTest, CharacterLiteralUtf8) {
1663   if (!GetParam().isCXX17OrLater()) {
1664     return;
1665   }
1666   EXPECT_TRUE(treeDumpEqual(
1667       R"cpp(
1668 void test() {
1669   u8'a';
1670   u8'\x7f';
1671 }
1672 )cpp",
1673       R"txt(
1674 *: TranslationUnit
1675 `-SimpleDeclaration
1676   |-void
1677   |-SimpleDeclarator
1678   | |-test
1679   | `-ParametersAndQualifiers
1680   |   |-(
1681   |   `-)
1682   `-CompoundStatement
1683     |-{
1684     |-ExpressionStatement
1685     | |-CharacterLiteralExpression
1686     | | `-u8'a'
1687     | `-;
1688     |-ExpressionStatement
1689     | |-CharacterLiteralExpression
1690     | | `-u8'\x7f'
1691     | `-;
1692     `-}
1693 )txt"));
1694 }
1695 
1696 TEST_P(SyntaxTreeTest, FloatingLiteral) {
1697   EXPECT_TRUE(treeDumpEqual(
1698       R"cpp(
1699 void test() {
1700   1e-2;
1701   2.;
1702   .2;
1703   2.f;
1704 }
1705 )cpp",
1706       R"txt(
1707 *: TranslationUnit
1708 `-SimpleDeclaration
1709   |-void
1710   |-SimpleDeclarator
1711   | |-test
1712   | `-ParametersAndQualifiers
1713   |   |-(
1714   |   `-)
1715   `-CompoundStatement
1716     |-{
1717     |-ExpressionStatement
1718     | |-FloatingLiteralExpression
1719     | | `-1e-2
1720     | `-;
1721     |-ExpressionStatement
1722     | |-FloatingLiteralExpression
1723     | | `-2.
1724     | `-;
1725     |-ExpressionStatement
1726     | |-FloatingLiteralExpression
1727     | | `-.2
1728     | `-;
1729     |-ExpressionStatement
1730     | |-FloatingLiteralExpression
1731     | | `-2.f
1732     | `-;
1733     `-}
1734 )txt"));
1735 }
1736 
1737 TEST_P(SyntaxTreeTest, FloatingLiteralHexadecimal) {
1738   if (!GetParam().isCXX17OrLater()) {
1739     return;
1740   }
1741   EXPECT_TRUE(treeDumpEqual(
1742       R"cpp(
1743 void test() {
1744   0xfp1;
1745   0xf.p1;
1746   0x.fp1;
1747   0xf.fp1f;
1748 }
1749 )cpp",
1750       R"txt(
1751 *: TranslationUnit
1752 `-SimpleDeclaration
1753   |-void
1754   |-SimpleDeclarator
1755   | |-test
1756   | `-ParametersAndQualifiers
1757   |   |-(
1758   |   `-)
1759   `-CompoundStatement
1760     |-{
1761     |-ExpressionStatement
1762     | |-FloatingLiteralExpression
1763     | | `-0xfp1
1764     | `-;
1765     |-ExpressionStatement
1766     | |-FloatingLiteralExpression
1767     | | `-0xf.p1
1768     | `-;
1769     |-ExpressionStatement
1770     | |-FloatingLiteralExpression
1771     | | `-0x.fp1
1772     | `-;
1773     |-ExpressionStatement
1774     | |-FloatingLiteralExpression
1775     | | `-0xf.fp1f
1776     | `-;
1777     `-}
1778 )txt"));
1779 }
1780 
1781 TEST_P(SyntaxTreeTest, StringLiteral) {
1782   EXPECT_TRUE(treeDumpEqual(
1783       R"cpp(
1784 void test() {
1785   "a\n\0\x20";
1786   L"αβ";
1787 }
1788 )cpp",
1789       R"txt(
1790 *: TranslationUnit
1791 `-SimpleDeclaration
1792   |-void
1793   |-SimpleDeclarator
1794   | |-test
1795   | `-ParametersAndQualifiers
1796   |   |-(
1797   |   `-)
1798   `-CompoundStatement
1799     |-{
1800     |-ExpressionStatement
1801     | |-StringLiteralExpression
1802     | | `-"a\n\0\x20"
1803     | `-;
1804     |-ExpressionStatement
1805     | |-StringLiteralExpression
1806     | | `-L"αβ"
1807     | `-;
1808     `-}
1809 )txt"));
1810 }
1811 
1812 TEST_P(SyntaxTreeTest, StringLiteralUtf) {
1813   if (!GetParam().isCXX11OrLater()) {
1814     return;
1815   }
1816   EXPECT_TRUE(treeDumpEqual(
1817       R"cpp(
1818 void test() {
1819   u8"a\x1f\x05";
1820   u"C++抽象構文木";
1821   U"����\n";
1822 }
1823 )cpp",
1824       R"txt(
1825 *: TranslationUnit
1826 `-SimpleDeclaration
1827   |-void
1828   |-SimpleDeclarator
1829   | |-test
1830   | `-ParametersAndQualifiers
1831   |   |-(
1832   |   `-)
1833   `-CompoundStatement
1834     |-{
1835     |-ExpressionStatement
1836     | |-StringLiteralExpression
1837     | | `-u8"a\x1f\x05"
1838     | `-;
1839     |-ExpressionStatement
1840     | |-StringLiteralExpression
1841     | | `-u"C++抽象構文木"
1842     | `-;
1843     |-ExpressionStatement
1844     | |-StringLiteralExpression
1845     | | `-U"����\n"
1846     | `-;
1847     `-}
1848 )txt"));
1849 }
1850 
1851 TEST_P(SyntaxTreeTest, StringLiteralRaw) {
1852   if (!GetParam().isCXX11OrLater()) {
1853     return;
1854   }
1855   // This test uses regular string literals instead of raw string literals to
1856   // hold source code and expected output because of a bug in MSVC up to MSVC
1857   // 2019 16.2:
1858   // https://developercommunity.visualstudio.com/content/problem/67300/stringifying-raw-string-literal.html
1859   EXPECT_TRUE(treeDumpEqual( //
1860       "void test() {\n"
1861       "  R\"SyntaxTree(\n"
1862       "  Hello \"Syntax\" \\\"\n"
1863       "  )SyntaxTree\";\n"
1864       "}\n",
1865       "*: TranslationUnit\n"
1866       "`-SimpleDeclaration\n"
1867       "  |-void\n"
1868       "  |-SimpleDeclarator\n"
1869       "  | |-test\n"
1870       "  | `-ParametersAndQualifiers\n"
1871       "  |   |-(\n"
1872       "  |   `-)\n"
1873       "  `-CompoundStatement\n"
1874       "    |-{\n"
1875       "    |-ExpressionStatement\n"
1876       "    | |-StringLiteralExpression\n"
1877       "    | | `-R\"SyntaxTree(\n"
1878       "  Hello \"Syntax\" \\\"\n"
1879       "  )SyntaxTree\"\n"
1880       "    | `-;\n"
1881       "    `-}\n"));
1882 }
1883 
1884 TEST_P(SyntaxTreeTest, BoolLiteral) {
1885   if (GetParam().isC()) {
1886     return;
1887   }
1888   EXPECT_TRUE(treeDumpEqual(
1889       R"cpp(
1890 void test() {
1891   true;
1892   false;
1893 }
1894 )cpp",
1895       R"txt(
1896 *: TranslationUnit
1897 `-SimpleDeclaration
1898   |-void
1899   |-SimpleDeclarator
1900   | |-test
1901   | `-ParametersAndQualifiers
1902   |   |-(
1903   |   `-)
1904   `-CompoundStatement
1905     |-{
1906     |-ExpressionStatement
1907     | |-BoolLiteralExpression
1908     | | `-true
1909     | `-;
1910     |-ExpressionStatement
1911     | |-BoolLiteralExpression
1912     | | `-false
1913     | `-;
1914     `-}
1915 )txt"));
1916 }
1917 
1918 TEST_P(SyntaxTreeTest, CxxNullPtrLiteral) {
1919   if (!GetParam().isCXX11OrLater()) {
1920     return;
1921   }
1922   EXPECT_TRUE(treeDumpEqual(
1923       R"cpp(
1924 void test() {
1925   nullptr;
1926 }
1927 )cpp",
1928       R"txt(
1929 *: TranslationUnit
1930 `-SimpleDeclaration
1931   |-void
1932   |-SimpleDeclarator
1933   | |-test
1934   | `-ParametersAndQualifiers
1935   |   |-(
1936   |   `-)
1937   `-CompoundStatement
1938     |-{
1939     |-ExpressionStatement
1940     | |-CxxNullPtrExpression
1941     | | `-nullptr
1942     | `-;
1943     `-}
1944 )txt"));
1945 }
1946 
1947 TEST_P(SyntaxTreeTest, PostfixUnaryOperator) {
1948   EXPECT_TRUE(treeDumpEqual(
1949       R"cpp(
1950 void test(int a) {
1951   a++;
1952   a--;
1953 }
1954 )cpp",
1955       R"txt(
1956 *: TranslationUnit
1957 `-SimpleDeclaration
1958   |-void
1959   |-SimpleDeclarator
1960   | |-test
1961   | `-ParametersAndQualifiers
1962   |   |-(
1963   |   |-SimpleDeclaration
1964   |   | |-int
1965   |   | `-SimpleDeclarator
1966   |   |   `-a
1967   |   `-)
1968   `-CompoundStatement
1969     |-{
1970     |-ExpressionStatement
1971     | |-PostfixUnaryOperatorExpression
1972     | | |-IdExpression
1973     | | | `-UnqualifiedId
1974     | | |   `-a
1975     | | `-++
1976     | `-;
1977     |-ExpressionStatement
1978     | |-PostfixUnaryOperatorExpression
1979     | | |-IdExpression
1980     | | | `-UnqualifiedId
1981     | | |   `-a
1982     | | `---
1983     | `-;
1984     `-}
1985 )txt"));
1986 }
1987 
1988 TEST_P(SyntaxTreeTest, PrefixUnaryOperator) {
1989   EXPECT_TRUE(treeDumpEqual(
1990       R"cpp(
1991 void test(int a, int *ap) {
1992   --a; ++a;
1993   ~a;
1994   -a;
1995   +a;
1996   &a;
1997   *ap;
1998   !a;
1999   __real a; __imag a;
2000 }
2001 )cpp",
2002       R"txt(
2003 *: TranslationUnit
2004 `-SimpleDeclaration
2005   |-void
2006   |-SimpleDeclarator
2007   | |-test
2008   | `-ParametersAndQualifiers
2009   |   |-(
2010   |   |-SimpleDeclaration
2011   |   | |-int
2012   |   | `-SimpleDeclarator
2013   |   |   `-a
2014   |   |-,
2015   |   |-SimpleDeclaration
2016   |   | |-int
2017   |   | `-SimpleDeclarator
2018   |   |   |-*
2019   |   |   `-ap
2020   |   `-)
2021   `-CompoundStatement
2022     |-{
2023     |-ExpressionStatement
2024     | |-PrefixUnaryOperatorExpression
2025     | | |---
2026     | | `-IdExpression
2027     | |   `-UnqualifiedId
2028     | |     `-a
2029     | `-;
2030     |-ExpressionStatement
2031     | |-PrefixUnaryOperatorExpression
2032     | | |-++
2033     | | `-IdExpression
2034     | |   `-UnqualifiedId
2035     | |     `-a
2036     | `-;
2037     |-ExpressionStatement
2038     | |-PrefixUnaryOperatorExpression
2039     | | |-~
2040     | | `-IdExpression
2041     | |   `-UnqualifiedId
2042     | |     `-a
2043     | `-;
2044     |-ExpressionStatement
2045     | |-PrefixUnaryOperatorExpression
2046     | | |--
2047     | | `-IdExpression
2048     | |   `-UnqualifiedId
2049     | |     `-a
2050     | `-;
2051     |-ExpressionStatement
2052     | |-PrefixUnaryOperatorExpression
2053     | | |-+
2054     | | `-IdExpression
2055     | |   `-UnqualifiedId
2056     | |     `-a
2057     | `-;
2058     |-ExpressionStatement
2059     | |-PrefixUnaryOperatorExpression
2060     | | |-&
2061     | | `-IdExpression
2062     | |   `-UnqualifiedId
2063     | |     `-a
2064     | `-;
2065     |-ExpressionStatement
2066     | |-PrefixUnaryOperatorExpression
2067     | | |-*
2068     | | `-IdExpression
2069     | |   `-UnqualifiedId
2070     | |     `-ap
2071     | `-;
2072     |-ExpressionStatement
2073     | |-PrefixUnaryOperatorExpression
2074     | | |-!
2075     | | `-IdExpression
2076     | |   `-UnqualifiedId
2077     | |     `-a
2078     | `-;
2079     |-ExpressionStatement
2080     | |-PrefixUnaryOperatorExpression
2081     | | |-__real
2082     | | `-IdExpression
2083     | |   `-UnqualifiedId
2084     | |     `-a
2085     | `-;
2086     |-ExpressionStatement
2087     | |-PrefixUnaryOperatorExpression
2088     | | |-__imag
2089     | | `-IdExpression
2090     | |   `-UnqualifiedId
2091     | |     `-a
2092     | `-;
2093     `-}
2094 )txt"));
2095 }
2096 
2097 TEST_P(SyntaxTreeTest, PrefixUnaryOperatorCxx) {
2098   if (!GetParam().isCXX()) {
2099     return;
2100   }
2101   EXPECT_TRUE(treeDumpEqual(
2102       R"cpp(
2103 void test(int a, bool b) {
2104   compl a;
2105   not b;
2106 }
2107 )cpp",
2108       R"txt(
2109 *: TranslationUnit
2110 `-SimpleDeclaration
2111   |-void
2112   |-SimpleDeclarator
2113   | |-test
2114   | `-ParametersAndQualifiers
2115   |   |-(
2116   |   |-SimpleDeclaration
2117   |   | |-int
2118   |   | `-SimpleDeclarator
2119   |   |   `-a
2120   |   |-,
2121   |   |-SimpleDeclaration
2122   |   | |-bool
2123   |   | `-SimpleDeclarator
2124   |   |   `-b
2125   |   `-)
2126   `-CompoundStatement
2127     |-{
2128     |-ExpressionStatement
2129     | |-PrefixUnaryOperatorExpression
2130     | | |-compl
2131     | | `-IdExpression
2132     | |   `-UnqualifiedId
2133     | |     `-a
2134     | `-;
2135     |-ExpressionStatement
2136     | |-PrefixUnaryOperatorExpression
2137     | | |-not
2138     | | `-IdExpression
2139     | |   `-UnqualifiedId
2140     | |     `-b
2141     | `-;
2142     `-}
2143 )txt"));
2144 }
2145 
2146 TEST_P(SyntaxTreeTest, BinaryOperator) {
2147   EXPECT_TRUE(treeDumpEqual(
2148       R"cpp(
2149 void test(int a) {
2150   1 - 2;
2151   1 == 2;
2152   a = 1;
2153   a <<= 1;
2154   1 || 0;
2155   1 & 2;
2156   a ^= 3;
2157 }
2158 )cpp",
2159       R"txt(
2160 *: TranslationUnit
2161 `-SimpleDeclaration
2162   |-void
2163   |-SimpleDeclarator
2164   | |-test
2165   | `-ParametersAndQualifiers
2166   |   |-(
2167   |   |-SimpleDeclaration
2168   |   | |-int
2169   |   | `-SimpleDeclarator
2170   |   |   `-a
2171   |   `-)
2172   `-CompoundStatement
2173     |-{
2174     |-ExpressionStatement
2175     | |-BinaryOperatorExpression
2176     | | |-IntegerLiteralExpression
2177     | | | `-1
2178     | | |--
2179     | | `-IntegerLiteralExpression
2180     | |   `-2
2181     | `-;
2182     |-ExpressionStatement
2183     | |-BinaryOperatorExpression
2184     | | |-IntegerLiteralExpression
2185     | | | `-1
2186     | | |-==
2187     | | `-IntegerLiteralExpression
2188     | |   `-2
2189     | `-;
2190     |-ExpressionStatement
2191     | |-BinaryOperatorExpression
2192     | | |-IdExpression
2193     | | | `-UnqualifiedId
2194     | | |   `-a
2195     | | |-=
2196     | | `-IntegerLiteralExpression
2197     | |   `-1
2198     | `-;
2199     |-ExpressionStatement
2200     | |-BinaryOperatorExpression
2201     | | |-IdExpression
2202     | | | `-UnqualifiedId
2203     | | |   `-a
2204     | | |-<<=
2205     | | `-IntegerLiteralExpression
2206     | |   `-1
2207     | `-;
2208     |-ExpressionStatement
2209     | |-BinaryOperatorExpression
2210     | | |-IntegerLiteralExpression
2211     | | | `-1
2212     | | |-||
2213     | | `-IntegerLiteralExpression
2214     | |   `-0
2215     | `-;
2216     |-ExpressionStatement
2217     | |-BinaryOperatorExpression
2218     | | |-IntegerLiteralExpression
2219     | | | `-1
2220     | | |-&
2221     | | `-IntegerLiteralExpression
2222     | |   `-2
2223     | `-;
2224     |-ExpressionStatement
2225     | |-BinaryOperatorExpression
2226     | | |-IdExpression
2227     | | | `-UnqualifiedId
2228     | | |   `-a
2229     | | |-^=
2230     | | `-IntegerLiteralExpression
2231     | |   `-3
2232     | `-;
2233     `-}
2234 )txt"));
2235 }
2236 
2237 TEST_P(SyntaxTreeTest, BinaryOperatorCxx) {
2238   if (!GetParam().isCXX()) {
2239     return;
2240   }
2241   EXPECT_TRUE(treeDumpEqual(
2242       R"cpp(
2243 void test(int a) {
2244   true || false;
2245   true or false;
2246   1 bitand 2;
2247   a xor_eq 3;
2248 }
2249 )cpp",
2250       R"txt(
2251 *: TranslationUnit
2252 `-SimpleDeclaration
2253   |-void
2254   |-SimpleDeclarator
2255   | |-test
2256   | `-ParametersAndQualifiers
2257   |   |-(
2258   |   |-SimpleDeclaration
2259   |   | |-int
2260   |   | `-SimpleDeclarator
2261   |   |   `-a
2262   |   `-)
2263   `-CompoundStatement
2264     |-{
2265     |-ExpressionStatement
2266     | |-BinaryOperatorExpression
2267     | | |-BoolLiteralExpression
2268     | | | `-true
2269     | | |-||
2270     | | `-BoolLiteralExpression
2271     | |   `-false
2272     | `-;
2273     |-ExpressionStatement
2274     | |-BinaryOperatorExpression
2275     | | |-BoolLiteralExpression
2276     | | | `-true
2277     | | |-or
2278     | | `-BoolLiteralExpression
2279     | |   `-false
2280     | `-;
2281     |-ExpressionStatement
2282     | |-BinaryOperatorExpression
2283     | | |-IntegerLiteralExpression
2284     | | | `-1
2285     | | |-bitand
2286     | | `-IntegerLiteralExpression
2287     | |   `-2
2288     | `-;
2289     |-ExpressionStatement
2290     | |-BinaryOperatorExpression
2291     | | |-IdExpression
2292     | | | `-UnqualifiedId
2293     | | |   `-a
2294     | | |-xor_eq
2295     | | `-IntegerLiteralExpression
2296     | |   `-3
2297     | `-;
2298     `-}
2299 )txt"));
2300 }
2301 
2302 TEST_P(SyntaxTreeTest, NestedBinaryOperator) {
2303   EXPECT_TRUE(treeDumpEqual(
2304       R"cpp(
2305 void test(int a, int b) {
2306   (1 + 2) * (4 / 2);
2307   a + b + 42;
2308   a = b = 42;
2309   a + b * 4 + 2;
2310   a % 2 + b * 42;
2311 }
2312 )cpp",
2313       R"txt(
2314 *: TranslationUnit
2315 `-SimpleDeclaration
2316   |-void
2317   |-SimpleDeclarator
2318   | |-test
2319   | `-ParametersAndQualifiers
2320   |   |-(
2321   |   |-SimpleDeclaration
2322   |   | |-int
2323   |   | `-SimpleDeclarator
2324   |   |   `-a
2325   |   |-,
2326   |   |-SimpleDeclaration
2327   |   | |-int
2328   |   | `-SimpleDeclarator
2329   |   |   `-b
2330   |   `-)
2331   `-CompoundStatement
2332     |-{
2333     |-ExpressionStatement
2334     | |-BinaryOperatorExpression
2335     | | |-ParenExpression
2336     | | | |-(
2337     | | | |-BinaryOperatorExpression
2338     | | | | |-IntegerLiteralExpression
2339     | | | | | `-1
2340     | | | | |-+
2341     | | | | `-IntegerLiteralExpression
2342     | | | |   `-2
2343     | | | `-)
2344     | | |-*
2345     | | `-ParenExpression
2346     | |   |-(
2347     | |   |-BinaryOperatorExpression
2348     | |   | |-IntegerLiteralExpression
2349     | |   | | `-4
2350     | |   | |-/
2351     | |   | `-IntegerLiteralExpression
2352     | |   |   `-2
2353     | |   `-)
2354     | `-;
2355     |-ExpressionStatement
2356     | |-BinaryOperatorExpression
2357     | | |-BinaryOperatorExpression
2358     | | | |-IdExpression
2359     | | | | `-UnqualifiedId
2360     | | | |   `-a
2361     | | | |-+
2362     | | | `-IdExpression
2363     | | |   `-UnqualifiedId
2364     | | |     `-b
2365     | | |-+
2366     | | `-IntegerLiteralExpression
2367     | |   `-42
2368     | `-;
2369     |-ExpressionStatement
2370     | |-BinaryOperatorExpression
2371     | | |-IdExpression
2372     | | | `-UnqualifiedId
2373     | | |   `-a
2374     | | |-=
2375     | | `-BinaryOperatorExpression
2376     | |   |-IdExpression
2377     | |   | `-UnqualifiedId
2378     | |   |   `-b
2379     | |   |-=
2380     | |   `-IntegerLiteralExpression
2381     | |     `-42
2382     | `-;
2383     |-ExpressionStatement
2384     | |-BinaryOperatorExpression
2385     | | |-BinaryOperatorExpression
2386     | | | |-IdExpression
2387     | | | | `-UnqualifiedId
2388     | | | |   `-a
2389     | | | |-+
2390     | | | `-BinaryOperatorExpression
2391     | | |   |-IdExpression
2392     | | |   | `-UnqualifiedId
2393     | | |   |   `-b
2394     | | |   |-*
2395     | | |   `-IntegerLiteralExpression
2396     | | |     `-4
2397     | | |-+
2398     | | `-IntegerLiteralExpression
2399     | |   `-2
2400     | `-;
2401     |-ExpressionStatement
2402     | |-BinaryOperatorExpression
2403     | | |-BinaryOperatorExpression
2404     | | | |-IdExpression
2405     | | | | `-UnqualifiedId
2406     | | | |   `-a
2407     | | | |-%
2408     | | | `-IntegerLiteralExpression
2409     | | |   `-2
2410     | | |-+
2411     | | `-BinaryOperatorExpression
2412     | |   |-IdExpression
2413     | |   | `-UnqualifiedId
2414     | |   |   `-b
2415     | |   |-*
2416     | |   `-IntegerLiteralExpression
2417     | |     `-42
2418     | `-;
2419     `-}
2420 )txt"));
2421 }
2422 
2423 TEST_P(SyntaxTreeTest, UserDefinedBinaryOperator) {
2424   if (!GetParam().isCXX()) {
2425     return;
2426   }
2427   EXPECT_TRUE(treeDumpEqual(
2428       R"cpp(
2429 struct X {
2430   X& operator=(const X&);
2431   friend X operator+(X, const X&);
2432   friend bool operator<(const X&, const X&);
2433   friend X operator<<(X&, const X&);
2434   X operator,(X&);
2435   X operator->*(int);
2436   // TODO: Unbox operators in syntax tree.
2437   // Represent operators by `+` instead of `IdExpression-UnqualifiedId-+`
2438 };
2439 void test(X x, X y, X* xp, int X::* pmi) {
2440   x = y;
2441   x + y;
2442   x < y;
2443   x << y;
2444   x, y;
2445   xp->*pmi;
2446 }
2447 )cpp",
2448       R"txt(
2449 *: TranslationUnit
2450 |-SimpleDeclaration
2451 | |-struct
2452 | |-X
2453 | |-{
2454 | |-SimpleDeclaration
2455 | | |-X
2456 | | |-SimpleDeclarator
2457 | | | |-&
2458 | | | |-operator
2459 | | | |-=
2460 | | | `-ParametersAndQualifiers
2461 | | |   |-(
2462 | | |   |-SimpleDeclaration
2463 | | |   | |-const
2464 | | |   | |-X
2465 | | |   | `-SimpleDeclarator
2466 | | |   |   `-&
2467 | | |   `-)
2468 | | `-;
2469 | |-UnknownDeclaration
2470 | | `-SimpleDeclaration
2471 | |   |-friend
2472 | |   |-X
2473 | |   |-SimpleDeclarator
2474 | |   | |-operator
2475 | |   | |-+
2476 | |   | `-ParametersAndQualifiers
2477 | |   |   |-(
2478 | |   |   |-SimpleDeclaration
2479 | |   |   | `-X
2480 | |   |   |-,
2481 | |   |   |-SimpleDeclaration
2482 | |   |   | |-const
2483 | |   |   | |-X
2484 | |   |   | `-SimpleDeclarator
2485 | |   |   |   `-&
2486 | |   |   `-)
2487 | |   `-;
2488 | |-UnknownDeclaration
2489 | | `-SimpleDeclaration
2490 | |   |-friend
2491 | |   |-bool
2492 | |   |-SimpleDeclarator
2493 | |   | |-operator
2494 | |   | |-<
2495 | |   | `-ParametersAndQualifiers
2496 | |   |   |-(
2497 | |   |   |-SimpleDeclaration
2498 | |   |   | |-const
2499 | |   |   | |-X
2500 | |   |   | `-SimpleDeclarator
2501 | |   |   |   `-&
2502 | |   |   |-,
2503 | |   |   |-SimpleDeclaration
2504 | |   |   | |-const
2505 | |   |   | |-X
2506 | |   |   | `-SimpleDeclarator
2507 | |   |   |   `-&
2508 | |   |   `-)
2509 | |   `-;
2510 | |-UnknownDeclaration
2511 | | `-SimpleDeclaration
2512 | |   |-friend
2513 | |   |-X
2514 | |   |-SimpleDeclarator
2515 | |   | |-operator
2516 | |   | |-<<
2517 | |   | `-ParametersAndQualifiers
2518 | |   |   |-(
2519 | |   |   |-SimpleDeclaration
2520 | |   |   | |-X
2521 | |   |   | `-SimpleDeclarator
2522 | |   |   |   `-&
2523 | |   |   |-,
2524 | |   |   |-SimpleDeclaration
2525 | |   |   | |-const
2526 | |   |   | |-X
2527 | |   |   | `-SimpleDeclarator
2528 | |   |   |   `-&
2529 | |   |   `-)
2530 | |   `-;
2531 | |-SimpleDeclaration
2532 | | |-X
2533 | | |-SimpleDeclarator
2534 | | | |-operator
2535 | | | |-,
2536 | | | `-ParametersAndQualifiers
2537 | | |   |-(
2538 | | |   |-SimpleDeclaration
2539 | | |   | |-X
2540 | | |   | `-SimpleDeclarator
2541 | | |   |   `-&
2542 | | |   `-)
2543 | | `-;
2544 | |-SimpleDeclaration
2545 | | |-X
2546 | | |-SimpleDeclarator
2547 | | | |-operator
2548 | | | |-->*
2549 | | | `-ParametersAndQualifiers
2550 | | |   |-(
2551 | | |   |-SimpleDeclaration
2552 | | |   | `-int
2553 | | |   `-)
2554 | | `-;
2555 | |-}
2556 | `-;
2557 `-SimpleDeclaration
2558   |-void
2559   |-SimpleDeclarator
2560   | |-test
2561   | `-ParametersAndQualifiers
2562   |   |-(
2563   |   |-SimpleDeclaration
2564   |   | |-X
2565   |   | `-SimpleDeclarator
2566   |   |   `-x
2567   |   |-,
2568   |   |-SimpleDeclaration
2569   |   | |-X
2570   |   | `-SimpleDeclarator
2571   |   |   `-y
2572   |   |-,
2573   |   |-SimpleDeclaration
2574   |   | |-X
2575   |   | `-SimpleDeclarator
2576   |   |   |-*
2577   |   |   `-xp
2578   |   |-,
2579   |   |-SimpleDeclaration
2580   |   | |-int
2581   |   | `-SimpleDeclarator
2582   |   |   |-MemberPointer
2583   |   |   | |-X
2584   |   |   | |-::
2585   |   |   | `-*
2586   |   |   `-pmi
2587   |   `-)
2588   `-CompoundStatement
2589     |-{
2590     |-ExpressionStatement
2591     | |-BinaryOperatorExpression
2592     | | |-IdExpression
2593     | | | `-UnqualifiedId
2594     | | |   `-x
2595     | | |-IdExpression
2596     | | | `-UnqualifiedId
2597     | | |   `-=
2598     | | `-IdExpression
2599     | |   `-UnqualifiedId
2600     | |     `-y
2601     | `-;
2602     |-ExpressionStatement
2603     | |-BinaryOperatorExpression
2604     | | |-UnknownExpression
2605     | | | `-IdExpression
2606     | | |   `-UnqualifiedId
2607     | | |     `-x
2608     | | |-IdExpression
2609     | | | `-UnqualifiedId
2610     | | |   `-+
2611     | | `-IdExpression
2612     | |   `-UnqualifiedId
2613     | |     `-y
2614     | `-;
2615     |-ExpressionStatement
2616     | |-BinaryOperatorExpression
2617     | | |-IdExpression
2618     | | | `-UnqualifiedId
2619     | | |   `-x
2620     | | |-IdExpression
2621     | | | `-UnqualifiedId
2622     | | |   `-<
2623     | | `-IdExpression
2624     | |   `-UnqualifiedId
2625     | |     `-y
2626     | `-;
2627     |-ExpressionStatement
2628     | |-BinaryOperatorExpression
2629     | | |-IdExpression
2630     | | | `-UnqualifiedId
2631     | | |   `-x
2632     | | |-IdExpression
2633     | | | `-UnqualifiedId
2634     | | |   `-<<
2635     | | `-IdExpression
2636     | |   `-UnqualifiedId
2637     | |     `-y
2638     | `-;
2639     |-ExpressionStatement
2640     | |-BinaryOperatorExpression
2641     | | |-IdExpression
2642     | | | `-UnqualifiedId
2643     | | |   `-x
2644     | | |-IdExpression
2645     | | | `-UnqualifiedId
2646     | | |   `-,
2647     | | `-IdExpression
2648     | |   `-UnqualifiedId
2649     | |     `-y
2650     | `-;
2651     |-ExpressionStatement
2652     | |-BinaryOperatorExpression
2653     | | |-IdExpression
2654     | | | `-UnqualifiedId
2655     | | |   `-xp
2656     | | |-->*
2657     | | `-IdExpression
2658     | |   `-UnqualifiedId
2659     | |     `-pmi
2660     | `-;
2661     `-}
2662 )txt"));
2663 }
2664 
2665 TEST_P(SyntaxTreeTest, UserDefinedUnaryPrefixOperator) {
2666   if (!GetParam().isCXX()) {
2667     return;
2668   }
2669   EXPECT_TRUE(treeDumpEqual(
2670       R"cpp(
2671 struct X {
2672   X operator++();
2673   bool operator!();
2674   X* operator&();
2675 };
2676 void test(X x) {
2677   ++x;
2678   !x;
2679   &x;
2680 }
2681 )cpp",
2682       R"txt(
2683 *: TranslationUnit
2684 |-SimpleDeclaration
2685 | |-struct
2686 | |-X
2687 | |-{
2688 | |-SimpleDeclaration
2689 | | |-X
2690 | | |-SimpleDeclarator
2691 | | | |-operator
2692 | | | |-++
2693 | | | `-ParametersAndQualifiers
2694 | | |   |-(
2695 | | |   `-)
2696 | | `-;
2697 | |-SimpleDeclaration
2698 | | |-bool
2699 | | |-SimpleDeclarator
2700 | | | |-operator
2701 | | | |-!
2702 | | | `-ParametersAndQualifiers
2703 | | |   |-(
2704 | | |   `-)
2705 | | `-;
2706 | |-SimpleDeclaration
2707 | | |-X
2708 | | |-SimpleDeclarator
2709 | | | |-*
2710 | | | |-operator
2711 | | | |-&
2712 | | | `-ParametersAndQualifiers
2713 | | |   |-(
2714 | | |   `-)
2715 | | `-;
2716 | |-}
2717 | `-;
2718 `-SimpleDeclaration
2719   |-void
2720   |-SimpleDeclarator
2721   | |-test
2722   | `-ParametersAndQualifiers
2723   |   |-(
2724   |   |-SimpleDeclaration
2725   |   | |-X
2726   |   | `-SimpleDeclarator
2727   |   |   `-x
2728   |   `-)
2729   `-CompoundStatement
2730     |-{
2731     |-ExpressionStatement
2732     | |-PrefixUnaryOperatorExpression
2733     | | |-IdExpression
2734     | | | `-UnqualifiedId
2735     | | |   `-++
2736     | | `-IdExpression
2737     | |   `-UnqualifiedId
2738     | |     `-x
2739     | `-;
2740     |-ExpressionStatement
2741     | |-PrefixUnaryOperatorExpression
2742     | | |-IdExpression
2743     | | | `-UnqualifiedId
2744     | | |   `-!
2745     | | `-IdExpression
2746     | |   `-UnqualifiedId
2747     | |     `-x
2748     | `-;
2749     |-ExpressionStatement
2750     | |-PrefixUnaryOperatorExpression
2751     | | |-IdExpression
2752     | | | `-UnqualifiedId
2753     | | |   `-&
2754     | | `-IdExpression
2755     | |   `-UnqualifiedId
2756     | |     `-x
2757     | `-;
2758     `-}
2759 )txt"));
2760 }
2761 
2762 TEST_P(SyntaxTreeTest, UserDefinedUnaryPostfixOperator) {
2763   if (!GetParam().isCXX()) {
2764     return;
2765   }
2766   EXPECT_TRUE(treeDumpEqual(
2767       R"cpp(
2768 struct X {
2769   X operator++(int);
2770 };
2771 void test(X x) {
2772   x++;
2773 }
2774 )cpp",
2775       R"txt(
2776 *: TranslationUnit
2777 |-SimpleDeclaration
2778 | |-struct
2779 | |-X
2780 | |-{
2781 | |-SimpleDeclaration
2782 | | |-X
2783 | | |-SimpleDeclarator
2784 | | | |-operator
2785 | | | |-++
2786 | | | `-ParametersAndQualifiers
2787 | | |   |-(
2788 | | |   |-SimpleDeclaration
2789 | | |   | `-int
2790 | | |   `-)
2791 | | `-;
2792 | |-}
2793 | `-;
2794 `-SimpleDeclaration
2795   |-void
2796   |-SimpleDeclarator
2797   | |-test
2798   | `-ParametersAndQualifiers
2799   |   |-(
2800   |   |-SimpleDeclaration
2801   |   | |-X
2802   |   | `-SimpleDeclarator
2803   |   |   `-x
2804   |   `-)
2805   `-CompoundStatement
2806     |-{
2807     |-ExpressionStatement
2808     | |-PostfixUnaryOperatorExpression
2809     | | |-IdExpression
2810     | | | `-UnqualifiedId
2811     | | |   `-x
2812     | | `-IdExpression
2813     | |   `-UnqualifiedId
2814     | |     `-++
2815     | `-;
2816     `-}
2817 )txt"));
2818 }
2819 
2820 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
2821   EXPECT_TRUE(treeDumpEqual(
2822       R"cpp(
2823 int *a, b;
2824 int *c, d;
2825 )cpp",
2826       R"txt(
2827 *: TranslationUnit
2828 |-SimpleDeclaration
2829 | |-int
2830 | |-SimpleDeclarator
2831 | | |-*
2832 | | `-a
2833 | |-,
2834 | |-SimpleDeclarator
2835 | | `-b
2836 | `-;
2837 `-SimpleDeclaration
2838   |-int
2839   |-SimpleDeclarator
2840   | |-*
2841   | `-c
2842   |-,
2843   |-SimpleDeclarator
2844   | `-d
2845   `-;
2846 )txt"));
2847 }
2848 
2849 TEST_P(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
2850   EXPECT_TRUE(treeDumpEqual(
2851       R"cpp(
2852 typedef int *a, b;
2853 )cpp",
2854       R"txt(
2855 *: TranslationUnit
2856 `-SimpleDeclaration
2857   |-typedef
2858   |-int
2859   |-SimpleDeclarator
2860   | |-*
2861   | `-a
2862   |-,
2863   |-SimpleDeclarator
2864   | `-b
2865   `-;
2866 )txt"));
2867 }
2868 
2869 TEST_P(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
2870   EXPECT_TRUE(treeDumpEqual(
2871       R"cpp(
2872 void foo() {
2873   int *a, b;
2874   typedef int *ta, tb;
2875 }
2876 )cpp",
2877       R"txt(
2878 *: TranslationUnit
2879 `-SimpleDeclaration
2880   |-void
2881   |-SimpleDeclarator
2882   | |-foo
2883   | `-ParametersAndQualifiers
2884   |   |-(
2885   |   `-)
2886   `-CompoundStatement
2887     |-{
2888     |-DeclarationStatement
2889     | |-SimpleDeclaration
2890     | | |-int
2891     | | |-SimpleDeclarator
2892     | | | |-*
2893     | | | `-a
2894     | | |-,
2895     | | `-SimpleDeclarator
2896     | |   `-b
2897     | `-;
2898     |-DeclarationStatement
2899     | |-SimpleDeclaration
2900     | | |-typedef
2901     | | |-int
2902     | | |-SimpleDeclarator
2903     | | | |-*
2904     | | | `-ta
2905     | | |-,
2906     | | `-SimpleDeclarator
2907     | |   `-tb
2908     | `-;
2909     `-}
2910 )txt"));
2911 }
2912 
2913 TEST_P(SyntaxTreeTest, Namespaces) {
2914   if (!GetParam().isCXX()) {
2915     return;
2916   }
2917   EXPECT_TRUE(treeDumpEqual(
2918       R"cpp(
2919 namespace a { namespace b {} }
2920 namespace a::b {}
2921 namespace {}
2922 
2923 namespace foo = a;
2924 )cpp",
2925       R"txt(
2926 *: TranslationUnit
2927 |-NamespaceDefinition
2928 | |-namespace
2929 | |-a
2930 | |-{
2931 | |-NamespaceDefinition
2932 | | |-namespace
2933 | | |-b
2934 | | |-{
2935 | | `-}
2936 | `-}
2937 |-NamespaceDefinition
2938 | |-namespace
2939 | |-a
2940 | |-::
2941 | |-b
2942 | |-{
2943 | `-}
2944 |-NamespaceDefinition
2945 | |-namespace
2946 | |-{
2947 | `-}
2948 `-NamespaceAliasDefinition
2949   |-namespace
2950   |-foo
2951   |-=
2952   |-a
2953   `-;
2954 )txt"));
2955 }
2956 
2957 TEST_P(SyntaxTreeTest, UsingDirective) {
2958   if (!GetParam().isCXX()) {
2959     return;
2960   }
2961   EXPECT_TRUE(treeDumpEqual(
2962       R"cpp(
2963 namespace ns {}
2964 using namespace ::ns;
2965 )cpp",
2966       R"txt(
2967 *: TranslationUnit
2968 |-NamespaceDefinition
2969 | |-namespace
2970 | |-ns
2971 | |-{
2972 | `-}
2973 `-UsingNamespaceDirective
2974   |-using
2975   |-namespace
2976   |-::
2977   |-ns
2978   `-;
2979 )txt"));
2980 }
2981 
2982 TEST_P(SyntaxTreeTest, UsingDeclaration) {
2983   if (!GetParam().isCXX()) {
2984     return;
2985   }
2986   EXPECT_TRUE(treeDumpEqual(
2987       R"cpp(
2988 namespace ns { int a; }
2989 using ns::a;
2990 )cpp",
2991       R"txt(
2992 *: TranslationUnit
2993 |-NamespaceDefinition
2994 | |-namespace
2995 | |-ns
2996 | |-{
2997 | |-SimpleDeclaration
2998 | | |-int
2999 | | |-SimpleDeclarator
3000 | | | `-a
3001 | | `-;
3002 | `-}
3003 `-UsingDeclaration
3004   |-using
3005   |-ns
3006   |-::
3007   |-a
3008   `-;
3009 )txt"));
3010 }
3011 
3012 TEST_P(SyntaxTreeTest, FreeStandingClasses) {
3013   // Free-standing classes, must live inside a SimpleDeclaration.
3014   EXPECT_TRUE(treeDumpEqual(
3015       R"cpp(
3016 struct X;
3017 struct X {};
3018 
3019 struct Y *y1;
3020 struct Y {} *y2;
3021 
3022 struct {} *a1;
3023 )cpp",
3024       R"txt(
3025 *: TranslationUnit
3026 |-SimpleDeclaration
3027 | |-struct
3028 | |-X
3029 | `-;
3030 |-SimpleDeclaration
3031 | |-struct
3032 | |-X
3033 | |-{
3034 | |-}
3035 | `-;
3036 |-SimpleDeclaration
3037 | |-struct
3038 | |-Y
3039 | |-SimpleDeclarator
3040 | | |-*
3041 | | `-y1
3042 | `-;
3043 |-SimpleDeclaration
3044 | |-struct
3045 | |-Y
3046 | |-{
3047 | |-}
3048 | |-SimpleDeclarator
3049 | | |-*
3050 | | `-y2
3051 | `-;
3052 `-SimpleDeclaration
3053   |-struct
3054   |-{
3055   |-}
3056   |-SimpleDeclarator
3057   | |-*
3058   | `-a1
3059   `-;
3060 )txt"));
3061 }
3062 
3063 TEST_P(SyntaxTreeTest, Templates) {
3064   if (!GetParam().isCXX()) {
3065     return;
3066   }
3067   if (GetParam().hasDelayedTemplateParsing()) {
3068     // FIXME: Make this test work on Windows by generating the expected syntax
3069     // tree when `-fdelayed-template-parsing` is active.
3070     return;
3071   }
3072   EXPECT_TRUE(treeDumpEqual(
3073       R"cpp(
3074 template <class T> struct cls {};
3075 template <class T> int var = 10;
3076 template <class T> int fun() {}
3077 )cpp",
3078       R"txt(
3079 *: TranslationUnit
3080 |-TemplateDeclaration
3081 | |-template
3082 | |-<
3083 | |-UnknownDeclaration
3084 | | |-class
3085 | | `-T
3086 | |->
3087 | `-SimpleDeclaration
3088 |   |-struct
3089 |   |-cls
3090 |   |-{
3091 |   |-}
3092 |   `-;
3093 |-TemplateDeclaration
3094 | |-template
3095 | |-<
3096 | |-UnknownDeclaration
3097 | | |-class
3098 | | `-T
3099 | |->
3100 | `-SimpleDeclaration
3101 |   |-int
3102 |   |-SimpleDeclarator
3103 |   | |-var
3104 |   | |-=
3105 |   | `-IntegerLiteralExpression
3106 |   |   `-10
3107 |   `-;
3108 `-TemplateDeclaration
3109   |-template
3110   |-<
3111   |-UnknownDeclaration
3112   | |-class
3113   | `-T
3114   |->
3115   `-SimpleDeclaration
3116     |-int
3117     |-SimpleDeclarator
3118     | |-fun
3119     | `-ParametersAndQualifiers
3120     |   |-(
3121     |   `-)
3122     `-CompoundStatement
3123       |-{
3124       `-}
3125 )txt"));
3126 }
3127 
3128 TEST_P(SyntaxTreeTest, NestedTemplates) {
3129   if (!GetParam().isCXX()) {
3130     return;
3131   }
3132   EXPECT_TRUE(treeDumpEqual(
3133       R"cpp(
3134 template <class T>
3135 struct X {
3136   template <class U>
3137   U foo();
3138 };
3139 )cpp",
3140       R"txt(
3141 *: TranslationUnit
3142 `-TemplateDeclaration
3143   |-template
3144   |-<
3145   |-UnknownDeclaration
3146   | |-class
3147   | `-T
3148   |->
3149   `-SimpleDeclaration
3150     |-struct
3151     |-X
3152     |-{
3153     |-TemplateDeclaration
3154     | |-template
3155     | |-<
3156     | |-UnknownDeclaration
3157     | | |-class
3158     | | `-U
3159     | |->
3160     | `-SimpleDeclaration
3161     |   |-U
3162     |   |-SimpleDeclarator
3163     |   | |-foo
3164     |   | `-ParametersAndQualifiers
3165     |   |   |-(
3166     |   |   `-)
3167     |   `-;
3168     |-}
3169     `-;
3170 )txt"));
3171 }
3172 
3173 TEST_P(SyntaxTreeTest, Templates2) {
3174   if (!GetParam().isCXX()) {
3175     return;
3176   }
3177   EXPECT_TRUE(treeDumpEqual(
3178       R"cpp(
3179 template <class T> struct X { struct Y; };
3180 template <class T> struct X<T>::Y {};
3181 )cpp",
3182       R"txt(
3183 *: TranslationUnit
3184 |-TemplateDeclaration
3185 | |-template
3186 | |-<
3187 | |-UnknownDeclaration
3188 | | |-class
3189 | | `-T
3190 | |->
3191 | `-SimpleDeclaration
3192 |   |-struct
3193 |   |-X
3194 |   |-{
3195 |   |-SimpleDeclaration
3196 |   | |-struct
3197 |   | |-Y
3198 |   | `-;
3199 |   |-}
3200 |   `-;
3201 `-TemplateDeclaration
3202   |-template
3203   |-<
3204   |-UnknownDeclaration
3205   | |-class
3206   | `-T
3207   |->
3208   `-SimpleDeclaration
3209     |-struct
3210     |-X
3211     |-<
3212     |-T
3213     |->
3214     |-::
3215     |-Y
3216     |-{
3217     |-}
3218     `-;
3219 )txt"));
3220 }
3221 
3222 TEST_P(SyntaxTreeTest, TemplatesUsingUsing) {
3223   if (!GetParam().isCXX()) {
3224     return;
3225   }
3226   EXPECT_TRUE(treeDumpEqual(
3227       R"cpp(
3228 template <class T> struct X {
3229   using T::foo;
3230   using typename T::bar;
3231 };
3232 )cpp",
3233       R"txt(
3234 *: TranslationUnit
3235 `-TemplateDeclaration
3236   |-template
3237   |-<
3238   |-UnknownDeclaration
3239   | |-class
3240   | `-T
3241   |->
3242   `-SimpleDeclaration
3243     |-struct
3244     |-X
3245     |-{
3246     |-UsingDeclaration
3247     | |-using
3248     | |-T
3249     | |-::
3250     | |-foo
3251     | `-;
3252     |-UsingDeclaration
3253     | |-using
3254     | |-typename
3255     | |-T
3256     | |-::
3257     | |-bar
3258     | `-;
3259     |-}
3260     `-;
3261 )txt"));
3262 }
3263 
3264 TEST_P(SyntaxTreeTest, ExplicitTemplateInstantations) {
3265   if (!GetParam().isCXX()) {
3266     return;
3267   }
3268   EXPECT_TRUE(treeDumpEqual(
3269       R"cpp(
3270 template <class T> struct X {};
3271 template <class T> struct X<T*> {};
3272 template <> struct X<int> {};
3273 
3274 template struct X<double>;
3275 extern template struct X<float>;
3276 )cpp",
3277       R"txt(
3278 *: TranslationUnit
3279 |-TemplateDeclaration
3280 | |-template
3281 | |-<
3282 | |-UnknownDeclaration
3283 | | |-class
3284 | | `-T
3285 | |->
3286 | `-SimpleDeclaration
3287 |   |-struct
3288 |   |-X
3289 |   |-{
3290 |   |-}
3291 |   `-;
3292 |-TemplateDeclaration
3293 | |-template
3294 | |-<
3295 | |-UnknownDeclaration
3296 | | |-class
3297 | | `-T
3298 | |->
3299 | `-SimpleDeclaration
3300 |   |-struct
3301 |   |-X
3302 |   |-<
3303 |   |-T
3304 |   |-*
3305 |   |->
3306 |   |-{
3307 |   |-}
3308 |   `-;
3309 |-TemplateDeclaration
3310 | |-template
3311 | |-<
3312 | |->
3313 | `-SimpleDeclaration
3314 |   |-struct
3315 |   |-X
3316 |   |-<
3317 |   |-int
3318 |   |->
3319 |   |-{
3320 |   |-}
3321 |   `-;
3322 |-ExplicitTemplateInstantiation
3323 | |-template
3324 | `-SimpleDeclaration
3325 |   |-struct
3326 |   |-X
3327 |   |-<
3328 |   |-double
3329 |   |->
3330 |   `-;
3331 `-ExplicitTemplateInstantiation
3332   |-extern
3333   |-template
3334   `-SimpleDeclaration
3335     |-struct
3336     |-X
3337     |-<
3338     |-float
3339     |->
3340     `-;
3341 )txt"));
3342 }
3343 
3344 TEST_P(SyntaxTreeTest, UsingType) {
3345   if (!GetParam().isCXX()) {
3346     return;
3347   }
3348   EXPECT_TRUE(treeDumpEqual(
3349       R"cpp(
3350 using type = int;
3351 )cpp",
3352       R"txt(
3353 *: TranslationUnit
3354 `-TypeAliasDeclaration
3355   |-using
3356   |-type
3357   |-=
3358   |-int
3359   `-;
3360 )txt"));
3361 }
3362 
3363 TEST_P(SyntaxTreeTest, EmptyDeclaration) {
3364   EXPECT_TRUE(treeDumpEqual(
3365       R"cpp(
3366 ;
3367 )cpp",
3368       R"txt(
3369 *: TranslationUnit
3370 `-EmptyDeclaration
3371   `-;
3372 )txt"));
3373 }
3374 
3375 TEST_P(SyntaxTreeTest, StaticAssert) {
3376   if (!GetParam().isCXX11OrLater()) {
3377     return;
3378   }
3379   EXPECT_TRUE(treeDumpEqual(
3380       R"cpp(
3381 static_assert(true, "message");
3382 static_assert(true);
3383 )cpp",
3384       R"txt(
3385 *: TranslationUnit
3386 |-StaticAssertDeclaration
3387 | |-static_assert
3388 | |-(
3389 | |-BoolLiteralExpression
3390 | | `-true
3391 | |-,
3392 | |-StringLiteralExpression
3393 | | `-"message"
3394 | |-)
3395 | `-;
3396 `-StaticAssertDeclaration
3397   |-static_assert
3398   |-(
3399   |-BoolLiteralExpression
3400   | `-true
3401   |-)
3402   `-;
3403 )txt"));
3404 }
3405 
3406 TEST_P(SyntaxTreeTest, ExternC) {
3407   if (!GetParam().isCXX()) {
3408     return;
3409   }
3410   EXPECT_TRUE(treeDumpEqual(
3411       R"cpp(
3412 extern "C" int a;
3413 extern "C" { int b; int c; }
3414 )cpp",
3415       R"txt(
3416 *: TranslationUnit
3417 |-LinkageSpecificationDeclaration
3418 | |-extern
3419 | |-"C"
3420 | `-SimpleDeclaration
3421 |   |-int
3422 |   |-SimpleDeclarator
3423 |   | `-a
3424 |   `-;
3425 `-LinkageSpecificationDeclaration
3426   |-extern
3427   |-"C"
3428   |-{
3429   |-SimpleDeclaration
3430   | |-int
3431   | |-SimpleDeclarator
3432   | | `-b
3433   | `-;
3434   |-SimpleDeclaration
3435   | |-int
3436   | |-SimpleDeclarator
3437   | | `-c
3438   | `-;
3439   `-}
3440 )txt"));
3441 }
3442 
3443 TEST_P(SyntaxTreeTest, NonModifiableNodes) {
3444   // Some nodes are non-modifiable, they are marked with 'I:'.
3445   EXPECT_TRUE(treeDumpEqual(
3446       R"cpp(
3447 #define HALF_IF if (1+
3448 #define HALF_IF_2 1) {}
3449 void test() {
3450   HALF_IF HALF_IF_2 else {}
3451 })cpp",
3452       R"txt(
3453 *: TranslationUnit
3454 `-SimpleDeclaration
3455   |-void
3456   |-SimpleDeclarator
3457   | |-test
3458   | `-ParametersAndQualifiers
3459   |   |-(
3460   |   `-)
3461   `-CompoundStatement
3462     |-{
3463     |-IfStatement
3464     | |-I: if
3465     | |-I: (
3466     | |-I: BinaryOperatorExpression
3467     | | |-I: IntegerLiteralExpression
3468     | | | `-I: 1
3469     | | |-I: +
3470     | | `-I: IntegerLiteralExpression
3471     | |   `-I: 1
3472     | |-I: )
3473     | |-I: CompoundStatement
3474     | | |-I: {
3475     | | `-I: }
3476     | |-else
3477     | `-CompoundStatement
3478     |   |-{
3479     |   `-}
3480     `-}
3481 )txt"));
3482 }
3483 
3484 TEST_P(SyntaxTreeTest, ModifiableNodes) {
3485   // All nodes can be mutated.
3486   EXPECT_TRUE(treeDumpEqual(
3487       R"cpp(
3488 #define OPEN {
3489 #define CLOSE }
3490 
3491 void test() {
3492   OPEN
3493     1;
3494   CLOSE
3495 
3496   OPEN
3497     2;
3498   }
3499 }
3500 )cpp",
3501       R"txt(
3502 *: TranslationUnit
3503 `-SimpleDeclaration
3504   |-void
3505   |-SimpleDeclarator
3506   | |-test
3507   | `-ParametersAndQualifiers
3508   |   |-(
3509   |   `-)
3510   `-CompoundStatement
3511     |-{
3512     |-CompoundStatement
3513     | |-{
3514     | |-ExpressionStatement
3515     | | |-IntegerLiteralExpression
3516     | | | `-1
3517     | | `-;
3518     | `-}
3519     |-CompoundStatement
3520     | |-{
3521     | |-ExpressionStatement
3522     | | |-IntegerLiteralExpression
3523     | | | `-2
3524     | | `-;
3525     | `-}
3526     `-}
3527 )txt"));
3528 }
3529 
3530 TEST_P(SyntaxTreeTest, ArraySubscriptsInDeclarators) {
3531   EXPECT_TRUE(treeDumpEqual(
3532       R"cpp(
3533 int a[10];
3534 int b[1][2][3];
3535 int c[] = {1,2,3};
3536 )cpp",
3537       R"txt(
3538 *: TranslationUnit
3539 |-SimpleDeclaration
3540 | |-int
3541 | |-SimpleDeclarator
3542 | | |-a
3543 | | `-ArraySubscript
3544 | |   |-[
3545 | |   |-IntegerLiteralExpression
3546 | |   | `-10
3547 | |   `-]
3548 | `-;
3549 |-SimpleDeclaration
3550 | |-int
3551 | |-SimpleDeclarator
3552 | | |-b
3553 | | |-ArraySubscript
3554 | | | |-[
3555 | | | |-IntegerLiteralExpression
3556 | | | | `-1
3557 | | | `-]
3558 | | |-ArraySubscript
3559 | | | |-[
3560 | | | |-IntegerLiteralExpression
3561 | | | | `-2
3562 | | | `-]
3563 | | `-ArraySubscript
3564 | |   |-[
3565 | |   |-IntegerLiteralExpression
3566 | |   | `-3
3567 | |   `-]
3568 | `-;
3569 `-SimpleDeclaration
3570   |-int
3571   |-SimpleDeclarator
3572   | |-c
3573   | |-ArraySubscript
3574   | | |-[
3575   | | `-]
3576   | |-=
3577   | `-UnknownExpression
3578   |   `-UnknownExpression
3579   |     |-{
3580   |     |-IntegerLiteralExpression
3581   |     | `-1
3582   |     |-,
3583   |     |-IntegerLiteralExpression
3584   |     | `-2
3585   |     |-,
3586   |     |-IntegerLiteralExpression
3587   |     | `-3
3588   |     `-}
3589   `-;
3590 )txt"));
3591 }
3592 
3593 TEST_P(SyntaxTreeTest, StaticArraySubscriptsInDeclarators) {
3594   if (!GetParam().isC99OrLater()) {
3595     return;
3596   }
3597   EXPECT_TRUE(treeDumpEqual(
3598       R"cpp(
3599 void f(int xs[static 10]);
3600 )cpp",
3601       R"txt(
3602 *: TranslationUnit
3603 `-SimpleDeclaration
3604   |-void
3605   |-SimpleDeclarator
3606   | |-f
3607   | `-ParametersAndQualifiers
3608   |   |-(
3609   |   |-SimpleDeclaration
3610   |   | |-int
3611   |   | `-SimpleDeclarator
3612   |   |   |-xs
3613   |   |   `-ArraySubscript
3614   |   |     |-[
3615   |   |     |-static
3616   |   |     |-IntegerLiteralExpression
3617   |   |     | `-10
3618   |   |     `-]
3619   |   `-)
3620   `-;
3621 )txt"));
3622 }
3623 
3624 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctions) {
3625   if (!GetParam().isCXX()) {
3626     return;
3627   }
3628   EXPECT_TRUE(treeDumpEqual(
3629       R"cpp(
3630 int func1();
3631 int func2a(int a);
3632 int func2b(int);
3633 int func3a(int *ap);
3634 int func3b(int *);
3635 int func4a(int a, float b);
3636 int func4b(int, float);
3637 )cpp",
3638       R"txt(
3639 *: TranslationUnit
3640 |-SimpleDeclaration
3641 | |-int
3642 | |-SimpleDeclarator
3643 | | |-func1
3644 | | `-ParametersAndQualifiers
3645 | |   |-(
3646 | |   `-)
3647 | `-;
3648 |-SimpleDeclaration
3649 | |-int
3650 | |-SimpleDeclarator
3651 | | |-func2a
3652 | | `-ParametersAndQualifiers
3653 | |   |-(
3654 | |   |-SimpleDeclaration
3655 | |   | |-int
3656 | |   | `-SimpleDeclarator
3657 | |   |   `-a
3658 | |   `-)
3659 | `-;
3660 |-SimpleDeclaration
3661 | |-int
3662 | |-SimpleDeclarator
3663 | | |-func2b
3664 | | `-ParametersAndQualifiers
3665 | |   |-(
3666 | |   |-SimpleDeclaration
3667 | |   | `-int
3668 | |   `-)
3669 | `-;
3670 |-SimpleDeclaration
3671 | |-int
3672 | |-SimpleDeclarator
3673 | | |-func3a
3674 | | `-ParametersAndQualifiers
3675 | |   |-(
3676 | |   |-SimpleDeclaration
3677 | |   | |-int
3678 | |   | `-SimpleDeclarator
3679 | |   |   |-*
3680 | |   |   `-ap
3681 | |   `-)
3682 | `-;
3683 |-SimpleDeclaration
3684 | |-int
3685 | |-SimpleDeclarator
3686 | | |-func3b
3687 | | `-ParametersAndQualifiers
3688 | |   |-(
3689 | |   |-SimpleDeclaration
3690 | |   | |-int
3691 | |   | `-SimpleDeclarator
3692 | |   |   `-*
3693 | |   `-)
3694 | `-;
3695 |-SimpleDeclaration
3696 | |-int
3697 | |-SimpleDeclarator
3698 | | |-func4a
3699 | | `-ParametersAndQualifiers
3700 | |   |-(
3701 | |   |-SimpleDeclaration
3702 | |   | |-int
3703 | |   | `-SimpleDeclarator
3704 | |   |   `-a
3705 | |   |-,
3706 | |   |-SimpleDeclaration
3707 | |   | |-float
3708 | |   | `-SimpleDeclarator
3709 | |   |   `-b
3710 | |   `-)
3711 | `-;
3712 `-SimpleDeclaration
3713   |-int
3714   |-SimpleDeclarator
3715   | |-func4b
3716   | `-ParametersAndQualifiers
3717   |   |-(
3718   |   |-SimpleDeclaration
3719   |   | `-int
3720   |   |-,
3721   |   |-SimpleDeclaration
3722   |   | `-float
3723   |   `-)
3724   `-;
3725 )txt"));
3726 }
3727 
3728 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx) {
3729   if (!GetParam().isCXX()) {
3730     return;
3731   }
3732   EXPECT_TRUE(treeDumpEqual(
3733       R"cpp(
3734 int func1(const int a, volatile int b, const volatile int c);
3735 int func2(int& a);
3736 )cpp",
3737       R"txt(
3738 *: TranslationUnit
3739 |-SimpleDeclaration
3740 | |-int
3741 | |-SimpleDeclarator
3742 | | |-func1
3743 | | `-ParametersAndQualifiers
3744 | |   |-(
3745 | |   |-SimpleDeclaration
3746 | |   | |-const
3747 | |   | |-int
3748 | |   | `-SimpleDeclarator
3749 | |   |   `-a
3750 | |   |-,
3751 | |   |-SimpleDeclaration
3752 | |   | |-volatile
3753 | |   | |-int
3754 | |   | `-SimpleDeclarator
3755 | |   |   `-b
3756 | |   |-,
3757 | |   |-SimpleDeclaration
3758 | |   | |-const
3759 | |   | |-volatile
3760 | |   | |-int
3761 | |   | `-SimpleDeclarator
3762 | |   |   `-c
3763 | |   `-)
3764 | `-;
3765 `-SimpleDeclaration
3766   |-int
3767   |-SimpleDeclarator
3768   | |-func2
3769   | `-ParametersAndQualifiers
3770   |   |-(
3771   |   |-SimpleDeclaration
3772   |   | |-int
3773   |   | `-SimpleDeclarator
3774   |   |   |-&
3775   |   |   `-a
3776   |   `-)
3777   `-;
3778 )txt"));
3779 }
3780 
3781 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInFreeFunctionsCxx11) {
3782   if (!GetParam().isCXX11OrLater()) {
3783     return;
3784   }
3785   EXPECT_TRUE(treeDumpEqual(
3786       R"cpp(
3787 int func1(int&& a);
3788 )cpp",
3789       R"txt(
3790 *: TranslationUnit
3791 `-SimpleDeclaration
3792   |-int
3793   |-SimpleDeclarator
3794   | |-func1
3795   | `-ParametersAndQualifiers
3796   |   |-(
3797   |   |-SimpleDeclaration
3798   |   | |-int
3799   |   | `-SimpleDeclarator
3800   |   |   |-&&
3801   |   |   `-a
3802   |   `-)
3803   `-;
3804 )txt"));
3805 }
3806 
3807 TEST_P(SyntaxTreeTest, ParametersAndQualifiersInMemberFunctions) {
3808   if (!GetParam().isCXX()) {
3809     return;
3810   }
3811   EXPECT_TRUE(treeDumpEqual(
3812       R"cpp(
3813 struct Test {
3814   int a();
3815   int b() const;
3816   int c() volatile;
3817   int d() const volatile;
3818   int e() &;
3819   int f() &&;
3820 };
3821 )cpp",
3822       R"txt(
3823 *: TranslationUnit
3824 `-SimpleDeclaration
3825   |-struct
3826   |-Test
3827   |-{
3828   |-SimpleDeclaration
3829   | |-int
3830   | |-SimpleDeclarator
3831   | | |-a
3832   | | `-ParametersAndQualifiers
3833   | |   |-(
3834   | |   `-)
3835   | `-;
3836   |-SimpleDeclaration
3837   | |-int
3838   | |-SimpleDeclarator
3839   | | |-b
3840   | | `-ParametersAndQualifiers
3841   | |   |-(
3842   | |   |-)
3843   | |   `-const
3844   | `-;
3845   |-SimpleDeclaration
3846   | |-int
3847   | |-SimpleDeclarator
3848   | | |-c
3849   | | `-ParametersAndQualifiers
3850   | |   |-(
3851   | |   |-)
3852   | |   `-volatile
3853   | `-;
3854   |-SimpleDeclaration
3855   | |-int
3856   | |-SimpleDeclarator
3857   | | |-d
3858   | | `-ParametersAndQualifiers
3859   | |   |-(
3860   | |   |-)
3861   | |   |-const
3862   | |   `-volatile
3863   | `-;
3864   |-SimpleDeclaration
3865   | |-int
3866   | |-SimpleDeclarator
3867   | | |-e
3868   | | `-ParametersAndQualifiers
3869   | |   |-(
3870   | |   |-)
3871   | |   `-&
3872   | `-;
3873   |-SimpleDeclaration
3874   | |-int
3875   | |-SimpleDeclarator
3876   | | |-f
3877   | | `-ParametersAndQualifiers
3878   | |   |-(
3879   | |   |-)
3880   | |   `-&&
3881   | `-;
3882   |-}
3883   `-;
3884 )txt"));
3885 }
3886 
3887 TEST_P(SyntaxTreeTest, TrailingReturn) {
3888   if (!GetParam().isCXX11OrLater()) {
3889     return;
3890   }
3891   EXPECT_TRUE(treeDumpEqual(
3892       R"cpp(
3893 auto foo() -> int;
3894 )cpp",
3895       R"txt(
3896 *: TranslationUnit
3897 `-SimpleDeclaration
3898   |-auto
3899   |-SimpleDeclarator
3900   | |-foo
3901   | `-ParametersAndQualifiers
3902   |   |-(
3903   |   |-)
3904   |   `-TrailingReturnType
3905   |     |-->
3906   |     `-int
3907   `-;
3908 )txt"));
3909 }
3910 
3911 TEST_P(SyntaxTreeTest, DynamicExceptionSpecification) {
3912   if (!GetParam().supportsCXXDynamicExceptionSpecification()) {
3913     return;
3914   }
3915   EXPECT_TRUE(treeDumpEqual(
3916       R"cpp(
3917 struct MyException1 {};
3918 struct MyException2 {};
3919 int a() throw();
3920 int b() throw(...);
3921 int c() throw(MyException1);
3922 int d() throw(MyException1, MyException2);
3923 )cpp",
3924       R"txt(
3925 *: TranslationUnit
3926 |-SimpleDeclaration
3927 | |-struct
3928 | |-MyException1
3929 | |-{
3930 | |-}
3931 | `-;
3932 |-SimpleDeclaration
3933 | |-struct
3934 | |-MyException2
3935 | |-{
3936 | |-}
3937 | `-;
3938 |-SimpleDeclaration
3939 | |-int
3940 | |-SimpleDeclarator
3941 | | |-a
3942 | | `-ParametersAndQualifiers
3943 | |   |-(
3944 | |   |-)
3945 | |   |-throw
3946 | |   |-(
3947 | |   `-)
3948 | `-;
3949 |-SimpleDeclaration
3950 | |-int
3951 | |-SimpleDeclarator
3952 | | |-b
3953 | | `-ParametersAndQualifiers
3954 | |   |-(
3955 | |   |-)
3956 | |   |-throw
3957 | |   |-(
3958 | |   |-...
3959 | |   `-)
3960 | `-;
3961 |-SimpleDeclaration
3962 | |-int
3963 | |-SimpleDeclarator
3964 | | |-c
3965 | | `-ParametersAndQualifiers
3966 | |   |-(
3967 | |   |-)
3968 | |   |-throw
3969 | |   |-(
3970 | |   |-MyException1
3971 | |   `-)
3972 | `-;
3973 `-SimpleDeclaration
3974   |-int
3975   |-SimpleDeclarator
3976   | |-d
3977   | `-ParametersAndQualifiers
3978   |   |-(
3979   |   |-)
3980   |   |-throw
3981   |   |-(
3982   |   |-MyException1
3983   |   |-,
3984   |   |-MyException2
3985   |   `-)
3986   `-;
3987 )txt"));
3988 }
3989 
3990 TEST_P(SyntaxTreeTest, NoexceptExceptionSpecification) {
3991   if (!GetParam().isCXX11OrLater()) {
3992     return;
3993   }
3994   EXPECT_TRUE(treeDumpEqual(
3995       R"cpp(
3996 int a() noexcept;
3997 int b() noexcept(true);
3998 )cpp",
3999       R"txt(
4000 *: TranslationUnit
4001 |-SimpleDeclaration
4002 | |-int
4003 | |-SimpleDeclarator
4004 | | |-a
4005 | | `-ParametersAndQualifiers
4006 | |   |-(
4007 | |   |-)
4008 | |   `-noexcept
4009 | `-;
4010 `-SimpleDeclaration
4011   |-int
4012   |-SimpleDeclarator
4013   | |-b
4014   | `-ParametersAndQualifiers
4015   |   |-(
4016   |   |-)
4017   |   |-noexcept
4018   |   |-(
4019   |   |-BoolLiteralExpression
4020   |   | `-true
4021   |   `-)
4022   `-;
4023 )txt"));
4024 }
4025 
4026 TEST_P(SyntaxTreeTest, DeclaratorsInParentheses) {
4027   EXPECT_TRUE(treeDumpEqual(
4028       R"cpp(
4029 int (a);
4030 int *(b);
4031 int (*c)(int);
4032 int *(d)(int);
4033 )cpp",
4034       R"txt(
4035 *: TranslationUnit
4036 |-SimpleDeclaration
4037 | |-int
4038 | |-SimpleDeclarator
4039 | | `-ParenDeclarator
4040 | |   |-(
4041 | |   |-a
4042 | |   `-)
4043 | `-;
4044 |-SimpleDeclaration
4045 | |-int
4046 | |-SimpleDeclarator
4047 | | |-*
4048 | | `-ParenDeclarator
4049 | |   |-(
4050 | |   |-b
4051 | |   `-)
4052 | `-;
4053 |-SimpleDeclaration
4054 | |-int
4055 | |-SimpleDeclarator
4056 | | |-ParenDeclarator
4057 | | | |-(
4058 | | | |-*
4059 | | | |-c
4060 | | | `-)
4061 | | `-ParametersAndQualifiers
4062 | |   |-(
4063 | |   |-SimpleDeclaration
4064 | |   | `-int
4065 | |   `-)
4066 | `-;
4067 `-SimpleDeclaration
4068   |-int
4069   |-SimpleDeclarator
4070   | |-*
4071   | |-ParenDeclarator
4072   | | |-(
4073   | | |-d
4074   | | `-)
4075   | `-ParametersAndQualifiers
4076   |   |-(
4077   |   |-SimpleDeclaration
4078   |   | `-int
4079   |   `-)
4080   `-;
4081 )txt"));
4082 }
4083 
4084 TEST_P(SyntaxTreeTest, ConstVolatileQualifiers) {
4085   EXPECT_TRUE(treeDumpEqual(
4086       R"cpp(
4087 const int west = -1;
4088 int const east = 1;
4089 const int const universal = 0;
4090 const int const *const *volatile b;
4091 )cpp",
4092       R"txt(
4093 *: TranslationUnit
4094 |-SimpleDeclaration
4095 | |-const
4096 | |-int
4097 | |-SimpleDeclarator
4098 | | |-west
4099 | | |-=
4100 | | `-PrefixUnaryOperatorExpression
4101 | |   |--
4102 | |   `-IntegerLiteralExpression
4103 | |     `-1
4104 | `-;
4105 |-SimpleDeclaration
4106 | |-int
4107 | |-const
4108 | |-SimpleDeclarator
4109 | | |-east
4110 | | |-=
4111 | | `-IntegerLiteralExpression
4112 | |   `-1
4113 | `-;
4114 |-SimpleDeclaration
4115 | |-const
4116 | |-int
4117 | |-const
4118 | |-SimpleDeclarator
4119 | | |-universal
4120 | | |-=
4121 | | `-IntegerLiteralExpression
4122 | |   `-0
4123 | `-;
4124 `-SimpleDeclaration
4125   |-const
4126   |-int
4127   |-const
4128   |-SimpleDeclarator
4129   | |-*
4130   | |-const
4131   | |-*
4132   | |-volatile
4133   | `-b
4134   `-;
4135 )txt"));
4136 }
4137 
4138 TEST_P(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
4139   if (!GetParam().isCXX11OrLater()) {
4140     return;
4141   }
4142   EXPECT_TRUE(treeDumpEqual(
4143       R"cpp(
4144 auto foo() -> auto(*)(int) -> double*;
4145 )cpp",
4146       R"txt(
4147 *: TranslationUnit
4148 `-SimpleDeclaration
4149   |-auto
4150   |-SimpleDeclarator
4151   | |-foo
4152   | `-ParametersAndQualifiers
4153   |   |-(
4154   |   |-)
4155   |   `-TrailingReturnType
4156   |     |-->
4157   |     |-auto
4158   |     `-SimpleDeclarator
4159   |       |-ParenDeclarator
4160   |       | |-(
4161   |       | |-*
4162   |       | `-)
4163   |       `-ParametersAndQualifiers
4164   |         |-(
4165   |         |-SimpleDeclaration
4166   |         | `-int
4167   |         |-)
4168   |         `-TrailingReturnType
4169   |           |-->
4170   |           |-double
4171   |           `-SimpleDeclarator
4172   |             `-*
4173   `-;
4174 )txt"));
4175 }
4176 
4177 TEST_P(SyntaxTreeTest, MemberPointers) {
4178   if (!GetParam().isCXX()) {
4179     return;
4180   }
4181   EXPECT_TRUE(treeDumpEqual(
4182       R"cpp(
4183 struct X {};
4184 int X::* a;
4185 const int X::* b;
4186 )cpp",
4187       R"txt(
4188 *: TranslationUnit
4189 |-SimpleDeclaration
4190 | |-struct
4191 | |-X
4192 | |-{
4193 | |-}
4194 | `-;
4195 |-SimpleDeclaration
4196 | |-int
4197 | |-SimpleDeclarator
4198 | | |-MemberPointer
4199 | | | |-X
4200 | | | |-::
4201 | | | `-*
4202 | | `-a
4203 | `-;
4204 `-SimpleDeclaration
4205   |-const
4206   |-int
4207   |-SimpleDeclarator
4208   | |-MemberPointer
4209   | | |-X
4210   | | |-::
4211   | | `-*
4212   | `-b
4213   `-;
4214 )txt"));
4215 }
4216 
4217 TEST_P(SyntaxTreeTest, MemberFunctionPointer) {
4218   if (!GetParam().isCXX()) {
4219     return;
4220   }
4221   EXPECT_TRUE(treeDumpEqual(
4222       R"cpp(
4223 struct X {
4224   struct Y {};
4225 };
4226 void (X::*xp)();
4227 void (X::**xpp)(const int*);
4228 // FIXME: Generate the right syntax tree for this type,
4229 // i.e. create a syntax node for the outer member pointer
4230 void (X::Y::*xyp)(const int*, char);
4231 )cpp",
4232       R"txt(
4233 *: TranslationUnit
4234 |-SimpleDeclaration
4235 | |-struct
4236 | |-X
4237 | |-{
4238 | |-SimpleDeclaration
4239 | | |-struct
4240 | | |-Y
4241 | | |-{
4242 | | |-}
4243 | | `-;
4244 | |-}
4245 | `-;
4246 |-SimpleDeclaration
4247 | |-void
4248 | |-SimpleDeclarator
4249 | | |-ParenDeclarator
4250 | | | |-(
4251 | | | |-MemberPointer
4252 | | | | |-X
4253 | | | | |-::
4254 | | | | `-*
4255 | | | |-xp
4256 | | | `-)
4257 | | `-ParametersAndQualifiers
4258 | |   |-(
4259 | |   `-)
4260 | `-;
4261 |-SimpleDeclaration
4262 | |-void
4263 | |-SimpleDeclarator
4264 | | |-ParenDeclarator
4265 | | | |-(
4266 | | | |-MemberPointer
4267 | | | | |-X
4268 | | | | |-::
4269 | | | | `-*
4270 | | | |-*
4271 | | | |-xpp
4272 | | | `-)
4273 | | `-ParametersAndQualifiers
4274 | |   |-(
4275 | |   |-SimpleDeclaration
4276 | |   | |-const
4277 | |   | |-int
4278 | |   | `-SimpleDeclarator
4279 | |   |   `-*
4280 | |   `-)
4281 | `-;
4282 `-SimpleDeclaration
4283   |-void
4284   |-SimpleDeclarator
4285   | |-ParenDeclarator
4286   | | |-(
4287   | | |-X
4288   | | |-::
4289   | | |-MemberPointer
4290   | | | |-Y
4291   | | | |-::
4292   | | | `-*
4293   | | |-xyp
4294   | | `-)
4295   | `-ParametersAndQualifiers
4296   |   |-(
4297   |   |-SimpleDeclaration
4298   |   | |-const
4299   |   | |-int
4300   |   | `-SimpleDeclarator
4301   |   |   `-*
4302   |   |-,
4303   |   |-SimpleDeclaration
4304   |   | `-char
4305   |   `-)
4306   `-;
4307 )txt"));
4308 }
4309 
4310 TEST_P(SyntaxTreeTest, ComplexDeclarator) {
4311   EXPECT_TRUE(treeDumpEqual(
4312       R"cpp(
4313 void x(char a, short (*b)(int));
4314 )cpp",
4315       R"txt(
4316 *: TranslationUnit
4317 `-SimpleDeclaration
4318   |-void
4319   |-SimpleDeclarator
4320   | |-x
4321   | `-ParametersAndQualifiers
4322   |   |-(
4323   |   |-SimpleDeclaration
4324   |   | |-char
4325   |   | `-SimpleDeclarator
4326   |   |   `-a
4327   |   |-,
4328   |   |-SimpleDeclaration
4329   |   | |-short
4330   |   | `-SimpleDeclarator
4331   |   |   |-ParenDeclarator
4332   |   |   | |-(
4333   |   |   | |-*
4334   |   |   | |-b
4335   |   |   | `-)
4336   |   |   `-ParametersAndQualifiers
4337   |   |     |-(
4338   |   |     |-SimpleDeclaration
4339   |   |     | `-int
4340   |   |     `-)
4341   |   `-)
4342   `-;
4343 )txt"));
4344 }
4345 
4346 TEST_P(SyntaxTreeTest, ComplexDeclarator2) {
4347   EXPECT_TRUE(treeDumpEqual(
4348       R"cpp(
4349 void x(char a, short (*b)(int), long (**c)(long long));
4350 )cpp",
4351       R"txt(
4352 *: TranslationUnit
4353 `-SimpleDeclaration
4354   |-void
4355   |-SimpleDeclarator
4356   | |-x
4357   | `-ParametersAndQualifiers
4358   |   |-(
4359   |   |-SimpleDeclaration
4360   |   | |-char
4361   |   | `-SimpleDeclarator
4362   |   |   `-a
4363   |   |-,
4364   |   |-SimpleDeclaration
4365   |   | |-short
4366   |   | `-SimpleDeclarator
4367   |   |   |-ParenDeclarator
4368   |   |   | |-(
4369   |   |   | |-*
4370   |   |   | |-b
4371   |   |   | `-)
4372   |   |   `-ParametersAndQualifiers
4373   |   |     |-(
4374   |   |     |-SimpleDeclaration
4375   |   |     | `-int
4376   |   |     `-)
4377   |   |-,
4378   |   |-SimpleDeclaration
4379   |   | |-long
4380   |   | `-SimpleDeclarator
4381   |   |   |-ParenDeclarator
4382   |   |   | |-(
4383   |   |   | |-*
4384   |   |   | |-*
4385   |   |   | |-c
4386   |   |   | `-)
4387   |   |   `-ParametersAndQualifiers
4388   |   |     |-(
4389   |   |     |-SimpleDeclaration
4390   |   |     | |-long
4391   |   |     | `-long
4392   |   |     `-)
4393   |   `-)
4394   `-;
4395 )txt"));
4396 }
4397 
4398 TEST_P(SyntaxTreeTest, Mutations) {
4399   if (!GetParam().isCXX11OrLater()) {
4400     return;
4401   }
4402 
4403   using Transformation = std::function<void(
4404       const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>;
4405   auto CheckTransformation = [this](std::string Input, std::string Expected,
4406                                     Transformation Transform) -> void {
4407     llvm::Annotations Source(Input);
4408     auto *Root = buildTree(Source.code(), GetParam());
4409 
4410     Transform(Source, Root);
4411 
4412     auto Replacements = syntax::computeReplacements(*Arena, *Root);
4413     auto Output = tooling::applyAllReplacements(Source.code(), Replacements);
4414     if (!Output) {
4415       ADD_FAILURE() << "could not apply replacements: "
4416                     << llvm::toString(Output.takeError());
4417       return;
4418     }
4419 
4420     EXPECT_EQ(Expected, *Output) << "input is:\n" << Input;
4421   };
4422 
4423   // Removes the selected statement. Input should have exactly one selected
4424   // range and it should correspond to a single statement.
4425   auto RemoveStatement = [this](const llvm::Annotations &Input,
4426                                 syntax::TranslationUnit *TU) {
4427     auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU));
4428     ASSERT_TRUE(S->canModify()) << "cannot remove a statement";
4429     syntax::removeStatement(*Arena, S);
4430     EXPECT_TRUE(S->isDetached());
4431     EXPECT_FALSE(S->isOriginal())
4432         << "node removed from tree cannot be marked as original";
4433   };
4434 
4435   std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>>
4436       Cases = {
4437           {"void test() { [[100+100;]] test(); }", "void test() {  test(); }"},
4438           {"void test() { if (true) [[{}]] else {} }",
4439            "void test() { if (true) ; else {} }"},
4440           {"void test() { [[;]] }", "void test() {  }"}};
4441   for (const auto &C : Cases)
4442     CheckTransformation(C.first, C.second, RemoveStatement);
4443 }
4444 
4445 TEST_P(SyntaxTreeTest, SynthesizedNodes) {
4446   buildTree("", GetParam());
4447 
4448   auto *C = syntax::createPunctuation(*Arena, tok::comma);
4449   ASSERT_NE(C, nullptr);
4450   EXPECT_EQ(C->token()->kind(), tok::comma);
4451   EXPECT_TRUE(C->canModify());
4452   EXPECT_FALSE(C->isOriginal());
4453   EXPECT_TRUE(C->isDetached());
4454 
4455   auto *S = syntax::createEmptyStatement(*Arena);
4456   ASSERT_NE(S, nullptr);
4457   EXPECT_TRUE(S->canModify());
4458   EXPECT_FALSE(S->isOriginal());
4459   EXPECT_TRUE(S->isDetached());
4460 }
4461 
4462 static std::vector<TestClangConfig> allTestClangConfigs() {
4463   std::vector<TestClangConfig> all_configs;
4464   for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11,
4465                             Lang_CXX14, Lang_CXX17, Lang_CXX20}) {
4466     TestClangConfig config;
4467     config.Language = lang;
4468     config.Target = "x86_64-pc-linux-gnu";
4469     all_configs.push_back(config);
4470 
4471     // Windows target is interesting to test because it enables
4472     // `-fdelayed-template-parsing`.
4473     config.Target = "x86_64-pc-win32-msvc";
4474     all_configs.push_back(config);
4475   }
4476   return all_configs;
4477 }
4478 
4479 INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, SyntaxTreeTest,
4480                         testing::ValuesIn(allTestClangConfigs()), );
4481 
4482 } // namespace
4483