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