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