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