xref: /llvm-project/clang/unittests/Tooling/Syntax/TreeTest.cpp (revision 3a574a6cb35953e538e577a88f62af8dd01432c7)
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, UserDefinedBinaryOperator) {
997   expectTreeDumpEqual(
998       R"cpp(
999 struct X {
1000   X& operator=(const X&);
1001   friend X operator+(X, const X&);
1002   friend bool operator<(const X&, const X&);
1003 };
1004 void test(X x, X y) {
1005   x = y;
1006   x + y;
1007   x < y;
1008 }
1009       )cpp",
1010       R"txt(
1011 *: TranslationUnit
1012 |-SimpleDeclaration
1013 | |-struct
1014 | |-X
1015 | |-{
1016 | |-SimpleDeclaration
1017 | | |-X
1018 | | |-SimpleDeclarator
1019 | | | |-&
1020 | | | |-operator
1021 | | | |-=
1022 | | | `-ParametersAndQualifiers
1023 | | |   |-(
1024 | | |   |-SimpleDeclaration
1025 | | |   | |-const
1026 | | |   | |-X
1027 | | |   | `-SimpleDeclarator
1028 | | |   |   `-&
1029 | | |   `-)
1030 | | `-;
1031 | |-UnknownDeclaration
1032 | | `-SimpleDeclaration
1033 | |   |-friend
1034 | |   |-X
1035 | |   |-SimpleDeclarator
1036 | |   | |-operator
1037 | |   | |-+
1038 | |   | `-ParametersAndQualifiers
1039 | |   |   |-(
1040 | |   |   |-SimpleDeclaration
1041 | |   |   | `-X
1042 | |   |   |-,
1043 | |   |   |-SimpleDeclaration
1044 | |   |   | |-const
1045 | |   |   | |-X
1046 | |   |   | `-SimpleDeclarator
1047 | |   |   |   `-&
1048 | |   |   `-)
1049 | |   `-;
1050 | |-UnknownDeclaration
1051 | | `-SimpleDeclaration
1052 | |   |-friend
1053 | |   |-bool
1054 | |   |-SimpleDeclarator
1055 | |   | |-operator
1056 | |   | |-<
1057 | |   | `-ParametersAndQualifiers
1058 | |   |   |-(
1059 | |   |   |-SimpleDeclaration
1060 | |   |   | |-const
1061 | |   |   | |-X
1062 | |   |   | `-SimpleDeclarator
1063 | |   |   |   `-&
1064 | |   |   |-,
1065 | |   |   |-SimpleDeclaration
1066 | |   |   | |-const
1067 | |   |   | |-X
1068 | |   |   | `-SimpleDeclarator
1069 | |   |   |   `-&
1070 | |   |   `-)
1071 | |   `-;
1072 | |-}
1073 | `-;
1074 `-SimpleDeclaration
1075   |-void
1076   |-SimpleDeclarator
1077   | |-test
1078   | `-ParametersAndQualifiers
1079   |   |-(
1080   |   |-SimpleDeclaration
1081   |   | |-X
1082   |   | `-SimpleDeclarator
1083   |   |   `-x
1084   |   |-,
1085   |   |-SimpleDeclaration
1086   |   | |-X
1087   |   | `-SimpleDeclarator
1088   |   |   `-y
1089   |   `-)
1090   `-CompoundStatement
1091     |-{
1092     |-ExpressionStatement
1093     | |-BinaryOperatorExpression
1094     | | |-UnknownExpression
1095     | | | `-x
1096     | | |-UnknownExpression
1097     | | | `-=
1098     | | `-UnknownExpression
1099     | |   `-y
1100     | `-;
1101     |-ExpressionStatement
1102     | |-BinaryOperatorExpression
1103     | | |-UnknownExpression
1104     | | | `-UnknownExpression
1105     | | |   `-x
1106     | | |-UnknownExpression
1107     | | | `-+
1108     | | `-UnknownExpression
1109     | |   `-y
1110     | `-;
1111     |-ExpressionStatement
1112     | |-BinaryOperatorExpression
1113     | | |-UnknownExpression
1114     | | | `-x
1115     | | |-UnknownExpression
1116     | | | `-<
1117     | | `-UnknownExpression
1118     | |   `-y
1119     | `-;
1120     `-}
1121 )txt");
1122 }
1123 
1124 TEST_F(SyntaxTreeTest, MultipleDeclaratorsGrouping) {
1125   expectTreeDumpEqual(
1126       R"cpp(
1127       int *a, b; int *c, d;
1128   )cpp",
1129       R"txt(
1130 *: TranslationUnit
1131 |-SimpleDeclaration
1132 | |-int
1133 | |-SimpleDeclarator
1134 | | |-*
1135 | | `-a
1136 | |-,
1137 | |-SimpleDeclarator
1138 | | `-b
1139 | `-;
1140 `-SimpleDeclaration
1141   |-int
1142   |-SimpleDeclarator
1143   | |-*
1144   | `-c
1145   |-,
1146   |-SimpleDeclarator
1147   | `-d
1148   `-;
1149   )txt");
1150 }
1151 
1152 TEST_F(SyntaxTreeTest, MultipleDeclaratorsGroupingTypedef) {
1153   expectTreeDumpEqual(
1154       R"cpp(
1155     typedef int *a, b;
1156   )cpp",
1157       R"txt(
1158 *: TranslationUnit
1159 `-SimpleDeclaration
1160   |-typedef
1161   |-int
1162   |-SimpleDeclarator
1163   | |-*
1164   | `-a
1165   |-,
1166   |-SimpleDeclarator
1167   | `-b
1168   `-;
1169   )txt");
1170 }
1171 
1172 TEST_F(SyntaxTreeTest, MultipleDeclaratorsInsideStatement) {
1173   expectTreeDumpEqual(
1174       R"cpp(
1175 void foo() {
1176       int *a, b;
1177       typedef int *ta, tb;
1178 }
1179   )cpp",
1180       R"txt(
1181 *: TranslationUnit
1182 `-SimpleDeclaration
1183   |-void
1184   |-SimpleDeclarator
1185   | |-foo
1186   | `-ParametersAndQualifiers
1187   |   |-(
1188   |   `-)
1189   `-CompoundStatement
1190     |-{
1191     |-DeclarationStatement
1192     | |-SimpleDeclaration
1193     | | |-int
1194     | | |-SimpleDeclarator
1195     | | | |-*
1196     | | | `-a
1197     | | |-,
1198     | | `-SimpleDeclarator
1199     | |   `-b
1200     | `-;
1201     |-DeclarationStatement
1202     | |-SimpleDeclaration
1203     | | |-typedef
1204     | | |-int
1205     | | |-SimpleDeclarator
1206     | | | |-*
1207     | | | `-ta
1208     | | |-,
1209     | | `-SimpleDeclarator
1210     | |   `-tb
1211     | `-;
1212     `-}
1213   )txt");
1214 }
1215 
1216 TEST_F(SyntaxTreeTest, Namespaces) {
1217   expectTreeDumpEqual(
1218       R"cpp(
1219 namespace a { namespace b {} }
1220 namespace a::b {}
1221 namespace {}
1222 
1223 namespace foo = a;
1224     )cpp",
1225       R"txt(
1226 *: TranslationUnit
1227 |-NamespaceDefinition
1228 | |-namespace
1229 | |-a
1230 | |-{
1231 | |-NamespaceDefinition
1232 | | |-namespace
1233 | | |-b
1234 | | |-{
1235 | | `-}
1236 | `-}
1237 |-NamespaceDefinition
1238 | |-namespace
1239 | |-a
1240 | |-::
1241 | |-b
1242 | |-{
1243 | `-}
1244 |-NamespaceDefinition
1245 | |-namespace
1246 | |-{
1247 | `-}
1248 `-NamespaceAliasDefinition
1249   |-namespace
1250   |-foo
1251   |-=
1252   |-a
1253   `-;
1254 )txt");
1255 }
1256 
1257 TEST_F(SyntaxTreeTest, UsingDirective) {
1258   expectTreeDumpEqual(
1259       R"cpp(
1260 namespace ns {}
1261 using namespace ::ns;
1262     )cpp",
1263       R"txt(
1264 *: TranslationUnit
1265 |-NamespaceDefinition
1266 | |-namespace
1267 | |-ns
1268 | |-{
1269 | `-}
1270 `-UsingNamespaceDirective
1271   |-using
1272   |-namespace
1273   |-::
1274   |-ns
1275   `-;
1276        )txt");
1277 }
1278 
1279 TEST_F(SyntaxTreeTest, UsingDeclaration) {
1280   expectTreeDumpEqual(
1281       R"cpp(
1282 namespace ns { int a; }
1283 using ns::a;
1284     )cpp",
1285       R"txt(
1286 *: TranslationUnit
1287 |-NamespaceDefinition
1288 | |-namespace
1289 | |-ns
1290 | |-{
1291 | |-SimpleDeclaration
1292 | | |-int
1293 | | |-SimpleDeclarator
1294 | | | `-a
1295 | | `-;
1296 | `-}
1297 `-UsingDeclaration
1298   |-using
1299   |-ns
1300   |-::
1301   |-a
1302   `-;
1303        )txt");
1304 }
1305 
1306 TEST_F(SyntaxTreeTest, FreeStandingClasses) {
1307   // Free-standing classes, must live inside a SimpleDeclaration.
1308   expectTreeDumpEqual(
1309       R"cpp(
1310 struct X;
1311 struct X {};
1312 
1313 struct Y *y1;
1314 struct Y {} *y2;
1315 
1316 struct {} *a1;
1317     )cpp",
1318       R"txt(
1319 *: TranslationUnit
1320 |-SimpleDeclaration
1321 | |-struct
1322 | |-X
1323 | `-;
1324 |-SimpleDeclaration
1325 | |-struct
1326 | |-X
1327 | |-{
1328 | |-}
1329 | `-;
1330 |-SimpleDeclaration
1331 | |-struct
1332 | |-Y
1333 | |-SimpleDeclarator
1334 | | |-*
1335 | | `-y1
1336 | `-;
1337 |-SimpleDeclaration
1338 | |-struct
1339 | |-Y
1340 | |-{
1341 | |-}
1342 | |-SimpleDeclarator
1343 | | |-*
1344 | | `-y2
1345 | `-;
1346 `-SimpleDeclaration
1347   |-struct
1348   |-{
1349   |-}
1350   |-SimpleDeclarator
1351   | |-*
1352   | `-a1
1353   `-;
1354 )txt");
1355 }
1356 
1357 TEST_F(SyntaxTreeTest, Templates) {
1358   expectTreeDumpEqual(
1359       R"cpp(
1360 template <class T> struct cls {};
1361 template <class T> int var = 10;
1362 template <class T> int fun() {}
1363     )cpp",
1364       R"txt(
1365 *: TranslationUnit
1366 |-TemplateDeclaration
1367 | |-template
1368 | |-<
1369 | |-UnknownDeclaration
1370 | | |-class
1371 | | `-T
1372 | |->
1373 | `-SimpleDeclaration
1374 |   |-struct
1375 |   |-cls
1376 |   |-{
1377 |   |-}
1378 |   `-;
1379 |-TemplateDeclaration
1380 | |-template
1381 | |-<
1382 | |-UnknownDeclaration
1383 | | |-class
1384 | | `-T
1385 | |->
1386 | `-SimpleDeclaration
1387 |   |-int
1388 |   |-SimpleDeclarator
1389 |   | |-var
1390 |   | |-=
1391 |   | `-UnknownExpression
1392 |   |   `-10
1393 |   `-;
1394 `-TemplateDeclaration
1395   |-template
1396   |-<
1397   |-UnknownDeclaration
1398   | |-class
1399   | `-T
1400   |->
1401   `-SimpleDeclaration
1402     |-int
1403     |-SimpleDeclarator
1404     | |-fun
1405     | `-ParametersAndQualifiers
1406     |   |-(
1407     |   `-)
1408     `-CompoundStatement
1409       |-{
1410       `-}
1411 )txt",
1412       // FIXME: Make this test work on windows by generating the expected Syntax
1413       // tree when -fdelayed-template-parsing is active.
1414       /*RunWithDelayedTemplateParsing=*/false);
1415 }
1416 
1417 TEST_F(SyntaxTreeTest, NestedTemplates) {
1418   expectTreeDumpEqual(
1419       R"cpp(
1420 template <class T>
1421 struct X {
1422   template <class U>
1423   U foo();
1424 };
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     |-TemplateDeclaration
1440     | |-template
1441     | |-<
1442     | |-UnknownDeclaration
1443     | | |-class
1444     | | `-U
1445     | |->
1446     | `-SimpleDeclaration
1447     |   |-U
1448     |   |-SimpleDeclarator
1449     |   | |-foo
1450     |   | `-ParametersAndQualifiers
1451     |   |   |-(
1452     |   |   `-)
1453     |   `-;
1454     |-}
1455     `-;
1456 )txt");
1457 }
1458 
1459 TEST_F(SyntaxTreeTest, Templates2) {
1460   expectTreeDumpEqual(
1461       R"cpp(
1462 template <class T> struct X { struct Y; };
1463 template <class T> struct X<T>::Y {};
1464     )cpp",
1465       R"txt(
1466 *: TranslationUnit
1467 |-TemplateDeclaration
1468 | |-template
1469 | |-<
1470 | |-UnknownDeclaration
1471 | | |-class
1472 | | `-T
1473 | |->
1474 | `-SimpleDeclaration
1475 |   |-struct
1476 |   |-X
1477 |   |-{
1478 |   |-SimpleDeclaration
1479 |   | |-struct
1480 |   | |-Y
1481 |   | `-;
1482 |   |-}
1483 |   `-;
1484 `-TemplateDeclaration
1485   |-template
1486   |-<
1487   |-UnknownDeclaration
1488   | |-class
1489   | `-T
1490   |->
1491   `-SimpleDeclaration
1492     |-struct
1493     |-X
1494     |-<
1495     |-T
1496     |->
1497     |-::
1498     |-Y
1499     |-{
1500     |-}
1501     `-;
1502        )txt");
1503 }
1504 
1505 TEST_F(SyntaxTreeTest, TemplatesUsingUsing) {
1506   expectTreeDumpEqual(
1507       R"cpp(
1508 template <class T> struct X {
1509   using T::foo;
1510   using typename T::bar;
1511 };
1512     )cpp",
1513       R"txt(
1514 *: TranslationUnit
1515 `-TemplateDeclaration
1516   |-template
1517   |-<
1518   |-UnknownDeclaration
1519   | |-class
1520   | `-T
1521   |->
1522   `-SimpleDeclaration
1523     |-struct
1524     |-X
1525     |-{
1526     |-UsingDeclaration
1527     | |-using
1528     | |-T
1529     | |-::
1530     | |-foo
1531     | `-;
1532     |-UsingDeclaration
1533     | |-using
1534     | |-typename
1535     | |-T
1536     | |-::
1537     | |-bar
1538     | `-;
1539     |-}
1540     `-;
1541        )txt");
1542 }
1543 
1544 TEST_F(SyntaxTreeTest, ExplicitTemplateInstantations) {
1545   expectTreeDumpEqual(
1546       R"cpp(
1547 template <class T> struct X {};
1548 template <class T> struct X<T*> {};
1549 template <> struct X<int> {};
1550 
1551 template struct X<double>;
1552 extern template struct X<float>;
1553 )cpp",
1554       R"txt(
1555 *: TranslationUnit
1556 |-TemplateDeclaration
1557 | |-template
1558 | |-<
1559 | |-UnknownDeclaration
1560 | | |-class
1561 | | `-T
1562 | |->
1563 | `-SimpleDeclaration
1564 |   |-struct
1565 |   |-X
1566 |   |-{
1567 |   |-}
1568 |   `-;
1569 |-TemplateDeclaration
1570 | |-template
1571 | |-<
1572 | |-UnknownDeclaration
1573 | | |-class
1574 | | `-T
1575 | |->
1576 | `-SimpleDeclaration
1577 |   |-struct
1578 |   |-X
1579 |   |-<
1580 |   |-T
1581 |   |-*
1582 |   |->
1583 |   |-{
1584 |   |-}
1585 |   `-;
1586 |-TemplateDeclaration
1587 | |-template
1588 | |-<
1589 | |->
1590 | `-SimpleDeclaration
1591 |   |-struct
1592 |   |-X
1593 |   |-<
1594 |   |-int
1595 |   |->
1596 |   |-{
1597 |   |-}
1598 |   `-;
1599 |-ExplicitTemplateInstantiation
1600 | |-template
1601 | `-SimpleDeclaration
1602 |   |-struct
1603 |   |-X
1604 |   |-<
1605 |   |-double
1606 |   |->
1607 |   `-;
1608 `-ExplicitTemplateInstantiation
1609   |-extern
1610   |-template
1611   `-SimpleDeclaration
1612     |-struct
1613     |-X
1614     |-<
1615     |-float
1616     |->
1617     `-;
1618 )txt");
1619 }
1620 
1621 TEST_F(SyntaxTreeTest, UsingType) {
1622   expectTreeDumpEqual(
1623       R"cpp(
1624 using type = int;
1625     )cpp",
1626       R"txt(
1627 *: TranslationUnit
1628 `-TypeAliasDeclaration
1629   |-using
1630   |-type
1631   |-=
1632   |-int
1633   `-;
1634        )txt");
1635 }
1636 
1637 TEST_F(SyntaxTreeTest, EmptyDeclaration) {
1638   expectTreeDumpEqual(
1639       R"cpp(
1640 ;
1641     )cpp",
1642       R"txt(
1643 *: TranslationUnit
1644 `-EmptyDeclaration
1645   `-;
1646        )txt");
1647 }
1648 
1649 TEST_F(SyntaxTreeTest, StaticAssert) {
1650   expectTreeDumpEqual(
1651       R"cpp(
1652 static_assert(true, "message");
1653 static_assert(true);
1654     )cpp",
1655       R"txt(
1656 *: TranslationUnit
1657 |-StaticAssertDeclaration
1658 | |-static_assert
1659 | |-(
1660 | |-UnknownExpression
1661 | | `-true
1662 | |-,
1663 | |-UnknownExpression
1664 | | `-"message"
1665 | |-)
1666 | `-;
1667 `-StaticAssertDeclaration
1668   |-static_assert
1669   |-(
1670   |-UnknownExpression
1671   | `-true
1672   |-)
1673   `-;
1674        )txt");
1675 }
1676 
1677 TEST_F(SyntaxTreeTest, ExternC) {
1678   expectTreeDumpEqual(
1679       R"cpp(
1680 extern "C" int a;
1681 extern "C" { int b; int c; }
1682     )cpp",
1683       R"txt(
1684 *: TranslationUnit
1685 |-LinkageSpecificationDeclaration
1686 | |-extern
1687 | |-"C"
1688 | `-SimpleDeclaration
1689 |   |-int
1690 |   |-SimpleDeclarator
1691 |   | `-a
1692 |   `-;
1693 `-LinkageSpecificationDeclaration
1694   |-extern
1695   |-"C"
1696   |-{
1697   |-SimpleDeclaration
1698   | |-int
1699   | |-SimpleDeclarator
1700   | | `-b
1701   | `-;
1702   |-SimpleDeclaration
1703   | |-int
1704   | |-SimpleDeclarator
1705   | | `-c
1706   | `-;
1707   `-}
1708        )txt");
1709 }
1710 
1711 TEST_F(SyntaxTreeTest, NonModifiableNodes) {
1712   // Some nodes are non-modifiable, they are marked with 'I:'.
1713   expectTreeDumpEqual(
1714       R"cpp(
1715 #define HALF_IF if (1+
1716 #define HALF_IF_2 1) {}
1717 void test() {
1718   HALF_IF HALF_IF_2 else {}
1719 })cpp",
1720       R"txt(
1721 *: TranslationUnit
1722 `-SimpleDeclaration
1723   |-void
1724   |-SimpleDeclarator
1725   | |-test
1726   | `-ParametersAndQualifiers
1727   |   |-(
1728   |   `-)
1729   `-CompoundStatement
1730     |-{
1731     |-IfStatement
1732     | |-I: if
1733     | |-I: (
1734     | |-I: BinaryOperatorExpression
1735     | | |-I: UnknownExpression
1736     | | | `-I: 1
1737     | | |-I: +
1738     | | `-I: UnknownExpression
1739     | |   `-I: 1
1740     | |-I: )
1741     | |-I: CompoundStatement
1742     | | |-I: {
1743     | | `-I: }
1744     | |-else
1745     | `-CompoundStatement
1746     |   |-{
1747     |   `-}
1748     `-}
1749        )txt");
1750 }
1751 
1752 TEST_F(SyntaxTreeTest, ModifiableNodes) {
1753   // All nodes can be mutated.
1754   expectTreeDumpEqual(
1755       R"cpp(
1756 #define OPEN {
1757 #define CLOSE }
1758 
1759 void test() {
1760   OPEN
1761     1;
1762   CLOSE
1763 
1764   OPEN
1765     2;
1766   }
1767 }
1768 )cpp",
1769       R"txt(
1770 *: TranslationUnit
1771 `-SimpleDeclaration
1772   |-void
1773   |-SimpleDeclarator
1774   | |-test
1775   | `-ParametersAndQualifiers
1776   |   |-(
1777   |   `-)
1778   `-CompoundStatement
1779     |-{
1780     |-CompoundStatement
1781     | |-{
1782     | |-ExpressionStatement
1783     | | |-UnknownExpression
1784     | | | `-1
1785     | | `-;
1786     | `-}
1787     |-CompoundStatement
1788     | |-{
1789     | |-ExpressionStatement
1790     | | |-UnknownExpression
1791     | | | `-2
1792     | | `-;
1793     | `-}
1794     `-}
1795        )txt");
1796 }
1797 
1798 TEST_F(SyntaxTreeTest, ArraySubscriptsInDeclarators) {
1799   expectTreeDumpEqual(
1800       R"cpp(
1801 int a[10];
1802 int b[1][2][3];
1803 int c[] = {1,2,3};
1804 // void f(int xs[static 10]);
1805     )cpp",
1806       R"txt(
1807 *: TranslationUnit
1808 |-SimpleDeclaration
1809 | |-int
1810 | |-SimpleDeclarator
1811 | | |-a
1812 | | `-ArraySubscript
1813 | |   |-[
1814 | |   |-UnknownExpression
1815 | |   | `-10
1816 | |   `-]
1817 | `-;
1818 |-SimpleDeclaration
1819 | |-int
1820 | |-SimpleDeclarator
1821 | | |-b
1822 | | |-ArraySubscript
1823 | | | |-[
1824 | | | |-UnknownExpression
1825 | | | | `-1
1826 | | | `-]
1827 | | |-ArraySubscript
1828 | | | |-[
1829 | | | |-UnknownExpression
1830 | | | | `-2
1831 | | | `-]
1832 | | `-ArraySubscript
1833 | |   |-[
1834 | |   |-UnknownExpression
1835 | |   | `-3
1836 | |   `-]
1837 | `-;
1838 `-SimpleDeclaration
1839   |-int
1840   |-SimpleDeclarator
1841   | |-c
1842   | |-ArraySubscript
1843   | | |-[
1844   | | `-]
1845   | |-=
1846   | `-UnknownExpression
1847   |   `-UnknownExpression
1848   |     |-{
1849   |     |-UnknownExpression
1850   |     | `-1
1851   |     |-,
1852   |     |-UnknownExpression
1853   |     | `-2
1854   |     |-,
1855   |     |-UnknownExpression
1856   |     | `-3
1857   |     `-}
1858   `-;       )txt");
1859 }
1860 
1861 TEST_F(SyntaxTreeTest, ParameterListsInDeclarators) {
1862   expectTreeDumpEqual(
1863       R"cpp(
1864 struct Test {
1865   int a() const;
1866   int b() volatile;
1867   int c() &;
1868   int d() &&;
1869   int foo(int a, int b);
1870   int foo(const int a, volatile int b, const volatile int c, int* d,
1871           int& e, int&& f);
1872 };
1873       )cpp",
1874       R"txt(
1875 *: TranslationUnit
1876 `-SimpleDeclaration
1877   |-struct
1878   |-Test
1879   |-{
1880   |-SimpleDeclaration
1881   | |-int
1882   | |-SimpleDeclarator
1883   | | |-a
1884   | | `-ParametersAndQualifiers
1885   | |   |-(
1886   | |   |-)
1887   | |   `-const
1888   | `-;
1889   |-SimpleDeclaration
1890   | |-int
1891   | |-SimpleDeclarator
1892   | | |-b
1893   | | `-ParametersAndQualifiers
1894   | |   |-(
1895   | |   |-)
1896   | |   `-volatile
1897   | `-;
1898   |-SimpleDeclaration
1899   | |-int
1900   | |-SimpleDeclarator
1901   | | |-c
1902   | | `-ParametersAndQualifiers
1903   | |   |-(
1904   | |   |-)
1905   | |   `-&
1906   | `-;
1907   |-SimpleDeclaration
1908   | |-int
1909   | |-SimpleDeclarator
1910   | | |-d
1911   | | `-ParametersAndQualifiers
1912   | |   |-(
1913   | |   |-)
1914   | |   `-&&
1915   | `-;
1916   |-SimpleDeclaration
1917   | |-int
1918   | |-SimpleDeclarator
1919   | | |-foo
1920   | | `-ParametersAndQualifiers
1921   | |   |-(
1922   | |   |-SimpleDeclaration
1923   | |   | |-int
1924   | |   | `-SimpleDeclarator
1925   | |   |   `-a
1926   | |   |-,
1927   | |   |-SimpleDeclaration
1928   | |   | |-int
1929   | |   | `-SimpleDeclarator
1930   | |   |   `-b
1931   | |   `-)
1932   | `-;
1933   |-SimpleDeclaration
1934   | |-int
1935   | |-SimpleDeclarator
1936   | | |-foo
1937   | | `-ParametersAndQualifiers
1938   | |   |-(
1939   | |   |-SimpleDeclaration
1940   | |   | |-const
1941   | |   | |-int
1942   | |   | `-SimpleDeclarator
1943   | |   |   `-a
1944   | |   |-,
1945   | |   |-SimpleDeclaration
1946   | |   | |-volatile
1947   | |   | |-int
1948   | |   | `-SimpleDeclarator
1949   | |   |   `-b
1950   | |   |-,
1951   | |   |-SimpleDeclaration
1952   | |   | |-const
1953   | |   | |-volatile
1954   | |   | |-int
1955   | |   | `-SimpleDeclarator
1956   | |   |   `-c
1957   | |   |-,
1958   | |   |-SimpleDeclaration
1959   | |   | |-int
1960   | |   | `-SimpleDeclarator
1961   | |   |   |-*
1962   | |   |   `-d
1963   | |   |-,
1964   | |   |-SimpleDeclaration
1965   | |   | |-int
1966   | |   | `-SimpleDeclarator
1967   | |   |   |-&
1968   | |   |   `-e
1969   | |   |-,
1970   | |   |-SimpleDeclaration
1971   | |   | |-int
1972   | |   | `-SimpleDeclarator
1973   | |   |   |-&&
1974   | |   |   `-f
1975   | |   `-)
1976   | `-;
1977   |-}
1978   `-;
1979        )txt");
1980 }
1981 
1982 TEST_F(SyntaxTreeTest, TrailingConst) {
1983   expectTreeDumpEqual(
1984       R"cpp(
1985 struct X {
1986   int foo() const;
1987 };
1988     )cpp",
1989       R"txt(
1990 *: TranslationUnit
1991 `-SimpleDeclaration
1992   |-struct
1993   |-X
1994   |-{
1995   |-SimpleDeclaration
1996   | |-int
1997   | |-SimpleDeclarator
1998   | | |-foo
1999   | | `-ParametersAndQualifiers
2000   | |   |-(
2001   | |   |-)
2002   | |   `-const
2003   | `-;
2004   |-}
2005   `-;
2006     )txt");
2007 }
2008 
2009 TEST_F(SyntaxTreeTest, TrailingReturn) {
2010   expectTreeDumpEqual(
2011       R"cpp(
2012 auto foo() -> int;
2013     )cpp",
2014       R"txt(
2015 *: TranslationUnit
2016 `-SimpleDeclaration
2017   |-auto
2018   |-SimpleDeclarator
2019   | |-foo
2020   | `-ParametersAndQualifiers
2021   |   |-(
2022   |   |-)
2023   |   `-TrailingReturnType
2024   |     |-->
2025   |     `-int
2026   `-;
2027        )txt");
2028 }
2029 
2030 TEST_F(SyntaxTreeTest, ExceptionSpecification) {
2031   expectTreeDumpEqual(
2032       R"cpp(
2033 int a() noexcept;
2034 int b() noexcept(true);
2035 int c() throw();
2036     )cpp",
2037       R"txt(
2038 *: TranslationUnit
2039 |-SimpleDeclaration
2040 | |-int
2041 | |-SimpleDeclarator
2042 | | |-a
2043 | | `-ParametersAndQualifiers
2044 | |   |-(
2045 | |   |-)
2046 | |   `-noexcept
2047 | `-;
2048 |-SimpleDeclaration
2049 | |-int
2050 | |-SimpleDeclarator
2051 | | |-b
2052 | | `-ParametersAndQualifiers
2053 | |   |-(
2054 | |   |-)
2055 | |   |-noexcept
2056 | |   |-(
2057 | |   |-UnknownExpression
2058 | |   | `-true
2059 | |   `-)
2060 | `-;
2061 `-SimpleDeclaration
2062   |-int
2063   |-SimpleDeclarator
2064   | |-c
2065   | `-ParametersAndQualifiers
2066   |   |-(
2067   |   |-)
2068   |   |-throw
2069   |   |-(
2070   |   `-)
2071   `-;
2072        )txt");
2073 }
2074 
2075 TEST_F(SyntaxTreeTest, DeclaratorsInParentheses) {
2076   expectTreeDumpEqual(
2077       R"cpp(
2078 int (a);
2079 int *(b);
2080 int (*c)(int);
2081 int *(d)(int);
2082     )cpp",
2083       R"txt(
2084 *: TranslationUnit
2085 |-SimpleDeclaration
2086 | |-int
2087 | |-SimpleDeclarator
2088 | | `-ParenDeclarator
2089 | |   |-(
2090 | |   |-a
2091 | |   `-)
2092 | `-;
2093 |-SimpleDeclaration
2094 | |-int
2095 | |-SimpleDeclarator
2096 | | |-*
2097 | | `-ParenDeclarator
2098 | |   |-(
2099 | |   |-b
2100 | |   `-)
2101 | `-;
2102 |-SimpleDeclaration
2103 | |-int
2104 | |-SimpleDeclarator
2105 | | |-ParenDeclarator
2106 | | | |-(
2107 | | | |-*
2108 | | | |-c
2109 | | | `-)
2110 | | `-ParametersAndQualifiers
2111 | |   |-(
2112 | |   |-SimpleDeclaration
2113 | |   | `-int
2114 | |   `-)
2115 | `-;
2116 `-SimpleDeclaration
2117   |-int
2118   |-SimpleDeclarator
2119   | |-*
2120   | |-ParenDeclarator
2121   | | |-(
2122   | | |-d
2123   | | `-)
2124   | `-ParametersAndQualifiers
2125   |   |-(
2126   |   |-SimpleDeclaration
2127   |   | `-int
2128   |   `-)
2129   `-;
2130        )txt");
2131 }
2132 
2133 TEST_F(SyntaxTreeTest, ConstVolatileQualifiers) {
2134   expectTreeDumpEqual(
2135       R"cpp(
2136 const int west = -1;
2137 int const east = 1;
2138 const int const universal = 0;
2139 const int const *const *volatile b;
2140     )cpp",
2141       R"txt(
2142 *: TranslationUnit
2143 |-SimpleDeclaration
2144 | |-const
2145 | |-int
2146 | |-SimpleDeclarator
2147 | | |-west
2148 | | |-=
2149 | | `-PrefixUnaryOperatorExpression
2150 | |   |--
2151 | |   `-UnknownExpression
2152 | |     `-1
2153 | `-;
2154 |-SimpleDeclaration
2155 | |-int
2156 | |-const
2157 | |-SimpleDeclarator
2158 | | |-east
2159 | | |-=
2160 | | `-UnknownExpression
2161 | |   `-1
2162 | `-;
2163 |-SimpleDeclaration
2164 | |-const
2165 | |-int
2166 | |-const
2167 | |-SimpleDeclarator
2168 | | |-universal
2169 | | |-=
2170 | | `-UnknownExpression
2171 | |   `-0
2172 | `-;
2173 `-SimpleDeclaration
2174   |-const
2175   |-int
2176   |-const
2177   |-SimpleDeclarator
2178   | |-*
2179   | |-const
2180   | |-*
2181   | |-volatile
2182   | `-b
2183   `-;
2184        )txt");
2185 }
2186 
2187 TEST_F(SyntaxTreeTest, RangesOfDeclaratorsWithTrailingReturnTypes) {
2188   expectTreeDumpEqual(
2189       R"cpp(
2190 auto foo() -> auto(*)(int) -> double*;
2191     )cpp",
2192       R"txt(
2193 *: TranslationUnit
2194 `-SimpleDeclaration
2195   |-auto
2196   |-SimpleDeclarator
2197   | |-foo
2198   | `-ParametersAndQualifiers
2199   |   |-(
2200   |   |-)
2201   |   `-TrailingReturnType
2202   |     |-->
2203   |     |-auto
2204   |     `-SimpleDeclarator
2205   |       |-ParenDeclarator
2206   |       | |-(
2207   |       | |-*
2208   |       | `-)
2209   |       `-ParametersAndQualifiers
2210   |         |-(
2211   |         |-SimpleDeclaration
2212   |         | `-int
2213   |         |-)
2214   |         `-TrailingReturnType
2215   |           |-->
2216   |           |-double
2217   |           `-SimpleDeclarator
2218   |             `-*
2219   `-;
2220        )txt");
2221 }
2222 
2223 TEST_F(SyntaxTreeTest, MemberPointers) {
2224   expectTreeDumpEqual(
2225       R"cpp(
2226 struct X {};
2227 int X::* a;
2228 const int X::* b;
2229     )cpp",
2230       R"txt(
2231 *: TranslationUnit
2232 |-SimpleDeclaration
2233 | |-struct
2234 | |-X
2235 | |-{
2236 | |-}
2237 | `-;
2238 |-SimpleDeclaration
2239 | |-int
2240 | |-SimpleDeclarator
2241 | | |-MemberPointer
2242 | | | |-X
2243 | | | |-::
2244 | | | `-*
2245 | | `-a
2246 | `-;
2247 `-SimpleDeclaration
2248   |-const
2249   |-int
2250   |-SimpleDeclarator
2251   | |-MemberPointer
2252   | | |-X
2253   | | |-::
2254   | | `-*
2255   | `-b
2256   `-;
2257        )txt");
2258 }
2259 
2260 TEST_F(SyntaxTreeTest, ComplexDeclarator) {
2261   expectTreeDumpEqual(
2262       R"cpp(
2263 void x(char a, short (*b)(int));
2264     )cpp",
2265       R"txt(
2266 *: TranslationUnit
2267 `-SimpleDeclaration
2268   |-void
2269   |-SimpleDeclarator
2270   | |-x
2271   | `-ParametersAndQualifiers
2272   |   |-(
2273   |   |-SimpleDeclaration
2274   |   | |-char
2275   |   | `-SimpleDeclarator
2276   |   |   `-a
2277   |   |-,
2278   |   |-SimpleDeclaration
2279   |   | |-short
2280   |   | `-SimpleDeclarator
2281   |   |   |-ParenDeclarator
2282   |   |   | |-(
2283   |   |   | |-*
2284   |   |   | |-b
2285   |   |   | `-)
2286   |   |   `-ParametersAndQualifiers
2287   |   |     |-(
2288   |   |     |-SimpleDeclaration
2289   |   |     | `-int
2290   |   |     `-)
2291   |   `-)
2292   `-;
2293        )txt");
2294 }
2295 
2296 TEST_F(SyntaxTreeTest, ComplexDeclarator2) {
2297   expectTreeDumpEqual(
2298       R"cpp(
2299 void x(char a, short (*b)(int), long (**c)(long long));
2300     )cpp",
2301       R"txt(
2302 *: TranslationUnit
2303 `-SimpleDeclaration
2304   |-void
2305   |-SimpleDeclarator
2306   | |-x
2307   | `-ParametersAndQualifiers
2308   |   |-(
2309   |   |-SimpleDeclaration
2310   |   | |-char
2311   |   | `-SimpleDeclarator
2312   |   |   `-a
2313   |   |-,
2314   |   |-SimpleDeclaration
2315   |   | |-short
2316   |   | `-SimpleDeclarator
2317   |   |   |-ParenDeclarator
2318   |   |   | |-(
2319   |   |   | |-*
2320   |   |   | |-b
2321   |   |   | `-)
2322   |   |   `-ParametersAndQualifiers
2323   |   |     |-(
2324   |   |     |-SimpleDeclaration
2325   |   |     | `-int
2326   |   |     `-)
2327   |   |-,
2328   |   |-SimpleDeclaration
2329   |   | |-long
2330   |   | `-SimpleDeclarator
2331   |   |   |-ParenDeclarator
2332   |   |   | |-(
2333   |   |   | |-*
2334   |   |   | |-*
2335   |   |   | |-c
2336   |   |   | `-)
2337   |   |   `-ParametersAndQualifiers
2338   |   |     |-(
2339   |   |     |-SimpleDeclaration
2340   |   |     | |-long
2341   |   |     | `-long
2342   |   |     `-)
2343   |   `-)
2344   `-;
2345        )txt");
2346 }
2347 
2348 TEST_F(SyntaxTreeTest, Mutations) {
2349   using Transformation = std::function<void(
2350       const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>;
2351   auto CheckTransformation = [this](std::string Input, std::string Expected,
2352                                     Transformation Transform) -> void {
2353     llvm::Annotations Source(Input);
2354     auto *Root = buildTree(Source.code());
2355 
2356     Transform(Source, Root);
2357 
2358     auto Replacements = syntax::computeReplacements(*Arena, *Root);
2359     auto Output = tooling::applyAllReplacements(Source.code(), Replacements);
2360     if (!Output) {
2361       ADD_FAILURE() << "could not apply replacements: "
2362                     << llvm::toString(Output.takeError());
2363       return;
2364     }
2365 
2366     EXPECT_EQ(Expected, *Output) << "input is:\n" << Input;
2367   };
2368 
2369   // Removes the selected statement. Input should have exactly one selected
2370   // range and it should correspond to a single statement.
2371   auto RemoveStatement = [this](const llvm::Annotations &Input,
2372                                 syntax::TranslationUnit *TU) {
2373     auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU));
2374     ASSERT_TRUE(S->canModify()) << "cannot remove a statement";
2375     syntax::removeStatement(*Arena, S);
2376     EXPECT_TRUE(S->isDetached());
2377     EXPECT_FALSE(S->isOriginal())
2378         << "node removed from tree cannot be marked as original";
2379   };
2380 
2381   std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>>
2382       Cases = {
2383           {"void test() { [[100+100;]] test(); }", "void test() {  test(); }"},
2384           {"void test() { if (true) [[{}]] else {} }",
2385            "void test() { if (true) ; else {} }"},
2386           {"void test() { [[;]] }", "void test() {  }"}};
2387   for (const auto &C : Cases)
2388     CheckTransformation(C.first, C.second, RemoveStatement);
2389 }
2390 
2391 TEST_F(SyntaxTreeTest, SynthesizedNodes) {
2392   buildTree("");
2393 
2394   auto *C = syntax::createPunctuation(*Arena, tok::comma);
2395   ASSERT_NE(C, nullptr);
2396   EXPECT_EQ(C->token()->kind(), tok::comma);
2397   EXPECT_TRUE(C->canModify());
2398   EXPECT_FALSE(C->isOriginal());
2399   EXPECT_TRUE(C->isDetached());
2400 
2401   auto *S = syntax::createEmptyStatement(*Arena);
2402   ASSERT_NE(S, nullptr);
2403   EXPECT_TRUE(S->canModify());
2404   EXPECT_FALSE(S->isOriginal());
2405   EXPECT_TRUE(S->isDetached());
2406 }
2407 
2408 } // namespace
2409