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