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