xref: /freebsd/contrib/llvm-project/clang/lib/Tooling/Syntax/Synthesis.cpp (revision fcaf7f8644a9988098ac6be2165bce3ea4786e91)
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 
14 using namespace clang;
15 
16 /// Exposes private syntax tree APIs required to implement node synthesis.
17 /// Should not be used for anything else.
18 class clang::syntax::FactoryImpl {
19 public:
setCanModify(syntax::Node * N)20   static void setCanModify(syntax::Node *N) { N->CanModify = true; }
21 
prependChildLowLevel(syntax::Tree * T,syntax::Node * Child,syntax::NodeRole R)22   static void prependChildLowLevel(syntax::Tree *T, syntax::Node *Child,
23                                    syntax::NodeRole R) {
24     T->prependChildLowLevel(Child, R);
25   }
appendChildLowLevel(syntax::Tree * T,syntax::Node * Child,syntax::NodeRole R)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>>
lexBuffer(TokenBufferTokenManager & TBTM,std::unique_ptr<llvm::MemoryBuffer> Buffer)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.
createLeaf(syntax::Arena & A,TokenBufferTokenManager & TBTM,tok::TokenKind K,StringRef Spelling)40 syntax::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 
createLeaf(syntax::Arena & A,TokenBufferTokenManager & TBTM,tok::TokenKind K)57 syntax::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 
68 namespace {
69 // Allocates the concrete syntax `Tree` according to its `NodeKind`.
allocateTree(syntax::Arena & A,syntax::NodeKind Kind)70 syntax::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 
createTree(syntax::Arena & A,ArrayRef<std::pair<syntax::Node *,syntax::NodeRole>> Children,syntax::NodeKind K)204 syntax::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 
deepCopyExpandingMacros(syntax::Arena & A,TokenBufferTokenManager & TBTM,const syntax::Node * N)217 syntax::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 
createEmptyStatement(syntax::Arena & A,TokenBufferTokenManager & TBTM)235 syntax::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