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