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