clang  15.0.0git
Synthesis.cpp
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
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.
19 public:
20  static void setCanModify(syntax::Node *N) { N->CanModify = true; }
21 
23  syntax::NodeRole R) {
24  T->prependChildLowLevel(Child, R);
25  }
27  syntax::NodeRole R) {
28  T->appendChildLowLevel(Child, R);
29  }
30 
31  static std::pair<FileID, ArrayRef<Token>>
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.
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()));
54  return Leaf;
55 }
56 
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 
68 namespace {
69 // Allocates the concrete syntax `Tree` according to its `NodeKind`.
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:
105  case syntax::NodeKind::PostfixUnaryOperatorExpression:
107  case syntax::NodeKind::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:
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:
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:
151  case syntax::NodeKind::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:
159  case syntax::NodeKind::NamespaceDefinition:
160  return new (A.getAllocator()) syntax::NamespaceDefinition;
161  case syntax::NodeKind::NamespaceAliasDefinition:
163  case syntax::NodeKind::UsingNamespaceDirective:
165  case syntax::NodeKind::UsingDeclaration:
166  return new (A.getAllocator()) syntax::UsingDeclaration;
167  case syntax::NodeKind::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:
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:
197  case syntax::NodeKind::DeclaratorList:
198  return new (A.getAllocator()) syntax::DeclaratorList;
199  }
200  llvm_unreachable("unknown node kind");
201 }
202 } // namespace
203 
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 
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 
236  return cast<EmptyStatement>(
237  createTree(A, {{createLeaf(A, TBTM, tok::semi), NodeRole::Unknown}},
238  NodeKind::EmptyStatement));
239 }
clang::syntax::TemplateDeclaration
template <template-parameters> <declaration>
Definition: Nodes.h:414
clang::syntax::FactoryImpl::prependChildLowLevel
static void prependChildLowLevel(syntax::Tree *T, syntax::Node *Child, syntax::NodeRole R)
Definition: Synthesis.cpp:22
clang::syntax::ForStatement
for (<init>; <cond>; <increment>) <body>
Definition: Nodes.h:278
clang::syntax::Token::kind
tok::TokenKind kind() const
Definition: Tokens.h:110
clang::syntax::NamespaceDefinition
namespace <name> { <decls> }
Definition: Nodes.h:438
clang::syntax::RangeBasedForStatement
for (<decl> : <init>) <body>
Definition: Nodes.h:322
clang::syntax::UnknownExpression
An expression of an unknown kind, i.e.
Definition: Nodes.h:135
clang::syntax::ContinueStatement
continue;
Definition: Nodes.h:296
clang::syntax::Node
A node in a syntax tree.
Definition: Tree.h:54
clang::syntax::DeclaratorList
Definition: Nodes.h:393
clang::syntax::ParenDeclarator
Declarator inside parentheses.
Definition: Nodes.h:503
clang::tok::getPunctuatorSpelling
const char * getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple punctuation tokens like '!' or '', and returns NULL for literal and...
Definition: TokenKinds.cpp:31
clang::syntax::NamespaceAliasDefinition
namespace <name> = <namespace-reference>
Definition: Nodes.h:445
BuildTree.h
clang::syntax::UnqualifiedId
Models an unqualified-id.
Definition: Nodes.h:127
clang::syntax::UsingNamespaceDirective
using namespace <name>
Definition: Nodes.h:453
clang::syntax::deepCopyExpandingMacros
syntax::Node * deepCopyExpandingMacros(syntax::Arena &A, TokenBufferTokenManager &TBTM, const syntax::Node *N)
Creates a completely independent copy of N with its macros expanded.
Definition: Synthesis.cpp:217
TokenKinds.h
clang::syntax::StaticAssertDeclaration
static_assert(<condition>, <message>) static_assert(<condition>)
Definition: Nodes.h:376
clang::prec::Unknown
@ Unknown
Definition: OperatorPrecedence.h:27
clang::syntax::BreakStatement
break;
Definition: Nodes.h:304
clang::syntax::Tree
A node that has children and represents a syntactic language construct.
Definition: Tree.h:144
clang::syntax::ArraySubscript
Array size specified inside a declarator.
Definition: Nodes.h:515
clang::syntax::createLeaf
syntax::Leaf * createLeaf(syntax::Arena &A, TokenBufferTokenManager &TBTM, tok::TokenKind K, StringRef Spelling)
Create Leaf from token with Spelling and assert it has the desired TokenKind.
Definition: Synthesis.cpp:40
clang::syntax::createEmptyStatement
syntax::EmptyStatement * createEmptyStatement(syntax::Arena &A, TokenBufferTokenManager &TBTM)
Definition: Synthesis.cpp:235
clang::syntax::BinaryOperatorExpression
<lhs> <operator> <rhs>
Definition: Nodes.h:198
clang::syntax::SimpleDeclaration
Groups multiple declarators (e.g.
Definition: Nodes.h:405
clang::syntax::FactoryImpl::lexBuffer
static std::pair< FileID, ArrayRef< Token > > lexBuffer(TokenBufferTokenManager &TBTM, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Definition: Synthesis.cpp:32
TokenBufferTokenManager.h
clang::syntax::DeclarationStatement
E.g. 'int a, b = 10;'.
Definition: Nodes.h:224
clang::syntax::Node::getKind
NodeKind getKind() const
Definition: Tree.h:70
clang::syntax::EmptyStatement
The no-op statement, i.e. ';'.
Definition: Nodes.h:231
clang::syntax::ExpressionStatement
Expression in a statement position, e.g.
Definition: Nodes.h:332
clang::syntax::IfStatement
if (cond) <then-statement> else <else-statement> FIXME: add condition that models 'expression or vari...
Definition: Nodes.h:267
clang::tok::TokenKind
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition: TokenKinds.h:25
clang::syntax::TokenBufferTokenManager::getToken
const syntax::Token * getToken(Key I) const
Definition: TokenBufferTokenManager.h:40
Tokens.h
clang::syntax::CallArguments
Models arguments of a function call.
Definition: Nodes.h:146
clang::syntax::TokenManager::Key
uintptr_t Key
A key to identify a specific token.
Definition: TokenManager.h:40
clang::syntax::Arena
A memory arena for syntax trees.
Definition: Tree.h:36
clang::tok::getKeywordSpelling
const char * getKeywordSpelling(TokenKind Kind) LLVM_READNONE
Determines the spelling of simple keyword and contextual keyword tokens like 'int' and 'dynamic_cast'...
Definition: TokenKinds.cpp:40
llvm::ArrayRef
Definition: LLVM.h:34
clang::syntax::TypeAliasDeclaration
using <name> = <type>
Definition: Nodes.h:468
clang::syntax::Arena::getAllocator
llvm::BumpPtrAllocator & getAllocator()
Definition: Tree.h:38
clang::syntax::LinkageSpecificationDeclaration
extern <string-literal> declaration extern <string-literal> { <decls> }
Definition: Nodes.h:386
Tree.h
clang::syntax::SimpleDeclarator
A top-level declarator without parentheses.
Definition: Nodes.h:494
clang::syntax::FactoryImpl
Exposes private syntax tree APIs required to implement node synthesis.
Definition: Synthesis.cpp:18
clang::syntax::Leaf
A leaf node points to a single token.
Definition: Tree.h:132
clang::ObjCPropertyAttribute::Kind
Kind
Definition: DeclObjCCommon.h:22
clang::syntax::FactoryImpl::appendChildLowLevel
static void appendChildLowLevel(syntax::Tree *T, syntax::Node *Child, syntax::NodeRole R)
Definition: Synthesis.cpp:26
clang::syntax::CaseStatement
case : <body>
Definition: Nodes.h:247
clang::syntax::MemberPointer
Member pointer inside a declarator E.g.
Definition: Nodes.h:572
clang::syntax::NodeRole
NodeRole
A relation between a parent and child node, e.g.
Definition: Nodes.h:54
clang::syntax::FactoryImpl::setCanModify
static void setCanModify(syntax::Node *N)
Definition: Synthesis.cpp:20
clang::syntax::createTree
syntax::Tree * createTree(syntax::Arena &A, ArrayRef< std::pair< syntax::Node *, syntax::NodeRole >> Children, syntax::NodeKind K)
Creates the concrete syntax node according to the specified NodeKind K.
Definition: Synthesis.cpp:204
clang
Definition: CalledOnceCheck.h:17
clang::syntax::NodeKind
NodeKind
A kind of a syntax node, used for implementing casts.
Definition: Nodes.h:32
clang::syntax::ExplicitTemplateInstantiation
template <declaration> Examples: template struct X<int> template void foo<int>() template int var<dou...
Definition: Nodes.h:427
clang::syntax::TokenBufferTokenManager
A TokenBuffer-powered token manager.
Definition: TokenBufferTokenManager.h:20
clang::syntax::PrefixUnaryOperatorExpression
<operator> <operand>
Definition: Nodes.h:172
clang::syntax::TrailingReturnType
Trailing return type after the parameter list, including the arrow token.
Definition: Nodes.h:527
clang::syntax::ReturnStatement
return <expr>; return;
Definition: Nodes.h:313
clang::syntax::PostfixUnaryOperatorExpression
<operand> <operator>
Definition: Nodes.h:184
clang::syntax::UnknownDeclaration
Declaration of an unknown kind, e.g. not yet supported in syntax trees.
Definition: Nodes.h:361
clang::syntax::EmptyDeclaration
A semicolon in the top-level context. Does not declare anything.
Definition: Nodes.h:368
clang::syntax::ParametersAndQualifiers
Parameter list for a function type and a trailing return type, if the function has one.
Definition: Nodes.h:560
clang::syntax::ParameterDeclarationList
Models a parameter-declaration-list which appears within parameters-and-qualifiers.
Definition: Nodes.h:540
clang::syntax::Node::assertInvariants
void assertInvariants() const
Asserts invariants on this node of the tree and its immediate children.
Definition: Tree.cpp:239
clang::syntax::DefaultStatement
default: <body>
Definition: Nodes.h:257
clang::syntax::WhileStatement
while (<cond>) <body>
Definition: Nodes.h:287
clang::syntax::UsingDeclaration
using <scope>::<name> using typename <scope>::<name>
Definition: Nodes.h:461
clang::syntax::UnknownStatement
A statement of an unknown kind, i.e.
Definition: Nodes.h:217
clang::syntax::CompoundStatement
{ statement1; statement2; … }
Definition: Nodes.h:340
clang::syntax::SwitchStatement
switch (<cond>) <body>
Definition: Nodes.h:238
clang::syntax::TokenBufferTokenManager::getText
llvm::StringRef getText(Key I) const override
Definition: TokenBufferTokenManager.h:29
clang::syntax::NestedNameSpecifier
Models a nested-name-specifier.
Definition: Nodes.h:116