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