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