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