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