1 //===- Synthesis.cpp ------------------------------------------*- C++ -*-=====//
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 #include "clang/Basic/TokenKinds.h"
9 #include "clang/Tooling/Syntax/BuildTree.h"
10 #include "clang/Tooling/Syntax/Tree.h"
11 
12 using namespace clang;
13 
14 /// Exposes private syntax tree APIs required to implement node synthesis.
15 /// Should not be used for anything else.
16 class clang::syntax::FactoryImpl {
17 public:
18   static void setCanModify(syntax::Node *N) { N->CanModify = true; }
19 
20   static void prependChildLowLevel(syntax::Tree *T, syntax::Node *Child,
21                                    syntax::NodeRole R) {
22     T->prependChildLowLevel(Child, R);
23   }
24 
25   static std::pair<FileID, ArrayRef<Token>>
26   lexBuffer(syntax::Arena &A, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
27     return A.lexBuffer(std::move(Buffer));
28   }
29 };
30 
31 // FIXME: `createLeaf` is based on `syntax::tokenize` internally, as such it
32 // doesn't support digraphs or line continuations.
33 syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K,
34                                         StringRef Spelling) {
35   auto Tokens =
36       FactoryImpl::lexBuffer(A, llvm::MemoryBuffer::getMemBufferCopy(Spelling))
37           .second;
38   assert(Tokens.size() == 1);
39   assert(Tokens.front().kind() == K &&
40          "spelling is not lexed into the expected kind of token");
41 
42   auto *Leaf = new (A.getAllocator()) syntax::Leaf(Tokens.begin());
43   syntax::FactoryImpl::setCanModify(Leaf);
44   Leaf->assertInvariants();
45   return Leaf;
46 }
47 
48 syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A, tok::TokenKind K) {
49   const auto *Spelling = tok::getPunctuatorSpelling(K);
50   if (!Spelling)
51     Spelling = tok::getKeywordSpelling(K);
52   assert(Spelling &&
53          "Cannot infer the spelling of the token from its token kind.");
54   return createLeaf(A, K, Spelling);
55 }
56 
57 namespace {
58 // Allocates the concrete syntax `Tree` according to its `NodeKind`.
59 syntax::Tree *allocateTree(syntax::Arena &A, syntax::NodeKind Kind) {
60   switch (Kind) {
61   case syntax::NodeKind::Leaf:
62     assert(false);
63     break;
64   case syntax::NodeKind::TranslationUnit:
65     return new (A.getAllocator()) syntax::TranslationUnit;
66   case syntax::NodeKind::UnknownExpression:
67     return new (A.getAllocator()) syntax::UnknownExpression;
68   case syntax::NodeKind::ParenExpression:
69     return new (A.getAllocator()) syntax::ParenExpression;
70   case syntax::NodeKind::ThisExpression:
71     return new (A.getAllocator()) syntax::ThisExpression;
72   case syntax::NodeKind::IntegerLiteralExpression:
73     return new (A.getAllocator()) syntax::IntegerLiteralExpression;
74   case syntax::NodeKind::CharacterLiteralExpression:
75     return new (A.getAllocator()) syntax::CharacterLiteralExpression;
76   case syntax::NodeKind::FloatingLiteralExpression:
77     return new (A.getAllocator()) syntax::FloatingLiteralExpression;
78   case syntax::NodeKind::StringLiteralExpression:
79     return new (A.getAllocator()) syntax::StringLiteralExpression;
80   case syntax::NodeKind::BoolLiteralExpression:
81     return new (A.getAllocator()) syntax::BoolLiteralExpression;
82   case syntax::NodeKind::CxxNullPtrExpression:
83     return new (A.getAllocator()) syntax::CxxNullPtrExpression;
84   case syntax::NodeKind::IntegerUserDefinedLiteralExpression:
85     return new (A.getAllocator()) syntax::IntegerUserDefinedLiteralExpression;
86   case syntax::NodeKind::FloatUserDefinedLiteralExpression:
87     return new (A.getAllocator()) syntax::FloatUserDefinedLiteralExpression;
88   case syntax::NodeKind::CharUserDefinedLiteralExpression:
89     return new (A.getAllocator()) syntax::CharUserDefinedLiteralExpression;
90   case syntax::NodeKind::StringUserDefinedLiteralExpression:
91     return new (A.getAllocator()) syntax::StringUserDefinedLiteralExpression;
92   case syntax::NodeKind::PrefixUnaryOperatorExpression:
93     return new (A.getAllocator()) syntax::PrefixUnaryOperatorExpression;
94   case syntax::NodeKind::PostfixUnaryOperatorExpression:
95     return new (A.getAllocator()) syntax::PostfixUnaryOperatorExpression;
96   case syntax::NodeKind::BinaryOperatorExpression:
97     return new (A.getAllocator()) syntax::BinaryOperatorExpression;
98   case syntax::NodeKind::UnqualifiedId:
99     return new (A.getAllocator()) syntax::UnqualifiedId;
100   case syntax::NodeKind::IdExpression:
101     return new (A.getAllocator()) syntax::IdExpression;
102   case syntax::NodeKind::CallExpression:
103     return new (A.getAllocator()) syntax::CallExpression;
104   case syntax::NodeKind::UnknownStatement:
105     return new (A.getAllocator()) syntax::UnknownStatement;
106   case syntax::NodeKind::DeclarationStatement:
107     return new (A.getAllocator()) syntax::DeclarationStatement;
108   case syntax::NodeKind::EmptyStatement:
109     return new (A.getAllocator()) syntax::EmptyStatement;
110   case syntax::NodeKind::SwitchStatement:
111     return new (A.getAllocator()) syntax::SwitchStatement;
112   case syntax::NodeKind::CaseStatement:
113     return new (A.getAllocator()) syntax::CaseStatement;
114   case syntax::NodeKind::DefaultStatement:
115     return new (A.getAllocator()) syntax::DefaultStatement;
116   case syntax::NodeKind::IfStatement:
117     return new (A.getAllocator()) syntax::IfStatement;
118   case syntax::NodeKind::ForStatement:
119     return new (A.getAllocator()) syntax::ForStatement;
120   case syntax::NodeKind::WhileStatement:
121     return new (A.getAllocator()) syntax::WhileStatement;
122   case syntax::NodeKind::ContinueStatement:
123     return new (A.getAllocator()) syntax::ContinueStatement;
124   case syntax::NodeKind::BreakStatement:
125     return new (A.getAllocator()) syntax::BreakStatement;
126   case syntax::NodeKind::ReturnStatement:
127     return new (A.getAllocator()) syntax::ReturnStatement;
128   case syntax::NodeKind::RangeBasedForStatement:
129     return new (A.getAllocator()) syntax::RangeBasedForStatement;
130   case syntax::NodeKind::ExpressionStatement:
131     return new (A.getAllocator()) syntax::ExpressionStatement;
132   case syntax::NodeKind::CompoundStatement:
133     return new (A.getAllocator()) syntax::CompoundStatement;
134   case syntax::NodeKind::UnknownDeclaration:
135     return new (A.getAllocator()) syntax::UnknownDeclaration;
136   case syntax::NodeKind::EmptyDeclaration:
137     return new (A.getAllocator()) syntax::EmptyDeclaration;
138   case syntax::NodeKind::StaticAssertDeclaration:
139     return new (A.getAllocator()) syntax::StaticAssertDeclaration;
140   case syntax::NodeKind::LinkageSpecificationDeclaration:
141     return new (A.getAllocator()) syntax::LinkageSpecificationDeclaration;
142   case syntax::NodeKind::SimpleDeclaration:
143     return new (A.getAllocator()) syntax::SimpleDeclaration;
144   case syntax::NodeKind::TemplateDeclaration:
145     return new (A.getAllocator()) syntax::TemplateDeclaration;
146   case syntax::NodeKind::ExplicitTemplateInstantiation:
147     return new (A.getAllocator()) syntax::ExplicitTemplateInstantiation;
148   case syntax::NodeKind::NamespaceDefinition:
149     return new (A.getAllocator()) syntax::NamespaceDefinition;
150   case syntax::NodeKind::NamespaceAliasDefinition:
151     return new (A.getAllocator()) syntax::NamespaceAliasDefinition;
152   case syntax::NodeKind::UsingNamespaceDirective:
153     return new (A.getAllocator()) syntax::UsingNamespaceDirective;
154   case syntax::NodeKind::UsingDeclaration:
155     return new (A.getAllocator()) syntax::UsingDeclaration;
156   case syntax::NodeKind::TypeAliasDeclaration:
157     return new (A.getAllocator()) syntax::TypeAliasDeclaration;
158   case syntax::NodeKind::SimpleDeclarator:
159     return new (A.getAllocator()) syntax::SimpleDeclarator;
160   case syntax::NodeKind::ParenDeclarator:
161     return new (A.getAllocator()) syntax::ParenDeclarator;
162   case syntax::NodeKind::ArraySubscript:
163     return new (A.getAllocator()) syntax::ArraySubscript;
164   case syntax::NodeKind::TrailingReturnType:
165     return new (A.getAllocator()) syntax::TrailingReturnType;
166   case syntax::NodeKind::ParametersAndQualifiers:
167     return new (A.getAllocator()) syntax::ParametersAndQualifiers;
168   case syntax::NodeKind::MemberPointer:
169     return new (A.getAllocator()) syntax::MemberPointer;
170   case syntax::NodeKind::GlobalNameSpecifier:
171     return new (A.getAllocator()) syntax::GlobalNameSpecifier;
172   case syntax::NodeKind::DecltypeNameSpecifier:
173     return new (A.getAllocator()) syntax::DecltypeNameSpecifier;
174   case syntax::NodeKind::IdentifierNameSpecifier:
175     return new (A.getAllocator()) syntax::IdentifierNameSpecifier;
176   case syntax::NodeKind::SimpleTemplateNameSpecifier:
177     return new (A.getAllocator()) syntax::SimpleTemplateNameSpecifier;
178   case syntax::NodeKind::NestedNameSpecifier:
179     return new (A.getAllocator()) syntax::NestedNameSpecifier;
180   case syntax::NodeKind::MemberExpression:
181     return new (A.getAllocator()) syntax::MemberExpression;
182   case syntax::NodeKind::CallArguments:
183     return new (A.getAllocator()) syntax::CallArguments;
184   case syntax::NodeKind::ParameterDeclarationList:
185     return new (A.getAllocator()) syntax::ParameterDeclarationList;
186   }
187   llvm_unreachable("unknown node kind");
188 }
189 } // namespace
190 
191 syntax::Tree *clang::syntax::createTree(
192     syntax::Arena &A,
193     std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children,
194     syntax::NodeKind K) {
195   auto *T = allocateTree(A, K);
196   FactoryImpl::setCanModify(T);
197   for (auto ChildIt = Children.rbegin(); ChildIt != Children.rend(); ++ChildIt)
198     FactoryImpl::prependChildLowLevel(T, ChildIt->first, ChildIt->second);
199 
200   T->assertInvariants();
201   return T;
202 }
203 
204 namespace {
205 bool canModifyAllDescendants(const syntax::Node *N) {
206   if (const auto *L = dyn_cast<syntax::Leaf>(N))
207     return L->canModify();
208 
209   const auto *T = cast<syntax::Tree>(N);
210 
211   if (!T->canModify())
212     return false;
213   for (const auto *Child = T->getFirstChild(); Child;
214        Child = Child->getNextSibling())
215     if (!canModifyAllDescendants(Child))
216       return false;
217 
218   return true;
219 }
220 
221 syntax::Node *deepCopyImpl(syntax::Arena &A, const syntax::Node *N) {
222   if (const auto *L = dyn_cast<syntax::Leaf>(N))
223     return createLeaf(A, L->getToken()->kind(),
224                       L->getToken()->text(A.getSourceManager()));
225 
226   const auto *T = cast<syntax::Tree>(N);
227   std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children;
228   for (const auto *Child = T->getFirstChild(); Child;
229        Child = Child->getNextSibling())
230     Children.push_back({deepCopyImpl(A, Child), Child->getRole()});
231 
232   return createTree(A, Children, N->getKind());
233 }
234 } // namespace
235 
236 syntax::Node *clang::syntax::deepCopy(syntax::Arena &A, const Node *N) {
237   if (!canModifyAllDescendants(N))
238     return nullptr;
239 
240   return deepCopyImpl(A, N);
241 }
242 
243 syntax::EmptyStatement *clang::syntax::createEmptyStatement(syntax::Arena &A) {
244   return cast<EmptyStatement>(
245       createTree(A, {{createLeaf(A, tok::semi), NodeRole::Unknown}},
246                  NodeKind::EmptyStatement));
247 }
248