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/Lex/PreprocessorOptions.h"
19 #include "clang/Tooling/Core/Replacement.h"
20 #include "clang/Tooling/Syntax/BuildTree.h"
21 #include "clang/Tooling/Syntax/Mutations.h"
22 #include "clang/Tooling/Syntax/Nodes.h"
23 #include "clang/Tooling/Syntax/Tokens.h"
24 #include "clang/Tooling/Tooling.h"
25 #include "llvm/ADT/ArrayRef.h"
26 #include "llvm/ADT/STLExtras.h"
27 #include "llvm/ADT/StringRef.h"
28 #include "llvm/Support/Casting.h"
29 #include "llvm/Support/Error.h"
30 #include "llvm/Testing/Support/Annotations.h"
31 #include "gmock/gmock.h"
32 #include "gtest/gtest.h"
33 #include <cstdlib>
34 
35 using namespace clang;
36 
37 namespace {
38 static llvm::ArrayRef<syntax::Token> tokens(syntax::Node *N) {
39   assert(N->isOriginal() && "tokens of modified nodes are not well-defined");
40   if (auto *L = dyn_cast<syntax::Leaf>(N))
41     return llvm::makeArrayRef(L->token(), 1);
42   auto *T = cast<syntax::Tree>(N);
43   return llvm::makeArrayRef(T->firstLeaf()->token(),
44                             T->lastLeaf()->token() + 1);
45 }
46 
47 class SyntaxTreeTest : public ::testing::Test {
48 protected:
49   // Build a syntax tree for the code.
50   syntax::TranslationUnit *
51   buildTree(llvm::StringRef Code,
52             const std::string &Target = "x86_64-pc-linux-gnu") {
53     // FIXME: this code is almost the identical to the one in TokensTest. Share
54     //        it.
55     class BuildSyntaxTree : public ASTConsumer {
56     public:
57       BuildSyntaxTree(syntax::TranslationUnit *&Root,
58                       std::unique_ptr<syntax::Arena> &Arena,
59                       std::unique_ptr<syntax::TokenCollector> Tokens)
60           : Root(Root), Arena(Arena), Tokens(std::move(Tokens)) {
61         assert(this->Tokens);
62       }
63 
64       void HandleTranslationUnit(ASTContext &Ctx) override {
65         Arena = std::make_unique<syntax::Arena>(Ctx.getSourceManager(),
66                                                 Ctx.getLangOpts(),
67                                                 std::move(*Tokens).consume());
68         Tokens = nullptr; // make sure we fail if this gets called twice.
69         Root = syntax::buildSyntaxTree(*Arena, *Ctx.getTranslationUnitDecl());
70       }
71 
72     private:
73       syntax::TranslationUnit *&Root;
74       std::unique_ptr<syntax::Arena> &Arena;
75       std::unique_ptr<syntax::TokenCollector> Tokens;
76     };
77 
78     class BuildSyntaxTreeAction : public ASTFrontendAction {
79     public:
80       BuildSyntaxTreeAction(syntax::TranslationUnit *&Root,
81                             std::unique_ptr<syntax::Arena> &Arena)
82           : Root(Root), Arena(Arena) {}
83 
84       std::unique_ptr<ASTConsumer>
85       CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
86         // We start recording the tokens, ast consumer will take on the result.
87         auto Tokens =
88             std::make_unique<syntax::TokenCollector>(CI.getPreprocessor());
89         return std::make_unique<BuildSyntaxTree>(Root, Arena,
90                                                  std::move(Tokens));
91       }
92 
93     private:
94       syntax::TranslationUnit *&Root;
95       std::unique_ptr<syntax::Arena> &Arena;
96     };
97 
98     constexpr const char *FileName = "./input.cpp";
99     FS->addFile(FileName, time_t(), llvm::MemoryBuffer::getMemBufferCopy(""));
100     if (!Diags->getClient())
101       Diags->setClient(new IgnoringDiagConsumer);
102     // Prepare to run a compiler.
103     std::vector<const char *> Args = {
104         "syntax-test", "-target",       Target.c_str(),
105         FileName,      "-fsyntax-only", "-std=c++17",
106     };
107     Invocation = createInvocationFromCommandLine(Args, Diags, FS);
108     assert(Invocation);
109     Invocation->getFrontendOpts().DisableFree = false;
110     Invocation->getPreprocessorOpts().addRemappedFile(
111         FileName, llvm::MemoryBuffer::getMemBufferCopy(Code).release());
112     CompilerInstance Compiler;
113     Compiler.setInvocation(Invocation);
114     Compiler.setDiagnostics(Diags.get());
115     Compiler.setFileManager(FileMgr.get());
116     Compiler.setSourceManager(SourceMgr.get());
117 
118     syntax::TranslationUnit *Root = nullptr;
119     BuildSyntaxTreeAction Recorder(Root, this->Arena);
120     if (!Compiler.ExecuteAction(Recorder)) {
121       ADD_FAILURE() << "failed to run the frontend";
122       std::abort();
123     }
124     return Root;
125   }
126 
127   void expectTreeDumpEqual(StringRef Code, StringRef Tree,
128                            bool RunWithDelayedTemplateParsing = true) {
129     SCOPED_TRACE(Code);
130 
131     std::string Expected = Tree.trim().str();
132 
133     // We want to run the test with -fdelayed-template-parsing enabled and
134     // disabled, therefore we use these representative targets that differ in
135     // the default value.
136     // We are not passing -fdelayed-template-parsing directly but we are using
137     // the `-target` to improve coverage and discover differences in behavior
138     // early.
139     for (const std::string Target :
140          {"x86_64-pc-linux-gnu", "x86_64-pc-win32-msvc"}) {
141       if (!RunWithDelayedTemplateParsing &&
142           Target == "x86_64-pc-win32-msvc") {
143         continue;
144       }
145       auto *Root = buildTree(Code, Target);
146       std::string Actual = std::string(StringRef(Root->dump(*Arena)).trim());
147       EXPECT_EQ(Expected, Actual)
148           << "for target " << Target << " the resulting dump is:\n"
149           << Actual;
150     }
151   }
152 
153   // Adds a file to the test VFS.
154   void addFile(llvm::StringRef Path, llvm::StringRef Contents) {
155     if (!FS->addFile(Path, time_t(),
156                      llvm::MemoryBuffer::getMemBufferCopy(Contents))) {
157       ADD_FAILURE() << "could not add a file to VFS: " << Path;
158     }
159   }
160 
161   /// Finds the deepest node in the tree that covers exactly \p R.
162   /// FIXME: implement this efficiently and move to public syntax tree API.
163   syntax::Node *nodeByRange(llvm::Annotations::Range R, syntax::Node *Root) {
164     llvm::ArrayRef<syntax::Token> Toks = tokens(Root);
165 
166     if (Toks.front().location().isFileID() &&
167         Toks.back().location().isFileID() &&
168         syntax::Token::range(*SourceMgr, Toks.front(), Toks.back()) ==
169             syntax::FileRange(SourceMgr->getMainFileID(), R.Begin, R.End))
170       return Root;
171 
172     auto *T = dyn_cast<syntax::Tree>(Root);
173     if (!T)
174       return nullptr;
175     for (auto *C = T->firstChild(); C != nullptr; C = C->nextSibling()) {
176       if (auto *Result = nodeByRange(R, C))
177         return Result;
178     }
179     return nullptr;
180   }
181 
182   // Data fields.
183   llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
184       new DiagnosticsEngine(new DiagnosticIDs, new DiagnosticOptions);
185   IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS =
186       new llvm::vfs::InMemoryFileSystem;
187   llvm::IntrusiveRefCntPtr<FileManager> FileMgr =
188       new FileManager(FileSystemOptions(), FS);
189   llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr =
190       new SourceManager(*Diags, *FileMgr);
191   std::shared_ptr<CompilerInvocation> Invocation;
192   // Set after calling buildTree().
193   std::unique_ptr<syntax::Arena> Arena;
194 };
195 
196 TEST_F(SyntaxTreeTest, Simple) {
197   expectTreeDumpEqual(
198       R"cpp(
199 int main() {}
200 void foo() {}
201     )cpp",
202       R"txt(
203 *: TranslationUnit
204 |-SimpleDeclaration
205 | |-int
206 | |-SimpleDeclarator
207 | | |-main
208 | | `-ParametersAndQualifiers
209 | |   |-(
210 | |   `-)
211 | `-CompoundStatement
212 |   |-{
213 |   `-}
214 `-SimpleDeclaration
215   |-void
216   |-SimpleDeclarator
217   | |-foo
218   | `-ParametersAndQualifiers
219   |   |-(
220   |   `-)
221   `-CompoundStatement
222     |-{
223     `-}
224 )txt");
225 }
226 
227 TEST_F(SyntaxTreeTest, SimpleVariable) {
228   expectTreeDumpEqual(
229       R"cpp(
230 int a;
231 int b = 42;
232     )cpp",
233       R"txt(
234 *: TranslationUnit
235 |-SimpleDeclaration
236 | |-int
237 | |-SimpleDeclarator
238 | | `-a
239 | `-;
240 `-SimpleDeclaration
241   |-int
242   |-SimpleDeclarator
243   | |-b
244   | |-=
245   | `-UnknownExpression
246   |   `-42
247   `-;
248 )txt");
249 }
250 
251 TEST_F(SyntaxTreeTest, SimpleFunction) {
252   expectTreeDumpEqual(
253       R"cpp(
254 void foo(int a, int b) {}
255     )cpp",
256       R"txt(
257 *: TranslationUnit
258 `-SimpleDeclaration
259   |-void
260   |-SimpleDeclarator
261   | |-foo
262   | `-ParametersAndQualifiers
263   |   |-(
264   |   |-SimpleDeclaration
265   |   | |-int
266   |   | `-SimpleDeclarator
267   |   |   `-a
268   |   |-,
269   |   |-SimpleDeclaration
270   |   | |-int
271   |   | `-SimpleDeclarator
272   |   |   `-b
273   |   `-)
274   `-CompoundStatement
275     |-{
276     `-}
277 )txt");
278 }
279 
280 TEST_F(SyntaxTreeTest, If) {
281   expectTreeDumpEqual(
282       R"cpp(
283 int main() {
284   if (true) {}
285   if (true) {} else if (false) {}
286 }
287         )cpp",
288       R"txt(
289 *: TranslationUnit
290 `-SimpleDeclaration
291   |-int
292   |-SimpleDeclarator
293   | |-main
294   | `-ParametersAndQualifiers
295   |   |-(
296   |   `-)
297   `-CompoundStatement
298     |-{
299     |-IfStatement
300     | |-if
301     | |-(
302     | |-UnknownExpression
303     | | `-true
304     | |-)
305     | `-CompoundStatement
306     |   |-{
307     |   `-}
308     |-IfStatement
309     | |-if
310     | |-(
311     | |-UnknownExpression
312     | | `-true
313     | |-)
314     | |-CompoundStatement
315     | | |-{
316     | | `-}
317     | |-else
318     | `-IfStatement
319     |   |-if
320     |   |-(
321     |   |-UnknownExpression
322     |   | `-false
323     |   |-)
324     |   `-CompoundStatement
325     |     |-{
326     |     `-}
327     `-}
328         )txt");
329 }
330 
331 TEST_F(SyntaxTreeTest, For) {
332   expectTreeDumpEqual(
333       R"cpp(
334 void test() {
335   for (;;)  {}
336 }
337 )cpp",
338       R"txt(
339 *: TranslationUnit
340 `-SimpleDeclaration
341   |-void
342   |-SimpleDeclarator
343   | |-test
344   | `-ParametersAndQualifiers
345   |   |-(
346   |   `-)
347   `-CompoundStatement
348     |-{
349     |-ForStatement
350     | |-for
351     | |-(
352     | |-;
353     | |-;
354     | |-)
355     | `-CompoundStatement
356     |   |-{
357     |   `-}
358     `-}
359         )txt");
360 }
361 
362 TEST_F(SyntaxTreeTest, RangeBasedFor) {
363   expectTreeDumpEqual(
364       R"cpp(
365 void test() {
366   int a[3];
367   for (int x : a) ;
368 }
369       )cpp",
370       R"txt(
371 *: TranslationUnit
372 `-SimpleDeclaration
373   |-void
374   |-SimpleDeclarator
375   | |-test
376   | `-ParametersAndQualifiers
377   |   |-(
378   |   `-)
379   `-CompoundStatement
380     |-{
381     |-DeclarationStatement
382     | |-SimpleDeclaration
383     | | |-int
384     | | `-SimpleDeclarator
385     | |   |-a
386     | |   `-ArraySubscript
387     | |     |-[
388     | |     |-UnknownExpression
389     | |     | `-3
390     | |     `-]
391     | `-;
392     |-RangeBasedForStatement
393     | |-for
394     | |-(
395     | |-SimpleDeclaration
396     | | |-int
397     | | |-SimpleDeclarator
398     | | | `-x
399     | | `-:
400     | |-UnknownExpression
401     | | `-a
402     | |-)
403     | `-EmptyStatement
404     |   `-;
405     `-}
406        )txt");
407 }
408 
409 TEST_F(SyntaxTreeTest, DeclarationStatement) {
410   expectTreeDumpEqual("void test() { int a = 10; }",
411                       R"txt(
412 *: TranslationUnit
413 `-SimpleDeclaration
414   |-void
415   |-SimpleDeclarator
416   | |-test
417   | `-ParametersAndQualifiers
418   |   |-(
419   |   `-)
420   `-CompoundStatement
421     |-{
422     |-DeclarationStatement
423     | |-SimpleDeclaration
424     | | |-int
425     | | `-SimpleDeclarator
426     | |   |-a
427     | |   |-=
428     | |   `-UnknownExpression
429     | |     `-10
430     | `-;
431     `-}
432 )txt");
433 }
434 
435 TEST_F(SyntaxTreeTest, Switch) {
436   expectTreeDumpEqual(
437       R"cpp(
438 void test() {
439   switch (true) {
440     case 0:
441     default:;
442   }
443 }
444 )cpp",
445       R"txt(
446 *: TranslationUnit
447 `-SimpleDeclaration
448   |-void
449   |-SimpleDeclarator
450   | |-test
451   | `-ParametersAndQualifiers
452   |   |-(
453   |   `-)
454   `-CompoundStatement
455     |-{
456     |-SwitchStatement
457     | |-switch
458     | |-(
459     | |-UnknownExpression
460     | | `-true
461     | |-)
462     | `-CompoundStatement
463     |   |-{
464     |   |-CaseStatement
465     |   | |-case
466     |   | |-UnknownExpression
467     |   | | `-0
468     |   | |-:
469     |   | `-DefaultStatement
470     |   |   |-default
471     |   |   |-:
472     |   |   `-EmptyStatement
473     |   |     `-;
474     |   `-}
475     `-}
476 )txt");
477 }
478 
479 TEST_F(SyntaxTreeTest, While) {
480   expectTreeDumpEqual(
481       R"cpp(
482 void test() {
483   while (true) { continue; break; }
484 }
485 )cpp",
486       R"txt(
487 *: TranslationUnit
488 `-SimpleDeclaration
489   |-void
490   |-SimpleDeclarator
491   | |-test
492   | `-ParametersAndQualifiers
493   |   |-(
494   |   `-)
495   `-CompoundStatement
496     |-{
497     |-WhileStatement
498     | |-while
499     | |-(
500     | |-UnknownExpression
501     | | `-true
502     | |-)
503     | `-CompoundStatement
504     |   |-{
505     |   |-ContinueStatement
506     |   | |-continue
507     |   | `-;
508     |   |-BreakStatement
509     |   | |-break
510     |   | `-;
511     |   `-}
512     `-}
513 )txt");
514 }
515 
516 TEST_F(SyntaxTreeTest, UnhandledStatement) {
517   // Unhandled statements should end up as 'unknown statement'.
518   // This example uses a 'label statement', which does not yet have a syntax
519   // counterpart.
520   expectTreeDumpEqual("void main() { foo: return 100; }",
521                       R"txt(
522 *: TranslationUnit
523 `-SimpleDeclaration
524   |-void
525   |-SimpleDeclarator
526   | |-main
527   | `-ParametersAndQualifiers
528   |   |-(
529   |   `-)
530   `-CompoundStatement
531     |-{
532     |-UnknownStatement
533     | |-foo
534     | |-:
535     | `-ReturnStatement
536     |   |-return
537     |   |-UnknownExpression
538     |   | `-100
539     |   `-;
540     `-}
541 )txt");
542 }
543 
544 TEST_F(SyntaxTreeTest, Expressions) {
545   // expressions should be wrapped in 'ExpressionStatement' when they appear
546   // in a statement position.
547   expectTreeDumpEqual(
548       R"cpp(
549 void test() {
550   test();
551   if (true) test(); else test();
552 }
553     )cpp",
554       R"txt(
555 *: TranslationUnit
556 `-SimpleDeclaration
557   |-void
558   |-SimpleDeclarator
559   | |-test
560   | `-ParametersAndQualifiers
561   |   |-(
562   |   `-)
563   `-CompoundStatement
564     |-{
565     |-ExpressionStatement
566     | |-UnknownExpression
567     | | |-test
568     | | |-(
569     | | `-)
570     | `-;
571     |-IfStatement
572     | |-if
573     | |-(
574     | |-UnknownExpression
575     | | `-true
576     | |-)
577     | |-ExpressionStatement
578     | | |-UnknownExpression
579     | | | |-test
580     | | | |-(
581     | | | `-)
582     | | `-;
583     | |-else
584     | `-ExpressionStatement
585     |   |-UnknownExpression
586     |   | |-test
587     |   | |-(
588     |   | `-)
589     |   `-;
590     `-}
591 )txt");
592 }
593 
594 TEST_F(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
595   expectTreeDumpEqual(
596       R"cpp(
597       int *a, b; int *c, d;
598   )cpp",
599       R"txt(
600 *: TranslationUnit
601 |-SimpleDeclaration
602 | |-int
603 | |-SimpleDeclarator
604 | | |-*
605 | | `-a
606 | |-,
607 | |-SimpleDeclarator
608 | | `-b
609 | `-;
610 `-SimpleDeclaration
611   |-int
612   |-SimpleDeclarator
613   | |-*
614   | `-c
615   |-,
616   |-SimpleDeclarator
617   | `-d
618   `-;
619   )txt");
620 }
621 
622 TEST_F(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
623   expectTreeDumpEqual(
624       R"cpp(
625     typedef int *a, b;
626   )cpp",
627       R"txt(
628 *: TranslationUnit
629 `-SimpleDeclaration
630   |-typedef
631   |-int
632   |-SimpleDeclarator
633   | |-*
634   | `-a
635   |-,
636   |-SimpleDeclarator
637   | `-b
638   `-;
639   )txt");
640 }
641 
642 TEST_F(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
643   expectTreeDumpEqual(
644       R"cpp(
645 void foo() {
646       int *a, b;
647       typedef int *ta, tb;
648 }
649   )cpp",
650       R"txt(
651 *: TranslationUnit
652 `-SimpleDeclaration
653   |-void
654   |-SimpleDeclarator
655   | |-foo
656   | `-ParametersAndQualifiers
657   |   |-(
658   |   `-)
659   `-CompoundStatement
660     |-{
661     |-DeclarationStatement
662     | |-SimpleDeclaration
663     | | |-int
664     | | |-SimpleDeclarator
665     | | | |-*
666     | | | `-a
667     | | |-,
668     | | `-SimpleDeclarator
669     | |   `-b
670     | `-;
671     |-DeclarationStatement
672     | |-SimpleDeclaration
673     | | |-typedef
674     | | |-int
675     | | |-SimpleDeclarator
676     | | | |-*
677     | | | `-ta
678     | | |-,
679     | | `-SimpleDeclarator
680     | |   `-tb
681     | `-;
682     `-}
683   )txt");
684 }
685 
686 TEST_F(SyntaxTreeTest, Namespaces) {
687   expectTreeDumpEqual(
688       R"cpp(
689 namespace a { namespace b {} }
690 namespace a::b {}
691 namespace {}
692 
693 namespace foo = a;
694     )cpp",
695       R"txt(
696 *: TranslationUnit
697 |-NamespaceDefinition
698 | |-namespace
699 | |-a
700 | |-{
701 | |-NamespaceDefinition
702 | | |-namespace
703 | | |-b
704 | | |-{
705 | | `-}
706 | `-}
707 |-NamespaceDefinition
708 | |-namespace
709 | |-a
710 | |-::
711 | |-b
712 | |-{
713 | `-}
714 |-NamespaceDefinition
715 | |-namespace
716 | |-{
717 | `-}
718 `-NamespaceAliasDefinition
719   |-namespace
720   |-foo
721   |-=
722   |-a
723   `-;
724 )txt");
725 }
726 
727 TEST_F(SyntaxTreeTest, UsingDirective) {
728   expectTreeDumpEqual(
729       R"cpp(
730 namespace ns {}
731 using namespace ::ns;
732     )cpp",
733       R"txt(
734 *: TranslationUnit
735 |-NamespaceDefinition
736 | |-namespace
737 | |-ns
738 | |-{
739 | `-}
740 `-UsingNamespaceDirective
741   |-using
742   |-namespace
743   |-::
744   |-ns
745   `-;
746        )txt");
747 }
748 
749 TEST_F(SyntaxTreeTest, UsingDeclaration) {
750   expectTreeDumpEqual(
751       R"cpp(
752 namespace ns { int a; }
753 using ns::a;
754     )cpp",
755       R"txt(
756 *: TranslationUnit
757 |-NamespaceDefinition
758 | |-namespace
759 | |-ns
760 | |-{
761 | |-SimpleDeclaration
762 | | |-int
763 | | |-SimpleDeclarator
764 | | | `-a
765 | | `-;
766 | `-}
767 `-UsingDeclaration
768   |-using
769   |-ns
770   |-::
771   |-a
772   `-;
773        )txt");
774 }
775 
776 TEST_F(SyntaxTreeTest, FreeStandingClasses) {
777   // Free-standing classes, must live inside a SimpleDeclaration.
778   expectTreeDumpEqual(
779       R"cpp(
780 sturct X;
781 struct X {};
782 
783 struct Y *y1;
784 struct Y {} *y2;
785 
786 struct {} *a1;
787     )cpp",
788       R"txt(
789 *: TranslationUnit
790 |-SimpleDeclaration
791 | |-sturct
792 | |-X
793 | `-;
794 |-SimpleDeclaration
795 | |-struct
796 | |-X
797 | |-{
798 | |-}
799 | `-;
800 |-SimpleDeclaration
801 | |-struct
802 | |-Y
803 | |-SimpleDeclarator
804 | | |-*
805 | | `-y1
806 | `-;
807 |-SimpleDeclaration
808 | |-struct
809 | |-Y
810 | |-{
811 | |-}
812 | |-SimpleDeclarator
813 | | |-*
814 | | `-y2
815 | `-;
816 `-SimpleDeclaration
817   |-struct
818   |-{
819   |-}
820   |-SimpleDeclarator
821   | |-*
822   | `-a1
823   `-;
824 )txt");
825 }
826 
827 TEST_F(SyntaxTreeTest, Templates) {
828   expectTreeDumpEqual(
829       R"cpp(
830 template <class T> struct cls {};
831 template <class T> int var = 10;
832 template <class T> int fun() {}
833     )cpp",
834       R"txt(
835 *: TranslationUnit
836 |-TemplateDeclaration
837 | |-template
838 | |-<
839 | |-UnknownDeclaration
840 | | |-class
841 | | `-T
842 | |->
843 | `-SimpleDeclaration
844 |   |-struct
845 |   |-cls
846 |   |-{
847 |   |-}
848 |   `-;
849 |-TemplateDeclaration
850 | |-template
851 | |-<
852 | |-UnknownDeclaration
853 | | |-class
854 | | `-T
855 | |->
856 | `-SimpleDeclaration
857 |   |-int
858 |   |-SimpleDeclarator
859 |   | |-var
860 |   | |-=
861 |   | `-UnknownExpression
862 |   |   `-10
863 |   `-;
864 `-TemplateDeclaration
865   |-template
866   |-<
867   |-UnknownDeclaration
868   | |-class
869   | `-T
870   |->
871   `-SimpleDeclaration
872     |-int
873     |-SimpleDeclarator
874     | |-fun
875     | `-ParametersAndQualifiers
876     |   |-(
877     |   `-)
878     `-CompoundStatement
879       |-{
880       `-}
881 )txt",
882       // FIXME: Make this test work on windows by generating the expected Syntax
883       // tree when -fdelayed-template-parsing is active.
884       /*RunWithDelayedTemplateParsing=*/false);
885 }
886 
887 TEST_F(SyntaxTreeTest, NestedTemplates) {
888   expectTreeDumpEqual(
889       R"cpp(
890 template <class T>
891 struct X {
892   template <class U>
893   U foo();
894 };
895     )cpp",
896       R"txt(
897 *: TranslationUnit
898 `-TemplateDeclaration
899   |-template
900   |-<
901   |-UnknownDeclaration
902   | |-class
903   | `-T
904   |->
905   `-SimpleDeclaration
906     |-struct
907     |-X
908     |-{
909     |-TemplateDeclaration
910     | |-template
911     | |-<
912     | |-UnknownDeclaration
913     | | |-class
914     | | `-U
915     | |->
916     | `-SimpleDeclaration
917     |   |-U
918     |   |-SimpleDeclarator
919     |   | |-foo
920     |   | `-ParametersAndQualifiers
921     |   |   |-(
922     |   |   `-)
923     |   `-;
924     |-}
925     `-;
926 )txt");
927 }
928 
929 TEST_F(SyntaxTreeTest, Templates2) {
930   expectTreeDumpEqual(
931       R"cpp(
932 template <class T> struct X { struct Y; };
933 template <class T> struct X<T>::Y {};
934     )cpp",
935       R"txt(
936 *: TranslationUnit
937 |-TemplateDeclaration
938 | |-template
939 | |-<
940 | |-UnknownDeclaration
941 | | |-class
942 | | `-T
943 | |->
944 | `-SimpleDeclaration
945 |   |-struct
946 |   |-X
947 |   |-{
948 |   |-SimpleDeclaration
949 |   | |-struct
950 |   | |-Y
951 |   | `-;
952 |   |-}
953 |   `-;
954 `-TemplateDeclaration
955   |-template
956   |-<
957   |-UnknownDeclaration
958   | |-class
959   | `-T
960   |->
961   `-SimpleDeclaration
962     |-struct
963     |-X
964     |-<
965     |-T
966     |->
967     |-::
968     |-Y
969     |-{
970     |-}
971     `-;
972        )txt");
973 }
974 
975 TEST_F(SyntaxTreeTest, TemplatesUsingUsing) {
976   expectTreeDumpEqual(
977       R"cpp(
978 template <class T> struct X {
979   using T::foo;
980   using typename T::bar;
981 };
982     )cpp",
983       R"txt(
984 *: TranslationUnit
985 `-TemplateDeclaration
986   |-template
987   |-<
988   |-UnknownDeclaration
989   | |-class
990   | `-T
991   |->
992   `-SimpleDeclaration
993     |-struct
994     |-X
995     |-{
996     |-UsingDeclaration
997     | |-using
998     | |-T
999     | |-::
1000     | |-foo
1001     | `-;
1002     |-UsingDeclaration
1003     | |-using
1004     | |-typename
1005     | |-T
1006     | |-::
1007     | |-bar
1008     | `-;
1009     |-}
1010     `-;
1011        )txt");
1012 }
1013 
1014 TEST_F(SyntaxTreeTest, ExplicitTemplateInstantations) {
1015   expectTreeDumpEqual(
1016       R"cpp(
1017 template <class T> struct X {};
1018 template <class T> struct X<T*> {};
1019 template <> struct X<int> {};
1020 
1021 template struct X<double>;
1022 extern template struct X<float>;
1023 )cpp",
1024       R"txt(
1025 *: TranslationUnit
1026 |-TemplateDeclaration
1027 | |-template
1028 | |-<
1029 | |-UnknownDeclaration
1030 | | |-class
1031 | | `-T
1032 | |->
1033 | `-SimpleDeclaration
1034 |   |-struct
1035 |   |-X
1036 |   |-{
1037 |   |-}
1038 |   `-;
1039 |-TemplateDeclaration
1040 | |-template
1041 | |-<
1042 | |-UnknownDeclaration
1043 | | |-class
1044 | | `-T
1045 | |->
1046 | `-SimpleDeclaration
1047 |   |-struct
1048 |   |-X
1049 |   |-<
1050 |   |-T
1051 |   |-*
1052 |   |->
1053 |   |-{
1054 |   |-}
1055 |   `-;
1056 |-TemplateDeclaration
1057 | |-template
1058 | |-<
1059 | |->
1060 | `-SimpleDeclaration
1061 |   |-struct
1062 |   |-X
1063 |   |-<
1064 |   |-int
1065 |   |->
1066 |   |-{
1067 |   |-}
1068 |   `-;
1069 |-ExplicitTemplateInstantiation
1070 | |-template
1071 | `-SimpleDeclaration
1072 |   |-struct
1073 |   |-X
1074 |   |-<
1075 |   |-double
1076 |   |->
1077 |   `-;
1078 `-ExplicitTemplateInstantiation
1079   |-extern
1080   |-template
1081   `-SimpleDeclaration
1082     |-struct
1083     |-X
1084     |-<
1085     |-float
1086     |->
1087     `-;
1088 )txt");
1089 }
1090 
1091 TEST_F(SyntaxTreeTest, UsingType) {
1092   expectTreeDumpEqual(
1093       R"cpp(
1094 using type = int;
1095     )cpp",
1096       R"txt(
1097 *: TranslationUnit
1098 `-TypeAliasDeclaration
1099   |-using
1100   |-type
1101   |-=
1102   |-int
1103   `-;
1104        )txt");
1105 }
1106 
1107 TEST_F(SyntaxTreeTest, EmptyDeclaration) {
1108   expectTreeDumpEqual(
1109       R"cpp(
1110 ;
1111     )cpp",
1112       R"txt(
1113 *: TranslationUnit
1114 `-EmptyDeclaration
1115   `-;
1116        )txt");
1117 }
1118 
1119 TEST_F(SyntaxTreeTest, StaticAssert) {
1120   expectTreeDumpEqual(
1121       R"cpp(
1122 static_assert(true, "message");
1123 static_assert(true);
1124     )cpp",
1125       R"txt(
1126 *: TranslationUnit
1127 |-StaticAssertDeclaration
1128 | |-static_assert
1129 | |-(
1130 | |-UnknownExpression
1131 | | `-true
1132 | |-,
1133 | |-UnknownExpression
1134 | | `-"message"
1135 | |-)
1136 | `-;
1137 `-StaticAssertDeclaration
1138   |-static_assert
1139   |-(
1140   |-UnknownExpression
1141   | `-true
1142   |-)
1143   `-;
1144        )txt");
1145 }
1146 
1147 TEST_F(SyntaxTreeTest, ExternC) {
1148   expectTreeDumpEqual(
1149       R"cpp(
1150 extern "C" int a;
1151 extern "C" { int b; int c; }
1152     )cpp",
1153       R"txt(
1154 *: TranslationUnit
1155 |-LinkageSpecificationDeclaration
1156 | |-extern
1157 | |-"C"
1158 | `-SimpleDeclaration
1159 |   |-int
1160 |   |-SimpleDeclarator
1161 |   | `-a
1162 |   `-;
1163 `-LinkageSpecificationDeclaration
1164   |-extern
1165   |-"C"
1166   |-{
1167   |-SimpleDeclaration
1168   | |-int
1169   | |-SimpleDeclarator
1170   | | `-b
1171   | `-;
1172   |-SimpleDeclaration
1173   | |-int
1174   | |-SimpleDeclarator
1175   | | `-c
1176   | `-;
1177   `-}
1178        )txt");
1179 }
1180 
1181 TEST_F(SyntaxTreeTest, NonModifiableNodes) {
1182   // Some nodes are non-modifiable, they are marked with 'I:'.
1183   expectTreeDumpEqual(
1184       R"cpp(
1185 #define HALF_IF if (1+
1186 #define HALF_IF_2 1) {}
1187 void test() {
1188   HALF_IF HALF_IF_2 else {}
1189 })cpp",
1190       R"txt(
1191 *: TranslationUnit
1192 `-SimpleDeclaration
1193   |-void
1194   |-SimpleDeclarator
1195   | |-test
1196   | `-ParametersAndQualifiers
1197   |   |-(
1198   |   `-)
1199   `-CompoundStatement
1200     |-{
1201     |-IfStatement
1202     | |-I: if
1203     | |-I: (
1204     | |-I: UnknownExpression
1205     | | |-I: 1
1206     | | |-I: +
1207     | | `-I: 1
1208     | |-I: )
1209     | |-I: CompoundStatement
1210     | | |-I: {
1211     | | `-I: }
1212     | |-else
1213     | `-CompoundStatement
1214     |   |-{
1215     |   `-}
1216     `-}
1217        )txt");
1218 }
1219 
1220 TEST_F(SyntaxTreeTest, ModifiableNodes) {
1221   // All nodes can be mutated.
1222   expectTreeDumpEqual(
1223       R"cpp(
1224 #define OPEN {
1225 #define CLOSE }
1226 
1227 void test() {
1228   OPEN
1229     1;
1230   CLOSE
1231 
1232   OPEN
1233     2;
1234   }
1235 }
1236 )cpp",
1237       R"txt(
1238 *: TranslationUnit
1239 `-SimpleDeclaration
1240   |-void
1241   |-SimpleDeclarator
1242   | |-test
1243   | `-ParametersAndQualifiers
1244   |   |-(
1245   |   `-)
1246   `-CompoundStatement
1247     |-{
1248     |-CompoundStatement
1249     | |-{
1250     | |-ExpressionStatement
1251     | | |-UnknownExpression
1252     | | | `-1
1253     | | `-;
1254     | `-}
1255     |-CompoundStatement
1256     | |-{
1257     | |-ExpressionStatement
1258     | | |-UnknownExpression
1259     | | | `-2
1260     | | `-;
1261     | `-}
1262     `-}
1263        )txt");
1264 }
1265 
1266 TEST_F(SyntaxTreeTest, ArraySubscriptsInDeclarators) {
1267   expectTreeDumpEqual(
1268       R"cpp(
1269 int a[10];
1270 int b[1][2][3];
1271 int c[] = {1,2,3};
1272 void f(int xs[static 10]);
1273     )cpp",
1274       R"txt(
1275 *: TranslationUnit
1276 |-SimpleDeclaration
1277 | |-int
1278 | |-SimpleDeclarator
1279 | | |-a
1280 | | `-ArraySubscript
1281 | |   |-[
1282 | |   |-UnknownExpression
1283 | |   | `-10
1284 | |   `-]
1285 | `-;
1286 |-SimpleDeclaration
1287 | |-int
1288 | |-SimpleDeclarator
1289 | | |-b
1290 | | |-ArraySubscript
1291 | | | |-[
1292 | | | |-UnknownExpression
1293 | | | | `-1
1294 | | | `-]
1295 | | |-ArraySubscript
1296 | | | |-[
1297 | | | |-UnknownExpression
1298 | | | | `-2
1299 | | | `-]
1300 | | `-ArraySubscript
1301 | |   |-[
1302 | |   |-UnknownExpression
1303 | |   | `-3
1304 | |   `-]
1305 | `-;
1306 |-SimpleDeclaration
1307 | |-int
1308 | |-SimpleDeclarator
1309 | | |-c
1310 | | |-ArraySubscript
1311 | | | |-[
1312 | | | `-]
1313 | | |-=
1314 | | `-UnknownExpression
1315 | |   |-{
1316 | |   |-1
1317 | |   |-,
1318 | |   |-2
1319 | |   |-,
1320 | |   |-3
1321 | |   `-}
1322 | `-;
1323 `-SimpleDeclaration
1324   |-void
1325   |-SimpleDeclarator
1326   | |-f
1327   | `-ParametersAndQualifiers
1328   |   |-(
1329   |   |-SimpleDeclaration
1330   |   | |-int
1331   |   | `-SimpleDeclarator
1332   |   |   |-xs
1333   |   |   `-ArraySubscript
1334   |   |     |-[
1335   |   |     |-static
1336   |   |     |-UnknownExpression
1337   |   |     | `-10
1338   |   |     `-]
1339   |   `-)
1340   `-;
1341        )txt");
1342 }
1343 
1344 TEST_F(SyntaxTreeTest, ParameterListsInDeclarators) {
1345   expectTreeDumpEqual(
1346       R"cpp(
1347 int a() const;
1348 int b() volatile;
1349 int c() &;
1350 int d() &&;
1351 int foo(int a, int b);
1352 int foo(
1353   const int a,
1354   volatile int b,
1355   const volatile int c,
1356   int* d,
1357   int& e,
1358   int&& f
1359 );
1360     )cpp",
1361       R"txt(
1362 *: TranslationUnit
1363 |-SimpleDeclaration
1364 | |-int
1365 | |-SimpleDeclarator
1366 | | |-a
1367 | | `-ParametersAndQualifiers
1368 | |   |-(
1369 | |   |-)
1370 | |   `-const
1371 | `-;
1372 |-SimpleDeclaration
1373 | |-int
1374 | |-SimpleDeclarator
1375 | | |-b
1376 | | `-ParametersAndQualifiers
1377 | |   |-(
1378 | |   |-)
1379 | |   `-volatile
1380 | `-;
1381 |-SimpleDeclaration
1382 | |-int
1383 | |-SimpleDeclarator
1384 | | |-c
1385 | | `-ParametersAndQualifiers
1386 | |   |-(
1387 | |   |-)
1388 | |   `-&
1389 | `-;
1390 |-SimpleDeclaration
1391 | |-int
1392 | |-SimpleDeclarator
1393 | | |-d
1394 | | `-ParametersAndQualifiers
1395 | |   |-(
1396 | |   |-)
1397 | |   `-&&
1398 | `-;
1399 |-SimpleDeclaration
1400 | |-int
1401 | |-SimpleDeclarator
1402 | | |-foo
1403 | | `-ParametersAndQualifiers
1404 | |   |-(
1405 | |   |-SimpleDeclaration
1406 | |   | |-int
1407 | |   | `-SimpleDeclarator
1408 | |   |   `-a
1409 | |   |-,
1410 | |   |-SimpleDeclaration
1411 | |   | |-int
1412 | |   | `-SimpleDeclarator
1413 | |   |   `-b
1414 | |   `-)
1415 | `-;
1416 `-SimpleDeclaration
1417   |-int
1418   |-SimpleDeclarator
1419   | |-foo
1420   | `-ParametersAndQualifiers
1421   |   |-(
1422   |   |-SimpleDeclaration
1423   |   | |-const
1424   |   | |-int
1425   |   | `-SimpleDeclarator
1426   |   |   `-a
1427   |   |-,
1428   |   |-SimpleDeclaration
1429   |   | |-volatile
1430   |   | |-int
1431   |   | `-SimpleDeclarator
1432   |   |   `-b
1433   |   |-,
1434   |   |-SimpleDeclaration
1435   |   | |-const
1436   |   | |-volatile
1437   |   | |-int
1438   |   | `-SimpleDeclarator
1439   |   |   `-c
1440   |   |-,
1441   |   |-SimpleDeclaration
1442   |   | |-int
1443   |   | `-SimpleDeclarator
1444   |   |   |-*
1445   |   |   `-d
1446   |   |-,
1447   |   |-SimpleDeclaration
1448   |   | |-int
1449   |   | `-SimpleDeclarator
1450   |   |   |-&
1451   |   |   `-e
1452   |   |-,
1453   |   |-SimpleDeclaration
1454   |   | |-int
1455   |   | `-SimpleDeclarator
1456   |   |   |-&&
1457   |   |   `-f
1458   |   `-)
1459   `-;
1460        )txt");
1461 }
1462 
1463 TEST_F(SyntaxTreeTest, TrailingConst) {
1464   expectTreeDumpEqual(
1465       R"cpp(
1466 struct X {
1467   int foo() const;
1468 }
1469     )cpp",
1470       R"txt(
1471 *: TranslationUnit
1472 `-SimpleDeclaration
1473   |-struct
1474   |-X
1475   |-{
1476   |-SimpleDeclaration
1477   | |-int
1478   | |-SimpleDeclarator
1479   | | |-foo
1480   | | `-ParametersAndQualifiers
1481   | |   |-(
1482   | |   |-)
1483   | |   `-const
1484   | `-;
1485   `-}
1486     )txt");
1487 }
1488 
1489 TEST_F(SyntaxTreeTest, TrailingReturn) {
1490   expectTreeDumpEqual(
1491       R"cpp(
1492 auto foo() -> int;
1493     )cpp",
1494       R"txt(
1495 *: TranslationUnit
1496 `-SimpleDeclaration
1497   |-auto
1498   |-SimpleDeclarator
1499   | |-foo
1500   | `-ParametersAndQualifiers
1501   |   |-(
1502   |   |-)
1503   |   `-TrailingReturnType
1504   |     |-->
1505   |     `-int
1506   `-;
1507        )txt");
1508 }
1509 
1510 TEST_F(SyntaxTreeTest, ExceptionSpecification) {
1511   expectTreeDumpEqual(
1512       R"cpp(
1513 int a() noexcept;
1514 int b() noexcept(true);
1515 int c() throw();
1516     )cpp",
1517       R"txt(
1518 *: TranslationUnit
1519 |-SimpleDeclaration
1520 | |-int
1521 | |-SimpleDeclarator
1522 | | |-a
1523 | | `-ParametersAndQualifiers
1524 | |   |-(
1525 | |   |-)
1526 | |   `-noexcept
1527 | `-;
1528 |-SimpleDeclaration
1529 | |-int
1530 | |-SimpleDeclarator
1531 | | |-b
1532 | | `-ParametersAndQualifiers
1533 | |   |-(
1534 | |   |-)
1535 | |   |-noexcept
1536 | |   |-(
1537 | |   |-UnknownExpression
1538 | |   | `-true
1539 | |   `-)
1540 | `-;
1541 `-SimpleDeclaration
1542   |-int
1543   |-SimpleDeclarator
1544   | |-c
1545   | `-ParametersAndQualifiers
1546   |   |-(
1547   |   |-)
1548   |   |-throw
1549   |   |-(
1550   |   `-)
1551   `-;
1552        )txt");
1553 }
1554 
1555 TEST_F(SyntaxTreeTest, DeclaratorsInParentheses) {
1556   expectTreeDumpEqual(
1557       R"cpp(
1558 int (a);
1559 int *(b);
1560 int (*c)(int);
1561 int *(d)(int);
1562     )cpp",
1563       R"txt(
1564 *: TranslationUnit
1565 |-SimpleDeclaration
1566 | |-int
1567 | |-SimpleDeclarator
1568 | | `-ParenDeclarator
1569 | |   |-(
1570 | |   |-a
1571 | |   `-)
1572 | `-;
1573 |-SimpleDeclaration
1574 | |-int
1575 | |-SimpleDeclarator
1576 | | |-*
1577 | | `-ParenDeclarator
1578 | |   |-(
1579 | |   |-b
1580 | |   `-)
1581 | `-;
1582 |-SimpleDeclaration
1583 | |-int
1584 | |-SimpleDeclarator
1585 | | |-ParenDeclarator
1586 | | | |-(
1587 | | | |-*
1588 | | | |-c
1589 | | | `-)
1590 | | `-ParametersAndQualifiers
1591 | |   |-(
1592 | |   |-SimpleDeclaration
1593 | |   | `-int
1594 | |   `-)
1595 | `-;
1596 `-SimpleDeclaration
1597   |-int
1598   |-SimpleDeclarator
1599   | |-*
1600   | |-ParenDeclarator
1601   | | |-(
1602   | | |-d
1603   | | `-)
1604   | `-ParametersAndQualifiers
1605   |   |-(
1606   |   |-SimpleDeclaration
1607   |   | `-int
1608   |   `-)
1609   `-;
1610        )txt");
1611 }
1612 
1613 TEST_F(SyntaxTreeTest, ConstVolatileQualifiers) {
1614   expectTreeDumpEqual(
1615       R"cpp(
1616 const int west = -1;
1617 int const east = 1;
1618 const int const universal = 0;
1619 const int const *const *volatile b;
1620     )cpp",
1621       R"txt(
1622 *: TranslationUnit
1623 |-SimpleDeclaration
1624 | |-const
1625 | |-int
1626 | |-SimpleDeclarator
1627 | | |-west
1628 | | |-=
1629 | | `-UnknownExpression
1630 | |   |--
1631 | |   `-1
1632 | `-;
1633 |-SimpleDeclaration
1634 | |-int
1635 | |-const
1636 | |-SimpleDeclarator
1637 | | |-east
1638 | | |-=
1639 | | `-UnknownExpression
1640 | |   `-1
1641 | `-;
1642 |-SimpleDeclaration
1643 | |-const
1644 | |-int
1645 | |-const
1646 | |-SimpleDeclarator
1647 | | |-universal
1648 | | |-=
1649 | | `-UnknownExpression
1650 | |   `-0
1651 | `-;
1652 `-SimpleDeclaration
1653   |-const
1654   |-int
1655   |-const
1656   |-SimpleDeclarator
1657   | |-*
1658   | |-const
1659   | |-*
1660   | |-volatile
1661   | `-b
1662   `-;
1663        )txt");
1664 }
1665 
1666 TEST_F(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
1667   expectTreeDumpEqual(
1668       R"cpp(
1669 auto foo() -> auto(*)(int) -> double*;
1670     )cpp",
1671       R"txt(
1672 *: TranslationUnit
1673 `-SimpleDeclaration
1674   |-auto
1675   |-SimpleDeclarator
1676   | |-foo
1677   | `-ParametersAndQualifiers
1678   |   |-(
1679   |   |-)
1680   |   `-TrailingReturnType
1681   |     |-->
1682   |     |-auto
1683   |     `-SimpleDeclarator
1684   |       |-ParenDeclarator
1685   |       | |-(
1686   |       | |-*
1687   |       | `-)
1688   |       `-ParametersAndQualifiers
1689   |         |-(
1690   |         |-SimpleDeclaration
1691   |         | `-int
1692   |         |-)
1693   |         `-TrailingReturnType
1694   |           |-->
1695   |           |-double
1696   |           `-SimpleDeclarator
1697   |             `-*
1698   `-;
1699        )txt");
1700 }
1701 
1702 TEST_F(SyntaxTreeTest, MemberPointers) {
1703   expectTreeDumpEqual(
1704       R"cpp(
1705 struct X {};
1706 int X::* a;
1707 const int X::* b;
1708     )cpp",
1709       R"txt(
1710 *: TranslationUnit
1711 |-SimpleDeclaration
1712 | |-struct
1713 | |-X
1714 | |-{
1715 | |-}
1716 | `-;
1717 |-SimpleDeclaration
1718 | |-int
1719 | |-SimpleDeclarator
1720 | | |-MemberPointer
1721 | | | |-X
1722 | | | |-::
1723 | | | `-*
1724 | | `-a
1725 | `-;
1726 `-SimpleDeclaration
1727   |-const
1728   |-int
1729   |-SimpleDeclarator
1730   | |-MemberPointer
1731   | | |-X
1732   | | |-::
1733   | | `-*
1734   | `-b
1735   `-;
1736        )txt");
1737 }
1738 
1739 TEST_F(SyntaxTreeTest, ComplexDeclarator) {
1740   expectTreeDumpEqual(
1741       R"cpp(
1742 void x(char a, short (*b)(int));
1743     )cpp",
1744       R"txt(
1745 *: TranslationUnit
1746 `-SimpleDeclaration
1747   |-void
1748   |-SimpleDeclarator
1749   | |-x
1750   | `-ParametersAndQualifiers
1751   |   |-(
1752   |   |-SimpleDeclaration
1753   |   | |-char
1754   |   | `-SimpleDeclarator
1755   |   |   `-a
1756   |   |-,
1757   |   |-SimpleDeclaration
1758   |   | |-short
1759   |   | `-SimpleDeclarator
1760   |   |   |-ParenDeclarator
1761   |   |   | |-(
1762   |   |   | |-*
1763   |   |   | |-b
1764   |   |   | `-)
1765   |   |   `-ParametersAndQualifiers
1766   |   |     |-(
1767   |   |     |-SimpleDeclaration
1768   |   |     | `-int
1769   |   |     `-)
1770   |   `-)
1771   `-;
1772        )txt");
1773 }
1774 
1775 TEST_F(SyntaxTreeTest, ComplexDeclarator2) {
1776   expectTreeDumpEqual(
1777       R"cpp(
1778 void x(char a, short (*b)(int), long (**c)(long long));
1779     )cpp",
1780       R"txt(
1781 *: TranslationUnit
1782 `-SimpleDeclaration
1783   |-void
1784   |-SimpleDeclarator
1785   | |-x
1786   | `-ParametersAndQualifiers
1787   |   |-(
1788   |   |-SimpleDeclaration
1789   |   | |-char
1790   |   | `-SimpleDeclarator
1791   |   |   `-a
1792   |   |-,
1793   |   |-SimpleDeclaration
1794   |   | |-short
1795   |   | `-SimpleDeclarator
1796   |   |   |-ParenDeclarator
1797   |   |   | |-(
1798   |   |   | |-*
1799   |   |   | |-b
1800   |   |   | `-)
1801   |   |   `-ParametersAndQualifiers
1802   |   |     |-(
1803   |   |     |-SimpleDeclaration
1804   |   |     | `-int
1805   |   |     `-)
1806   |   |-,
1807   |   |-SimpleDeclaration
1808   |   | |-long
1809   |   | `-SimpleDeclarator
1810   |   |   |-ParenDeclarator
1811   |   |   | |-(
1812   |   |   | |-*
1813   |   |   | |-*
1814   |   |   | |-c
1815   |   |   | `-)
1816   |   |   `-ParametersAndQualifiers
1817   |   |     |-(
1818   |   |     |-SimpleDeclaration
1819   |   |     | |-long
1820   |   |     | `-long
1821   |   |     `-)
1822   |   `-)
1823   `-;
1824        )txt");
1825 }
1826 
1827 TEST_F(SyntaxTreeTest, Mutations) {
1828   using Transformation = std::function<void(
1829       const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>;
1830   auto CheckTransformation = [this](std::string Input, std::string Expected,
1831                                     Transformation Transform) -> void {
1832     llvm::Annotations Source(Input);
1833     auto *Root = buildTree(Source.code());
1834 
1835     Transform(Source, Root);
1836 
1837     auto Replacements = syntax::computeReplacements(*Arena, *Root);
1838     auto Output = tooling::applyAllReplacements(Source.code(), Replacements);
1839     if (!Output) {
1840       ADD_FAILURE() << "could not apply replacements: "
1841                     << llvm::toString(Output.takeError());
1842       return;
1843     }
1844 
1845     EXPECT_EQ(Expected, *Output) << "input is:\n" << Input;
1846   };
1847 
1848   // Removes the selected statement. Input should have exactly one selected
1849   // range and it should correspond to a single statement.
1850   auto RemoveStatement = [this](const llvm::Annotations &Input,
1851                                 syntax::TranslationUnit *TU) {
1852     auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU));
1853     ASSERT_TRUE(S->canModify()) << "cannot remove a statement";
1854     syntax::removeStatement(*Arena, S);
1855     EXPECT_TRUE(S->isDetached());
1856     EXPECT_FALSE(S->isOriginal())
1857         << "node removed from tree cannot be marked as original";
1858   };
1859 
1860   std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>>
1861       Cases = {
1862           {"void test() { [[100+100;]] test(); }", "void test() {  test(); }"},
1863           {"void test() { if (true) [[{}]] else {} }",
1864            "void test() { if (true) ; else {} }"},
1865           {"void test() { [[;]] }", "void test() {  }"}};
1866   for (const auto &C : Cases)
1867     CheckTransformation(C.first, C.second, RemoveStatement);
1868 }
1869 
1870 TEST_F(SyntaxTreeTest, SynthesizedNodes) {
1871   buildTree("");
1872 
1873   auto *C = syntax::createPunctuation(*Arena, tok::comma);
1874   ASSERT_NE(C, nullptr);
1875   EXPECT_EQ(C->token()->kind(), tok::comma);
1876   EXPECT_TRUE(C->canModify());
1877   EXPECT_FALSE(C->isOriginal());
1878   EXPECT_TRUE(C->isDetached());
1879 
1880   auto *S = syntax::createEmptyStatement(*Arena);
1881   ASSERT_NE(S, nullptr);
1882   EXPECT_TRUE(S->canModify());
1883   EXPECT_FALSE(S->isOriginal());
1884   EXPECT_TRUE(S->isDetached());
1885 }
1886 
1887 } // namespace
1888