clang  14.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 //===----------------------------------------------------------------------===//
11 
12 using namespace clang;
13 
14 /// Exposes private syntax tree APIs required to implement node synthesis.
15 /// Should not be used for anything else.
17 public:
18  static void setCanModify(syntax::Node *N) { N->CanModify = true; }
19 
21  syntax::NodeRole R) {
22  T->prependChildLowLevel(Child, R);
23  }
25  syntax::NodeRole R) {
26  T->appendChildLowLevel(Child, R);
27  }
28 
29  static std::pair<FileID, ArrayRef<Token>>
30  lexBuffer(syntax::Arena &A, std::unique_ptr<llvm::MemoryBuffer> Buffer) {
31  return A.lexBuffer(std::move(Buffer));
32  }
33 };
34 
35 // FIXME: `createLeaf` is based on `syntax::tokenize` internally, as such it
36 // doesn't support digraphs or line continuations.
38  StringRef Spelling) {
39  auto Tokens =
40  FactoryImpl::lexBuffer(A, llvm::MemoryBuffer::getMemBufferCopy(Spelling))
41  .second;
42  assert(Tokens.size() == 1);
43  assert(Tokens.front().kind() == K &&
44  "spelling is not lexed into the expected kind of token");
45 
46  auto *Leaf = new (A.getAllocator()) syntax::Leaf(Tokens.begin());
49  return Leaf;
50 }
51 
53  const auto *Spelling = tok::getPunctuatorSpelling(K);
54  if (!Spelling)
55  Spelling = tok::getKeywordSpelling(K);
56  assert(Spelling &&
57  "Cannot infer the spelling of the token from its token kind.");
58  return createLeaf(A, K, Spelling);
59 }
60 
61 namespace {
62 // Allocates the concrete syntax `Tree` according to its `NodeKind`.
64  switch (Kind) {
65  case syntax::NodeKind::Leaf:
66  assert(false);
67  break;
68  case syntax::NodeKind::TranslationUnit:
69  return new (A.getAllocator()) syntax::TranslationUnit;
70  case syntax::NodeKind::UnknownExpression:
71  return new (A.getAllocator()) syntax::UnknownExpression;
72  case syntax::NodeKind::ParenExpression:
73  return new (A.getAllocator()) syntax::ParenExpression;
74  case syntax::NodeKind::ThisExpression:
75  return new (A.getAllocator()) syntax::ThisExpression;
76  case syntax::NodeKind::IntegerLiteralExpression:
77  return new (A.getAllocator()) syntax::IntegerLiteralExpression;
78  case syntax::NodeKind::CharacterLiteralExpression:
79  return new (A.getAllocator()) syntax::CharacterLiteralExpression;
80  case syntax::NodeKind::FloatingLiteralExpression:
81  return new (A.getAllocator()) syntax::FloatingLiteralExpression;
82  case syntax::NodeKind::StringLiteralExpression:
83  return new (A.getAllocator()) syntax::StringLiteralExpression;
84  case syntax::NodeKind::BoolLiteralExpression:
85  return new (A.getAllocator()) syntax::BoolLiteralExpression;
86  case syntax::NodeKind::CxxNullPtrExpression:
87  return new (A.getAllocator()) syntax::CxxNullPtrExpression;
88  case syntax::NodeKind::IntegerUserDefinedLiteralExpression:
89  return new (A.getAllocator()) syntax::IntegerUserDefinedLiteralExpression;
90  case syntax::NodeKind::FloatUserDefinedLiteralExpression:
91  return new (A.getAllocator()) syntax::FloatUserDefinedLiteralExpression;
92  case syntax::NodeKind::CharUserDefinedLiteralExpression:
93  return new (A.getAllocator()) syntax::CharUserDefinedLiteralExpression;
94  case syntax::NodeKind::StringUserDefinedLiteralExpression:
95  return new (A.getAllocator()) syntax::StringUserDefinedLiteralExpression;
96  case syntax::NodeKind::PrefixUnaryOperatorExpression:
98  case syntax::NodeKind::PostfixUnaryOperatorExpression:
100  case syntax::NodeKind::BinaryOperatorExpression:
102  case syntax::NodeKind::UnqualifiedId:
103  return new (A.getAllocator()) syntax::UnqualifiedId;
104  case syntax::NodeKind::IdExpression:
105  return new (A.getAllocator()) syntax::IdExpression;
106  case syntax::NodeKind::CallExpression:
107  return new (A.getAllocator()) syntax::CallExpression;
108  case syntax::NodeKind::UnknownStatement:
109  return new (A.getAllocator()) syntax::UnknownStatement;
110  case syntax::NodeKind::DeclarationStatement:
112  case syntax::NodeKind::EmptyStatement:
113  return new (A.getAllocator()) syntax::EmptyStatement;
114  case syntax::NodeKind::SwitchStatement:
115  return new (A.getAllocator()) syntax::SwitchStatement;
116  case syntax::NodeKind::CaseStatement:
117  return new (A.getAllocator()) syntax::CaseStatement;
118  case syntax::NodeKind::DefaultStatement:
119  return new (A.getAllocator()) syntax::DefaultStatement;
120  case syntax::NodeKind::IfStatement:
121  return new (A.getAllocator()) syntax::IfStatement;
122  case syntax::NodeKind::ForStatement:
123  return new (A.getAllocator()) syntax::ForStatement;
124  case syntax::NodeKind::WhileStatement:
125  return new (A.getAllocator()) syntax::WhileStatement;
126  case syntax::NodeKind::ContinueStatement:
127  return new (A.getAllocator()) syntax::ContinueStatement;
128  case syntax::NodeKind::BreakStatement:
129  return new (A.getAllocator()) syntax::BreakStatement;
130  case syntax::NodeKind::ReturnStatement:
131  return new (A.getAllocator()) syntax::ReturnStatement;
132  case syntax::NodeKind::RangeBasedForStatement:
134  case syntax::NodeKind::ExpressionStatement:
135  return new (A.getAllocator()) syntax::ExpressionStatement;
136  case syntax::NodeKind::CompoundStatement:
137  return new (A.getAllocator()) syntax::CompoundStatement;
138  case syntax::NodeKind::UnknownDeclaration:
139  return new (A.getAllocator()) syntax::UnknownDeclaration;
140  case syntax::NodeKind::EmptyDeclaration:
141  return new (A.getAllocator()) syntax::EmptyDeclaration;
142  case syntax::NodeKind::StaticAssertDeclaration:
144  case syntax::NodeKind::LinkageSpecificationDeclaration:
146  case syntax::NodeKind::SimpleDeclaration:
147  return new (A.getAllocator()) syntax::SimpleDeclaration;
148  case syntax::NodeKind::TemplateDeclaration:
149  return new (A.getAllocator()) syntax::TemplateDeclaration;
150  case syntax::NodeKind::ExplicitTemplateInstantiation:
152  case syntax::NodeKind::NamespaceDefinition:
153  return new (A.getAllocator()) syntax::NamespaceDefinition;
154  case syntax::NodeKind::NamespaceAliasDefinition:
156  case syntax::NodeKind::UsingNamespaceDirective:
158  case syntax::NodeKind::UsingDeclaration:
159  return new (A.getAllocator()) syntax::UsingDeclaration;
160  case syntax::NodeKind::TypeAliasDeclaration:
162  case syntax::NodeKind::SimpleDeclarator:
163  return new (A.getAllocator()) syntax::SimpleDeclarator;
164  case syntax::NodeKind::ParenDeclarator:
165  return new (A.getAllocator()) syntax::ParenDeclarator;
166  case syntax::NodeKind::ArraySubscript:
167  return new (A.getAllocator()) syntax::ArraySubscript;
168  case syntax::NodeKind::TrailingReturnType:
169  return new (A.getAllocator()) syntax::TrailingReturnType;
170  case syntax::NodeKind::ParametersAndQualifiers:
172  case syntax::NodeKind::MemberPointer:
173  return new (A.getAllocator()) syntax::MemberPointer;
174  case syntax::NodeKind::GlobalNameSpecifier:
175  return new (A.getAllocator()) syntax::GlobalNameSpecifier;
176  case syntax::NodeKind::DecltypeNameSpecifier:
177  return new (A.getAllocator()) syntax::DecltypeNameSpecifier;
178  case syntax::NodeKind::IdentifierNameSpecifier:
179  return new (A.getAllocator()) syntax::IdentifierNameSpecifier;
180  case syntax::NodeKind::SimpleTemplateNameSpecifier:
181  return new (A.getAllocator()) syntax::SimpleTemplateNameSpecifier;
182  case syntax::NodeKind::NestedNameSpecifier:
183  return new (A.getAllocator()) syntax::NestedNameSpecifier;
184  case syntax::NodeKind::MemberExpression:
185  return new (A.getAllocator()) syntax::MemberExpression;
186  case syntax::NodeKind::CallArguments:
187  return new (A.getAllocator()) syntax::CallArguments;
188  case syntax::NodeKind::ParameterDeclarationList:
190  case syntax::NodeKind::DeclaratorList:
191  return new (A.getAllocator()) syntax::DeclaratorList;
192  }
193  llvm_unreachable("unknown node kind");
194 }
195 } // namespace
196 
198  syntax::Arena &A,
199  ArrayRef<std::pair<syntax::Node *, syntax::NodeRole>> Children,
200  syntax::NodeKind K) {
201  auto *T = allocateTree(A, K);
202  FactoryImpl::setCanModify(T);
203  for (const auto &Child : Children)
204  FactoryImpl::appendChildLowLevel(T, Child.first, Child.second);
205 
206  T->assertInvariants();
207  return T;
208 }
209 
211  const syntax::Node *N) {
212  if (const auto *L = dyn_cast<syntax::Leaf>(N))
213  // `L->getToken()` gives us the expanded token, thus we implicitly expand
214  // any macros here.
215  return createLeaf(A, L->getToken()->kind(),
216  L->getToken()->text(A.getSourceManager()));
217 
218  const auto *T = cast<syntax::Tree>(N);
219  std::vector<std::pair<syntax::Node *, syntax::NodeRole>> Children;
220  for (const auto *Child = T->getFirstChild(); Child;
221  Child = Child->getNextSibling())
222  Children.push_back({deepCopyExpandingMacros(A, Child), Child->getRole()});
223 
224  return createTree(A, Children, N->getKind());
225 }
226 
228  return cast<EmptyStatement>(
229  createTree(A, {{createLeaf(A, tok::semi), NodeRole::Unknown}},
230  NodeKind::EmptyStatement));
231 }
clang::syntax::TemplateDeclaration
template <template-parameters> <declaration>
Definition: Nodes.h:419
clang::syntax::FactoryImpl::prependChildLowLevel
static void prependChildLowLevel(syntax::Tree *T, syntax::Node *Child, syntax::NodeRole R)
Definition: Synthesis.cpp:20
clang::syntax::ForStatement
for (<init>; <cond>; <increment>) <body>
Definition: Nodes.h:283
clang::syntax::NamespaceDefinition
namespace <name> { <decls> }
Definition: Nodes.h:443
clang::syntax::RangeBasedForStatement
for (<decl> : <init>) <body>
Definition: Nodes.h:327
clang::syntax::UnknownExpression
An expression of an unknown kind, i.e.
Definition: Nodes.h:140
clang::syntax::ContinueStatement
continue;
Definition: Nodes.h:301
clang::syntax::Node
A node in a syntax tree.
Definition: Tree.h:80
clang::syntax::DeclaratorList
Definition: Nodes.h:398
clang::syntax::ParenDeclarator
Declarator inside parentheses.
Definition: Nodes.h:508
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:450
BuildTree.h
clang::syntax::UnqualifiedId
Models an unqualified-id.
Definition: Nodes.h:132
clang::syntax::UsingNamespaceDirective
using namespace <name>
Definition: Nodes.h:458
clang::syntax::createLeaf
syntax::Leaf * createLeaf(syntax::Arena &A, tok::TokenKind K, StringRef Spelling)
Create Leaf from token with Spelling and assert it has the desired TokenKind.
Definition: Synthesis.cpp:37
clang::syntax::FactoryImpl::lexBuffer
static std::pair< FileID, ArrayRef< Token > > lexBuffer(syntax::Arena &A, std::unique_ptr< llvm::MemoryBuffer > Buffer)
Definition: Synthesis.cpp:30
TokenKinds.h
clang::syntax::StaticAssertDeclaration
static_assert(<condition>, <message>) static_assert(<condition>)
Definition: Nodes.h:381
clang::prec::Unknown
@ Unknown
Definition: OperatorPrecedence.h:27
clang::syntax::BreakStatement
break;
Definition: Nodes.h:309
clang::syntax::Tree
A node that has children and represents a syntactic language construct.
Definition: Tree.h:169
clang::syntax::ArraySubscript
Array size specified inside a declarator.
Definition: Nodes.h:520
clang::syntax::BinaryOperatorExpression
<lhs> <operator> <rhs>
Definition: Nodes.h:203
clang::syntax::SimpleDeclaration
Groups multiple declarators (e.g.
Definition: Nodes.h:410
clang::syntax::DeclarationStatement
E.g. 'int a, b = 10;'.
Definition: Nodes.h:229
clang::syntax::Node::getKind
NodeKind getKind() const
Definition: Tree.h:96
clang::syntax::EmptyStatement
The no-op statement, i.e. ';'.
Definition: Nodes.h:236
clang::syntax::ExpressionStatement
Expression in a statement position, e.g.
Definition: Nodes.h:337
clang::syntax::IfStatement
if (cond) <then-statement> else <else-statement> FIXME: add condition that models 'expression or vari...
Definition: Nodes.h:272
clang::tok::TokenKind
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition: TokenKinds.h:25
clang::syntax::CallArguments
Models arguments of a function call.
Definition: Nodes.h:151
clang::syntax::Arena
A memory arena for syntax trees.
Definition: Tree.h:41
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:473
clang::syntax::Arena::getAllocator
llvm::BumpPtrAllocator & getAllocator()
Definition: Tree.h:50
clang::syntax::LinkageSpecificationDeclaration
extern <string-literal> declaration extern <string-literal> { <decls> }
Definition: Nodes.h:391
clang::syntax::createEmptyStatement
syntax::EmptyStatement * createEmptyStatement(syntax::Arena &A)
Definition: Synthesis.cpp:227
Tree.h
clang::syntax::SimpleDeclarator
A top-level declarator without parentheses.
Definition: Nodes.h:499
clang::syntax::FactoryImpl
Exposes private syntax tree APIs required to implement node synthesis.
Definition: Synthesis.cpp:16
clang::syntax::Leaf
A leaf node points to a single token inside the expanded token stream.
Definition: Tree.h:157
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:24
clang::syntax::CaseStatement
case : <body>
Definition: Nodes.h:252
clang::syntax::MemberPointer
Member pointer inside a declarator E.g.
Definition: Nodes.h:577
clang::syntax::NodeRole
NodeRole
A relation between a parent and child node, e.g.
Definition: Nodes.h:59
clang::syntax::FactoryImpl::setCanModify
static void setCanModify(syntax::Node *N)
Definition: Synthesis.cpp:18
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:197
clang
Definition: CalledOnceCheck.h:17
clang::syntax::NodeKind
NodeKind
A kind of a syntax node, used for implementing casts.
Definition: Nodes.h:37
clang::syntax::ExplicitTemplateInstantiation
template <declaration> Examples: template struct X<int> template void foo<int>() template int var<dou...
Definition: Nodes.h:432
clang::syntax::PrefixUnaryOperatorExpression
<operator> <operand>
Definition: Nodes.h:177
clang::syntax::TrailingReturnType
Trailing return type after the parameter list, including the arrow token.
Definition: Nodes.h:532
clang::syntax::ReturnStatement
return <expr>; return;
Definition: Nodes.h:318
clang::syntax::PostfixUnaryOperatorExpression
<operand> <operator>
Definition: Nodes.h:189
clang::syntax::UnknownDeclaration
Declaration of an unknown kind, e.g. not yet supported in syntax trees.
Definition: Nodes.h:366
clang::syntax::EmptyDeclaration
A semicolon in the top-level context. Does not declare anything.
Definition: Nodes.h:373
clang::syntax::ParametersAndQualifiers
Parameter list for a function type and a trailing return type, if the function has one.
Definition: Nodes.h:565
clang::syntax::ParameterDeclarationList
Models a parameter-declaration-list which appears within parameters-and-qualifiers.
Definition: Nodes.h:545
clang::syntax::Node::assertInvariants
void assertInvariants() const
Asserts invariants on this node of the tree and its immediate children.
Definition: Tree.cpp:269
clang::syntax::DefaultStatement
default: <body>
Definition: Nodes.h:262
clang::syntax::WhileStatement
while (<cond>) <body>
Definition: Nodes.h:292
clang::syntax::UsingDeclaration
using <scope>::<name> using typename <scope>::<name>
Definition: Nodes.h:466
clang::syntax::UnknownStatement
A statement of an unknown kind, i.e.
Definition: Nodes.h:222
clang::syntax::Arena::getSourceManager
const SourceManager & getSourceManager() const
Definition: Tree.h:46
clang::syntax::CompoundStatement
{ statement1; statement2; … }
Definition: Nodes.h:345
clang::syntax::deepCopyExpandingMacros
syntax::Node * deepCopyExpandingMacros(syntax::Arena &A, const syntax::Node *N)
Creates a completely independent copy of N with its macros expanded.
Definition: Synthesis.cpp:210
clang::syntax::SwitchStatement
switch (<cond>) <body>
Definition: Nodes.h:243
clang::syntax::NestedNameSpecifier
Models a nested-name-specifier.
Definition: Nodes.h:121