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
14using namespace clang;
15
16/// Exposes private syntax tree APIs required to implement node synthesis.
17/// Should not be used for anything else.
18class clang::syntax::FactoryImpl {
19public:
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, R);
25  }
26  static void appendChildLowLevel(syntax::Tree *T, syntax::Node *Child,
27                                  syntax::NodeRole R) {
28    T->appendChildLowLevel(Child, 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(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.
40syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A,
41                                        TokenBufferTokenManager &TBTM,
42                                        tok::TokenKind K, StringRef Spelling) {
43  auto Tokens =
44      FactoryImpl::lexBuffer(TBTM, llvm::MemoryBuffer::getMemBufferCopy(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
57syntax::Leaf *clang::syntax::createLeaf(syntax::Arena &A,
58                                        TokenBufferTokenManager &TBTM,
59                                        tok::TokenKind K) {
60  const auto *Spelling = tok::getPunctuatorSpelling(K);
61  if (!Spelling)
62    Spelling = tok::getKeywordSpelling(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
68namespace {
69// Allocates the concrete syntax `Tree` according to its `NodeKind`.
70syntax::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
204syntax::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, K);
209  FactoryImpl::setCanModify(T);
210  for (const auto &Child : Children)
211    FactoryImpl::appendChildLowLevel(T, Child.first, Child.second);
212
213  T->assertInvariants();
214  return T;
215}
216
217syntax::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
222    // any macros here.
223    return createLeaf(A, TBTM, TBTM.getToken(L->getTokenKey())->kind(),
224                       TBTM.getText(L->getTokenKey()));
225
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()});
231
232  return createTree(A, Children, N->getKind());
233}
234
235syntax::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