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