1 //===- Synthesis.cpp ------------------------------------------*- C++ -*-=====//
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
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"
14 using namespace clang
;
16 /// Exposes private syntax tree APIs required to implement node synthesis.
17 /// Should not be used for anything else.
18 class clang::syntax::FactoryImpl
{
20 static void setCanModify(syntax::Node
*N
) { N
->CanModify
= true; }
22 static void prependChildLowLevel(syntax::Tree
*T
, syntax::Node
*Child
,
24 T
->prependChildLowLevel(Child
, R
);
26 static void appendChildLowLevel(syntax::Tree
*T
, syntax::Node
*Child
,
28 T
->appendChildLowLevel(Child
, R
);
31 static std::pair
<FileID
, ArrayRef
<Token
>>
32 lexBuffer(TokenBufferTokenManager
&TBTM
,
33 std::unique_ptr
<llvm::MemoryBuffer
> Buffer
) {
34 return TBTM
.lexBuffer(std::move(Buffer
));
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
) {
44 FactoryImpl::lexBuffer(TBTM
, llvm::MemoryBuffer::getMemBufferCopy(Spelling
))
46 assert(Tokens
.size() == 1);
47 assert(Tokens
.front().kind() == K
&&
48 "spelling is not lexed into the expected kind of token");
50 auto *Leaf
= new (A
.getAllocator()) syntax::Leaf(
51 reinterpret_cast<TokenManager::Key
>(Tokens
.begin()));
52 syntax::FactoryImpl::setCanModify(Leaf
);
53 Leaf
->assertInvariants();
57 syntax::Leaf
*clang::syntax::createLeaf(syntax::Arena
&A
,
58 TokenBufferTokenManager
&TBTM
,
60 const auto *Spelling
= tok::getPunctuatorSpelling(K
);
62 Spelling
= tok::getKeywordSpelling(K
);
64 "Cannot infer the spelling of the token from its token kind.");
65 return createLeaf(A
, TBTM
, K
, Spelling
);
69 // Allocates the concrete syntax `Tree` according to its `NodeKind`.
70 syntax::Tree
*allocateTree(syntax::Arena
&A
, syntax::NodeKind Kind
) {
72 case syntax::NodeKind::Leaf
:
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
;
200 llvm_unreachable("unknown node kind");
204 syntax::Tree
*clang::syntax::createTree(
206 ArrayRef
<std::pair
<syntax::Node
*, syntax::NodeRole
>> Children
,
207 syntax::NodeKind K
) {
208 auto *T
= allocateTree(A
, K
);
209 FactoryImpl::setCanModify(T
);
210 for (const auto &Child
: Children
)
211 FactoryImpl::appendChildLowLevel(T
, Child
.first
, Child
.second
);
213 T
->assertInvariants();
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
>(N
))
221 // `L->getToken()` gives us the expanded token, thus we implicitly expand
223 return createLeaf(A
, TBTM
, TBTM
.getToken(L
->getTokenKey())->kind(),
224 TBTM
.getText(L
->getTokenKey()));
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({deepCopyExpandingMacros(A
, TBTM
, Child
), Child
->getRole()});
232 return createTree(A
, Children
, N
->getKind());
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
));