/src/solidity/libsolidity/ast/AST.cpp
Line | Count | Source |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | /** |
19 | | * @author Christian <c@ethdev.com> |
20 | | * @date 2014 |
21 | | * Solidity abstract syntax tree. |
22 | | */ |
23 | | |
24 | | #include <libsolidity/ast/AST.h> |
25 | | |
26 | | #include <libsolidity/ast/CallGraph.h> |
27 | | #include <libsolidity/ast/ASTVisitor.h> |
28 | | #include <libsolidity/ast/AST_accept.h> |
29 | | #include <libsolidity/ast/TypeProvider.h> |
30 | | #include <libsolutil/FunctionSelector.h> |
31 | | #include <libsolutil/Keccak256.h> |
32 | | |
33 | | #include <range/v3/range/conversion.hpp> |
34 | | #include <range/v3/view/tail.hpp> |
35 | | #include <range/v3/view/zip.hpp> |
36 | | |
37 | | #include <boost/algorithm/string.hpp> |
38 | | |
39 | | #include <functional> |
40 | | #include <utility> |
41 | | |
42 | | using namespace solidity; |
43 | | using namespace solidity::frontend; |
44 | | |
45 | | namespace |
46 | | { |
47 | | TryCatchClause const* findClause(std::vector<ASTPointer<TryCatchClause>> const& _clauses, std::optional<std::string> _errorName = {}) |
48 | 318 | { |
49 | 318 | for (auto const& clause: ranges::views::tail(_clauses)) |
50 | 318 | if (_errorName.has_value() ? clause->errorName() == _errorName : clause->errorName().empty()) |
51 | 106 | return clause.get(); |
52 | 212 | return nullptr; |
53 | 318 | } |
54 | | } |
55 | | |
56 | | ASTNode::ASTNode(std::int64_t _id, SourceLocation _location): |
57 | 2.18M | m_id(_id), |
58 | 2.18M | m_location(std::move(_location)) |
59 | 2.18M | { |
60 | 2.18M | } |
61 | | |
62 | | Declaration const* ASTNode::referencedDeclaration(Expression const& _expression) |
63 | 60.2k | { |
64 | 60.2k | if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_expression)) |
65 | 9.46k | return memberAccess->annotation().referencedDeclaration; |
66 | 50.8k | else if (auto const* identifierPath = dynamic_cast<IdentifierPath const*>(&_expression)) |
67 | 0 | return identifierPath->annotation().referencedDeclaration; |
68 | 50.8k | else if (auto const* identifier = dynamic_cast<Identifier const*>(&_expression)) |
69 | 20.2k | return identifier->annotation().referencedDeclaration; |
70 | 30.5k | else |
71 | 30.5k | return nullptr; |
72 | 60.2k | } |
73 | | |
74 | | FunctionDefinition const* ASTNode::resolveFunctionCall(FunctionCall const& _functionCall, ContractDefinition const* _mostDerivedContract) |
75 | 9.62k | { |
76 | 9.62k | auto const* functionDef = dynamic_cast<FunctionDefinition const*>( |
77 | 9.62k | ASTNode::referencedDeclaration(_functionCall.expression()) |
78 | 9.62k | ); |
79 | | |
80 | 9.62k | if (!functionDef) |
81 | 195 | return nullptr; |
82 | | |
83 | 9.43k | if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression())) |
84 | 259 | { |
85 | 259 | if (*memberAccess->annotation().requiredLookup == VirtualLookup::Super) |
86 | 54 | { |
87 | 54 | if (auto const typeType = dynamic_cast<TypeType const*>(memberAccess->expression().annotation().type)) |
88 | 54 | if (auto const contractType = dynamic_cast<ContractType const*>(typeType->actualType())) |
89 | 54 | { |
90 | 54 | solAssert(_mostDerivedContract, ""); |
91 | 54 | solAssert(contractType->isSuper(), ""); |
92 | 54 | ContractDefinition const* superContract = contractType->contractDefinition().superContract(*_mostDerivedContract); |
93 | | |
94 | 54 | return &functionDef->resolveVirtual( |
95 | 54 | *_mostDerivedContract, |
96 | 54 | superContract |
97 | 54 | ); |
98 | 54 | } |
99 | 54 | } |
100 | 205 | else |
101 | 259 | solAssert(*memberAccess->annotation().requiredLookup == VirtualLookup::Static, ""); |
102 | 259 | } |
103 | 9.17k | else if (auto const* identifier = dynamic_cast<Identifier const*>(&_functionCall.expression())) |
104 | 9.17k | { |
105 | 9.17k | solAssert(*identifier->annotation().requiredLookup == VirtualLookup::Virtual, ""); |
106 | 9.17k | if (functionDef->virtualSemantics()) |
107 | 84 | { |
108 | 84 | solAssert(_mostDerivedContract, ""); |
109 | 84 | return &functionDef->resolveVirtual(*_mostDerivedContract); |
110 | 84 | } |
111 | 9.17k | } |
112 | 0 | else |
113 | 9.17k | solAssert(false, ""); |
114 | | |
115 | 9.29k | return functionDef; |
116 | 9.43k | } |
117 | | |
118 | | ASTAnnotation& ASTNode::annotation() const |
119 | 180k | { |
120 | 180k | if (!m_annotation) |
121 | 94.3k | m_annotation = std::make_unique<ASTAnnotation>(); |
122 | 180k | return *m_annotation; |
123 | 180k | } |
124 | | |
125 | | SourceUnitAnnotation& SourceUnit::annotation() const |
126 | 495k | { |
127 | 495k | return initAnnotation<SourceUnitAnnotation>(); |
128 | 495k | } |
129 | | |
130 | | std::set<SourceUnit const*> SourceUnit::referencedSourceUnits(bool _recurse, std::set<SourceUnit const*> _skipList) const |
131 | 67.9k | { |
132 | 67.9k | std::set<SourceUnit const*> sourceUnits; |
133 | 67.9k | referencedSourceUnits(sourceUnits, _recurse, _skipList); |
134 | 67.9k | return sourceUnits; |
135 | 67.9k | } |
136 | | |
137 | | void SourceUnit::referencedSourceUnits(std::set<SourceUnit const*>& _referencedSourceUnits, bool _recurse, std::set<SourceUnit const*>& _skipList) const |
138 | 71.0k | { |
139 | 71.0k | for (ImportDirective const* importDirective: filteredNodes<ImportDirective>(nodes())) |
140 | 5.30k | { |
141 | 5.30k | auto const& sourceUnit = importDirective->annotation().sourceUnit; |
142 | 5.30k | auto [skipListIt, notOnSkipListYet] = _skipList.insert(sourceUnit); |
143 | 5.30k | if (notOnSkipListYet) |
144 | 3.07k | { |
145 | 3.07k | _referencedSourceUnits.insert(sourceUnit); |
146 | 3.07k | if (_recurse) |
147 | 3.07k | sourceUnit->referencedSourceUnits(_referencedSourceUnits, true, _skipList); |
148 | 3.07k | } |
149 | 5.30k | } |
150 | 71.0k | } |
151 | | |
152 | | ImportAnnotation& ImportDirective::annotation() const |
153 | 23.5k | { |
154 | 23.5k | return initAnnotation<ImportAnnotation>(); |
155 | 23.5k | } |
156 | | |
157 | | Type const* ImportDirective::type() const |
158 | 160 | { |
159 | 160 | solAssert(!!annotation().sourceUnit, ""); |
160 | 160 | return TypeProvider::module(*annotation().sourceUnit); |
161 | 160 | } |
162 | | |
163 | | bool ContractDefinition::derivesFrom(ContractDefinition const& _base) const |
164 | 16.2k | { |
165 | 16.2k | return util::contains(annotation().linearizedBaseContracts, &_base); |
166 | 16.2k | } |
167 | | |
168 | | std::map<util::FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions(bool _includeInheritedFunctions) const |
169 | 69.4k | { |
170 | 69.4k | auto exportedFunctionList = interfaceFunctionList(_includeInheritedFunctions); |
171 | | |
172 | 69.4k | std::map<util::FixedHash<4>, FunctionTypePointer> exportedFunctions; |
173 | 69.4k | for (auto const& it: exportedFunctionList) |
174 | 80.3k | exportedFunctions.insert(it); |
175 | | |
176 | 69.4k | solAssert( |
177 | 69.4k | exportedFunctionList.size() == exportedFunctions.size(), |
178 | 69.4k | "Hash collision at Function Definition Hash calculation" |
179 | 69.4k | ); |
180 | | |
181 | 69.4k | return exportedFunctions; |
182 | 69.4k | } |
183 | | |
184 | | FunctionDefinition const* ContractDefinition::constructor() const |
185 | 539k | { |
186 | 539k | for (FunctionDefinition const* f: definedFunctions()) |
187 | 506k | if (f->isConstructor()) |
188 | 76.9k | return f; |
189 | 462k | return nullptr; |
190 | 539k | } |
191 | | |
192 | | bool ContractDefinition::canBeDeployed() const |
193 | 102k | { |
194 | 102k | return !abstract() && !isInterface(); |
195 | 102k | } |
196 | | |
197 | | FunctionDefinition const* ContractDefinition::fallbackFunction() const |
198 | 85.9k | { |
199 | 85.9k | for (ContractDefinition const* contract: annotation().linearizedBaseContracts) |
200 | 97.2k | for (FunctionDefinition const* f: contract->definedFunctions()) |
201 | 131k | if (f->isFallback()) |
202 | 1.21k | return f; |
203 | 84.7k | return nullptr; |
204 | 85.9k | } |
205 | | |
206 | | FunctionDefinition const* ContractDefinition::receiveFunction() const |
207 | 64.2k | { |
208 | 64.2k | for (ContractDefinition const* contract: annotation().linearizedBaseContracts) |
209 | 70.8k | for (FunctionDefinition const* f: contract->definedFunctions()) |
210 | 106k | if (f->isReceive()) |
211 | 537 | return f; |
212 | 63.7k | return nullptr; |
213 | 64.2k | } |
214 | | |
215 | | std::vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents() const |
216 | 29.0k | { |
217 | 29.0k | return m_interfaceEvents.init([&]{ |
218 | 14.2k | std::set<std::string> eventsSeen; |
219 | 14.2k | std::vector<EventDefinition const*> interfaceEvents; |
220 | | |
221 | 14.2k | for (ContractDefinition const* contract: annotation().linearizedBaseContracts) |
222 | 15.8k | for (EventDefinition const* e: contract->events()) |
223 | 1.50k | { |
224 | | /// NOTE: this requires the "internal" version of an Event, |
225 | | /// though here internal strictly refers to visibility, |
226 | | /// and not to function encoding (jump vs. call) |
227 | 1.50k | FunctionType const* functionType = e->functionType(true); |
228 | 1.50k | solAssert(functionType, ""); |
229 | 1.50k | std::string eventSignature = functionType->externalSignature(); |
230 | 1.50k | if (eventsSeen.count(eventSignature) == 0) |
231 | 1.50k | { |
232 | 1.50k | eventsSeen.insert(eventSignature); |
233 | 1.50k | interfaceEvents.push_back(e); |
234 | 1.50k | } |
235 | 1.50k | } |
236 | 14.2k | return interfaceEvents; |
237 | 14.2k | }); |
238 | 29.0k | } |
239 | | |
240 | | std::vector<EventDefinition const*> const ContractDefinition::usedInterfaceEvents() const |
241 | 43.2k | { |
242 | 43.2k | solAssert(annotation().creationCallGraph.set(), ""); |
243 | | |
244 | 43.2k | return util::convertContainer<std::vector<EventDefinition const*>>( |
245 | 43.2k | (*annotation().creationCallGraph)->emittedEvents + |
246 | 43.2k | (*annotation().deployedCallGraph)->emittedEvents |
247 | 43.2k | ); |
248 | 43.2k | } |
249 | | |
250 | | std::vector<EventDefinition const*> ContractDefinition::interfaceEvents(bool _requireCallGraph) const |
251 | 14.2k | { |
252 | 14.2k | std::set<EventDefinition const*, CompareByID> result; |
253 | 14.2k | for (ContractDefinition const* contract: annotation().linearizedBaseContracts) |
254 | 15.8k | result += contract->events(); |
255 | 14.2k | solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set()); |
256 | 14.2k | if (_requireCallGraph) |
257 | 14.2k | solAssert(annotation().creationCallGraph.set()); |
258 | 14.2k | if (annotation().creationCallGraph.set()) |
259 | 14.2k | result += usedInterfaceEvents(); |
260 | | // We could filter out all events that do not have an external interface |
261 | | // if _requireCallGraph is false. |
262 | 14.2k | return util::convertContainer<std::vector<EventDefinition const*>>(std::move(result)); |
263 | 14.2k | } |
264 | | |
265 | | std::vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const |
266 | 58.0k | { |
267 | 58.0k | std::set<ErrorDefinition const*, CompareByID> result; |
268 | 58.0k | for (ContractDefinition const* contract: annotation().linearizedBaseContracts) |
269 | 64.7k | result += filteredNodes<ErrorDefinition>(contract->m_subNodes); |
270 | 58.0k | solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set(), ""); |
271 | 58.0k | if (_requireCallGraph) |
272 | 58.0k | solAssert(annotation().creationCallGraph.set(), ""); |
273 | 58.0k | if (annotation().creationCallGraph.set()) |
274 | 58.0k | result += |
275 | 58.0k | (*annotation().creationCallGraph)->usedErrors + |
276 | 58.0k | (*annotation().deployedCallGraph)->usedErrors; |
277 | 58.0k | return util::convertContainer<std::vector<ErrorDefinition const*>>(std::move(result)); |
278 | 58.0k | } |
279 | | |
280 | | std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::interfaceFunctionList(bool _includeInheritedFunctions) const |
281 | 106k | { |
282 | 106k | return m_interfaceFunctionList[_includeInheritedFunctions].init([&]{ |
283 | 21.6k | std::set<std::string> signaturesSeen; |
284 | 21.6k | std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>> interfaceFunctionList; |
285 | | |
286 | 21.6k | for (ContractDefinition const* contract: annotation().linearizedBaseContracts) |
287 | 26.5k | { |
288 | 26.5k | if (_includeInheritedFunctions == false && contract != this) |
289 | 0 | continue; |
290 | 26.5k | std::vector<FunctionTypePointer> functions; |
291 | 26.5k | for (FunctionDefinition const* f: contract->definedFunctions()) |
292 | 25.0k | if (f->isPartOfExternalInterface()) |
293 | 19.3k | functions.push_back(TypeProvider::function(*f, FunctionType::Kind::External)); |
294 | 26.5k | for (VariableDeclaration const* v: contract->stateVariables()) |
295 | 11.2k | if (v->isPartOfExternalInterface()) |
296 | 4.22k | functions.push_back(TypeProvider::function(*v)); |
297 | 26.5k | for (FunctionTypePointer const& fun: functions) |
298 | 23.5k | { |
299 | 23.5k | if (!fun->interfaceFunctionType()) |
300 | | // Fails hopefully because we already registered the error |
301 | 37 | continue; |
302 | 23.5k | std::string functionSignature = fun->externalSignature(); |
303 | 23.5k | if (signaturesSeen.count(functionSignature) == 0) |
304 | 21.1k | { |
305 | 21.1k | signaturesSeen.insert(functionSignature); |
306 | 21.1k | interfaceFunctionList.emplace_back(util::selectorFromSignatureH32(functionSignature), fun); |
307 | 21.1k | } |
308 | 23.5k | } |
309 | 26.5k | } |
310 | | |
311 | 21.6k | return interfaceFunctionList; |
312 | 21.6k | }); |
313 | 106k | } |
314 | | |
315 | | uint32_t ContractDefinition::interfaceId() const |
316 | 18 | { |
317 | 18 | uint32_t result{0}; |
318 | 18 | for (auto const& function: interfaceFunctionList(false)) |
319 | 33 | result ^= fromBigEndian<uint32_t>(function.first.ref()); |
320 | 18 | return result; |
321 | 18 | } |
322 | | |
323 | | Type const* ContractDefinition::type() const |
324 | 1.17k | { |
325 | 1.17k | return TypeProvider::typeType(TypeProvider::contract(*this)); |
326 | 1.17k | } |
327 | | |
328 | | ContractDefinitionAnnotation& ContractDefinition::annotation() const |
329 | 3.95M | { |
330 | 3.95M | return initAnnotation<ContractDefinitionAnnotation>(); |
331 | 3.95M | } |
332 | | |
333 | | ContractDefinition const* ContractDefinition::superContract(ContractDefinition const& _mostDerivedContract) const |
334 | 11.4k | { |
335 | 11.4k | auto const& hierarchy = _mostDerivedContract.annotation().linearizedBaseContracts; |
336 | 11.4k | auto it = find(hierarchy.begin(), hierarchy.end(), this); |
337 | 11.4k | solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy."); |
338 | 11.4k | ++it; |
339 | 11.4k | if (it == hierarchy.end()) |
340 | 9.79k | return nullptr; |
341 | 1.68k | else |
342 | 1.68k | { |
343 | 1.68k | solAssert(*it != this, ""); |
344 | 1.68k | return *it; |
345 | 1.68k | } |
346 | 11.4k | } |
347 | | |
348 | | FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition const& _mostDerivedContract) const |
349 | 10.8k | { |
350 | 10.8k | ContractDefinition const* next = superContract(_mostDerivedContract); |
351 | 10.8k | if (next == nullptr) |
352 | 9.79k | return nullptr; |
353 | 1.04k | for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts) |
354 | 2.72k | if (c == next || next == nullptr) |
355 | 1.46k | { |
356 | 1.46k | if (c->constructor()) |
357 | 382 | return c->constructor(); |
358 | 1.08k | next = nullptr; |
359 | 1.08k | } |
360 | | |
361 | 664 | return nullptr; |
362 | 1.04k | } |
363 | | |
364 | | std::multimap<std::string, FunctionDefinition const*> const& ContractDefinition::definedFunctionsByName() const |
365 | 1.54k | { |
366 | 1.54k | return m_definedFunctionsByName.init([&]{ |
367 | 129 | std::multimap<std::string, FunctionDefinition const*> result; |
368 | 129 | for (FunctionDefinition const* fun: filteredNodes<FunctionDefinition>(m_subNodes)) |
369 | 188 | result.insert({fun->name(), fun}); |
370 | 129 | return result; |
371 | 129 | }); |
372 | 1.54k | } |
373 | | |
374 | | StorageLayoutSpecifier::StorageLayoutSpecifier( |
375 | | int64_t _id, |
376 | | SourceLocation const& _location, |
377 | | ASTPointer<Expression> _baseSlotExpression |
378 | | ): |
379 | 35 | ASTNode(_id, _location), |
380 | 35 | m_baseSlotExpression(_baseSlotExpression) |
381 | 35 | { |
382 | 35 | solAssert(m_baseSlotExpression); |
383 | 35 | solAssert(_location.contains(m_baseSlotExpression->location())); |
384 | 35 | } |
385 | | |
386 | | StorageLayoutSpecifierAnnotation& StorageLayoutSpecifier::annotation() const |
387 | 0 | { |
388 | 0 | return initAnnotation<StorageLayoutSpecifierAnnotation>(); |
389 | 0 | } |
390 | | |
391 | | TypeNameAnnotation& TypeName::annotation() const |
392 | 822k | { |
393 | 822k | return initAnnotation<TypeNameAnnotation>(); |
394 | 822k | } |
395 | | |
396 | | Type const* UserDefinedValueTypeDefinition::type() const |
397 | 412 | { |
398 | 412 | solAssert(m_underlyingType->annotation().type, ""); |
399 | 412 | return TypeProvider::typeType(TypeProvider::userDefinedValueType(*this)); |
400 | 412 | } |
401 | | |
402 | | TypeDeclarationAnnotation& UserDefinedValueTypeDefinition::annotation() const |
403 | 16.9k | { |
404 | 16.9k | return initAnnotation<TypeDeclarationAnnotation>(); |
405 | 16.9k | } |
406 | | |
407 | | std::vector<std::pair<ASTPointer<IdentifierPath>, std::optional<Token>>> UsingForDirective::functionsAndOperators() const |
408 | 1.78k | { |
409 | 1.78k | return ranges::zip_view(m_functionsOrLibrary, m_operators) | ranges::to<std::vector>; |
410 | 1.78k | } |
411 | | |
412 | | Type const* StructDefinition::type() const |
413 | 265 | { |
414 | 265 | solAssert(annotation().recursive.has_value(), "Requested struct type before DeclarationTypeChecker."); |
415 | 265 | return TypeProvider::typeType(TypeProvider::structType(*this, DataLocation::Storage)); |
416 | 265 | } |
417 | | |
418 | | StructDeclarationAnnotation& StructDefinition::annotation() const |
419 | 11.0M | { |
420 | 11.0M | return initAnnotation<StructDeclarationAnnotation>(); |
421 | 11.0M | } |
422 | | |
423 | | Type const* EnumValue::type() const |
424 | 0 | { |
425 | 0 | auto parentDef = dynamic_cast<EnumDefinition const*>(scope()); |
426 | 0 | solAssert(parentDef, "Enclosing Scope of EnumValue was not set"); |
427 | 0 | return TypeProvider::enumType(*parentDef); |
428 | 0 | } |
429 | | |
430 | | Type const* EnumDefinition::type() const |
431 | 176 | { |
432 | 176 | return TypeProvider::typeType(TypeProvider::enumType(*this)); |
433 | 176 | } |
434 | | |
435 | | TypeDeclarationAnnotation& EnumDefinition::annotation() const |
436 | 8.77k | { |
437 | 8.77k | return initAnnotation<TypeDeclarationAnnotation>(); |
438 | 8.77k | } |
439 | | |
440 | | bool FunctionDefinition::libraryFunction() const |
441 | 54.3k | { |
442 | 54.3k | if (auto const* contractDef = dynamic_cast<ContractDefinition const*>(scope())) |
443 | 52.8k | return contractDef->isLibrary(); |
444 | 1.49k | return false; |
445 | 54.3k | } |
446 | | |
447 | | Visibility FunctionDefinition::defaultVisibility() const |
448 | 13.2k | { |
449 | 13.2k | solAssert(!isConstructor(), ""); |
450 | 13.2k | return isFree() ? Visibility::Internal : Declaration::defaultVisibility(); |
451 | 13.2k | } |
452 | | |
453 | | FunctionTypePointer FunctionDefinition::functionType(bool _internal) const |
454 | 15.7k | { |
455 | 15.7k | if (_internal) |
456 | 1.37k | { |
457 | 1.37k | switch (visibility()) |
458 | 1.37k | { |
459 | 0 | case Visibility::Default: |
460 | 0 | solAssert(false, "visibility() should not return Default"); |
461 | 8 | case Visibility::Private: |
462 | 1.21k | case Visibility::Internal: |
463 | 1.37k | case Visibility::Public: |
464 | 1.37k | return TypeProvider::function(*this, FunctionType::Kind::Internal); |
465 | 0 | case Visibility::External: |
466 | 0 | return {}; |
467 | 1.37k | } |
468 | 1.37k | } |
469 | 14.3k | else |
470 | 14.3k | { |
471 | 14.3k | switch (visibility()) |
472 | 14.3k | { |
473 | 0 | case Visibility::Default: |
474 | 0 | solAssert(false, "visibility() should not return Default"); |
475 | 7 | case Visibility::Private: |
476 | 719 | case Visibility::Internal: |
477 | 719 | return {}; |
478 | 10.6k | case Visibility::Public: |
479 | 13.6k | case Visibility::External: |
480 | 13.6k | return TypeProvider::function(*this, FunctionType::Kind::External); |
481 | 14.3k | } |
482 | 14.3k | } |
483 | | |
484 | | // To make the compiler happy |
485 | 0 | return {}; |
486 | 15.7k | } |
487 | | |
488 | | Type const* FunctionDefinition::type() const |
489 | 11.6k | { |
490 | 11.6k | solAssert(visibility() != Visibility::External, ""); |
491 | 11.6k | return TypeProvider::function(*this, FunctionType::Kind::Internal); |
492 | 11.6k | } |
493 | | |
494 | | Type const* FunctionDefinition::typeViaContractName(ContractNameAccessKind const _accessKind) const |
495 | 1.28k | { |
496 | | // TODO: Fails because private library functions are attachable but not visible (issue #16721) |
497 | | //solAssert(isVisibleViaContractName(_accessKind)); |
498 | 1.28k | switch (_accessKind) |
499 | 1.28k | { |
500 | 235 | case ContractNameAccessKind::Local: |
501 | 235 | { |
502 | 235 | solAssert(!libraryFunction(), "Library members can only be accessed via library name."); |
503 | 235 | solAssert(visibility() > Visibility::Private, "Private non-library member is not visible via contract type name"); |
504 | | |
505 | 235 | if (!Declaration::isVisibleInContract() || !isImplemented()) |
506 | | // If is external or has no implementation, it cannot be called using contract type name. In case of accessing |
507 | | // via contract type name, only declaration is available, to be used in non calling context. I.e. to access |
508 | | // function selector `C.foo.selector` where foo has external visibility. |
509 | 72 | return TypeProvider::function(*this, FunctionType::Kind::Declaration); |
510 | 163 | else |
511 | | // If call is in local (or deriving) scope, function is visible in contract (non-external) and it has an |
512 | | // implementation, internal call is used. |
513 | 163 | return type(); |
514 | 235 | } |
515 | 132 | case ContractNameAccessKind::Foreign: |
516 | 132 | { |
517 | 132 | solAssert(!libraryFunction(), "Library members can only be accessed via library name."); |
518 | 132 | solAssert(isVisibleViaContractTypeAccess(), "Invisible member accessed via contract name."); |
519 | | // Foreign contract member function being accessed via contract type name, cannot be called. |
520 | 132 | return TypeProvider::function(*this, FunctionType::Kind::Declaration); |
521 | 235 | } |
522 | 918 | case ContractNameAccessKind::Library: |
523 | 918 | { |
524 | | // We could theoretically distinguish local and foreign scope for libraries but it does not affect the type, |
525 | | // so we don't. Access to private members from foreign scopes is not allowed by the type checker, so if we |
526 | | // get such a function here, we assume the scope is local. Note that access to private library members via |
527 | | // library name is not allowed, but you can (sometimes, see issue [#16721](#16721)) attach them via `using` |
528 | | // statement. |
529 | 918 | solAssert(libraryFunction(), "Non-library members cannot be accessed via library name."); |
530 | | // In case of library contract, member call kind depends on its visibility. |
531 | 918 | if (isPublic()) |
532 | | // When Lib.foo is public or external, an external call (delegate call) is used. |
533 | 370 | return FunctionType(*this).asExternallyCallableFunction(true /* _inLibrary */); |
534 | 548 | else |
535 | | // For private or internal visibility, internal call is used. |
536 | | // Private library members can be accessed in context of `using` statement. |
537 | 548 | return type(); |
538 | 918 | } |
539 | 1.28k | } |
540 | 0 | util::unreachable(); |
541 | 0 | } |
542 | | |
543 | | Type const* FunctionDefinition::typeWhenAttached() const |
544 | 1.69k | { |
545 | 1.69k | solAssert(isFree() || libraryFunction()); |
546 | 1.69k | return libraryFunction() ? typeViaContractName(ContractNameAccessKind::Library) : type(); |
547 | 1.69k | } |
548 | | |
549 | | std::string FunctionDefinition::externalSignature() const |
550 | 0 | { |
551 | 0 | return TypeProvider::function(*this)->externalSignature(); |
552 | 0 | } |
553 | | |
554 | | std::string FunctionDefinition::externalIdentifierHex() const |
555 | 0 | { |
556 | 0 | return TypeProvider::function(*this)->externalIdentifierHex(); |
557 | 0 | } |
558 | | |
559 | | FunctionDefinitionAnnotation& FunctionDefinition::annotation() const |
560 | 929k | { |
561 | 929k | return initAnnotation<FunctionDefinitionAnnotation>(); |
562 | 929k | } |
563 | | |
564 | | FunctionDefinition const& FunctionDefinition::resolveVirtual( |
565 | | ContractDefinition const& _mostDerivedContract, |
566 | | ContractDefinition const* _searchStart |
567 | | ) const |
568 | 25.7k | { |
569 | 25.7k | solAssert(!isConstructor(), ""); |
570 | 25.7k | solAssert(!name().empty(), ""); |
571 | | |
572 | | // If we are not doing super-lookup and the function is not virtual, we can stop here. |
573 | 25.7k | if (_searchStart == nullptr && !virtualSemantics()) |
574 | 24.3k | return *this; |
575 | | |
576 | 1.37k | solAssert(!isFree(), ""); |
577 | 1.37k | solAssert(isOrdinary(), ""); |
578 | 1.37k | solAssert(!libraryFunction(), ""); |
579 | | |
580 | | // We actually do not want the externally callable function here. |
581 | | // This is just to add an assertion since the comparison used to be less strict. |
582 | 1.37k | FunctionType const* externalFunctionType = TypeProvider::function(*this)->asExternallyCallableFunction(false); |
583 | | |
584 | 1.37k | bool foundSearchStart = (_searchStart == nullptr); |
585 | 1.37k | for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts) |
586 | 2.52k | { |
587 | 2.52k | if (!foundSearchStart && c != _searchStart) |
588 | 983 | continue; |
589 | 1.54k | else |
590 | 1.54k | foundSearchStart = true; |
591 | | |
592 | 1.54k | for (FunctionDefinition const* function: c->definedFunctions(name())) |
593 | 1.40k | if ( |
594 | | // With super lookup analysis guarantees that there is an implemented function in the chain. |
595 | | // With virtual lookup there are valid cases where returning an unimplemented one is fine. |
596 | 1.40k | (function->isImplemented() || _searchStart == nullptr) && |
597 | 1.39k | FunctionType(*function).asExternallyCallableFunction(false)->hasEqualParameterTypes(*externalFunctionType) |
598 | 1.40k | ) |
599 | 1.37k | { |
600 | 1.37k | solAssert(FunctionType(*function).hasEqualParameterTypes(*TypeProvider::function(*this))); |
601 | 1.37k | return *function; |
602 | 1.37k | } |
603 | 1.54k | } |
604 | | |
605 | 0 | solAssert(false, "Virtual function " + name() + " not found."); |
606 | 0 | return *this; // not reached |
607 | 1.37k | } |
608 | | |
609 | | Type const* ModifierDefinition::type() const |
610 | 5 | { |
611 | 5 | return TypeProvider::modifier(*this); |
612 | 5 | } |
613 | | |
614 | | ModifierDefinitionAnnotation& ModifierDefinition::annotation() const |
615 | 82.2k | { |
616 | 82.2k | return initAnnotation<ModifierDefinitionAnnotation>(); |
617 | 82.2k | } |
618 | | |
619 | | ModifierDefinition const& ModifierDefinition::resolveVirtual( |
620 | | ContractDefinition const& _mostDerivedContract, |
621 | | ContractDefinition const* _searchStart |
622 | | ) const |
623 | 36.2k | { |
624 | | // Super is not possible with modifiers |
625 | 36.2k | solAssert(_searchStart == nullptr, "Used super in connection with modifiers."); |
626 | | |
627 | | // The modifier is not virtual, we can stop here. |
628 | 36.2k | if (!virtualSemantics()) |
629 | 35.0k | return *this; |
630 | | |
631 | 1.20k | solAssert(!dynamic_cast<ContractDefinition const&>(*scope()).isLibrary(), ""); |
632 | | |
633 | 1.20k | for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts) |
634 | 1.25k | for (ModifierDefinition const* modifier: c->functionModifiers()) |
635 | 1.23k | if (modifier->name() == name()) |
636 | 1.20k | return *modifier; |
637 | | |
638 | 0 | solAssert(false, "Virtual modifier " + name() + " not found."); |
639 | 0 | return *this; // not reached |
640 | 1.20k | } |
641 | | |
642 | | |
643 | | Type const* EventDefinition::type() const |
644 | 1.38k | { |
645 | 1.38k | return TypeProvider::function(*this); |
646 | 1.38k | } |
647 | | |
648 | | FunctionTypePointer EventDefinition::functionType(bool _internal) const |
649 | 16.8k | { |
650 | 16.8k | if (_internal) |
651 | 16.0k | return TypeProvider::function(*this); |
652 | 816 | else |
653 | 816 | return nullptr; |
654 | 16.8k | } |
655 | | |
656 | | EventDefinitionAnnotation& EventDefinition::annotation() const |
657 | 70.1k | { |
658 | 70.1k | return initAnnotation<EventDefinitionAnnotation>(); |
659 | 70.1k | } |
660 | | |
661 | | Type const* ErrorDefinition::type() const |
662 | 100 | { |
663 | 100 | return TypeProvider::function(*this); |
664 | 100 | } |
665 | | |
666 | | FunctionTypePointer ErrorDefinition::functionType(bool _internal) const |
667 | 632 | { |
668 | 632 | if (_internal) |
669 | 632 | return TypeProvider::function(*this); |
670 | 0 | else |
671 | 0 | return nullptr; |
672 | 632 | } |
673 | | |
674 | | ErrorDefinitionAnnotation& ErrorDefinition::annotation() const |
675 | 12.3k | { |
676 | 12.3k | return initAnnotation<ErrorDefinitionAnnotation>(); |
677 | 12.3k | } |
678 | | |
679 | | SourceUnit const& Scopable::sourceUnit() const |
680 | 255k | { |
681 | 255k | ASTNode const* s = scope(); |
682 | 255k | solAssert(s, ""); |
683 | | // will not always be a declaration |
684 | 283k | while (dynamic_cast<Scopable const*>(s) && dynamic_cast<Scopable const*>(s)->scope()) |
685 | 28.3k | s = dynamic_cast<Scopable const*>(s)->scope(); |
686 | 255k | return dynamic_cast<SourceUnit const&>(*s); |
687 | 255k | } |
688 | | |
689 | | CallableDeclaration const* Scopable::functionOrModifierDefinition() const |
690 | 0 | { |
691 | 0 | ASTNode const* s = scope(); |
692 | 0 | solAssert(s, ""); |
693 | 0 | while (dynamic_cast<Scopable const*>(s)) |
694 | 0 | { |
695 | 0 | if (auto funDef = dynamic_cast<FunctionDefinition const*>(s)) |
696 | 0 | return funDef; |
697 | 0 | if (auto modDef = dynamic_cast<ModifierDefinition const*>(s)) |
698 | 0 | return modDef; |
699 | 0 | s = dynamic_cast<Scopable const*>(s)->scope(); |
700 | 0 | } |
701 | 0 | return nullptr; |
702 | 0 | } |
703 | | |
704 | | std::string Scopable::sourceUnitName() const |
705 | 75.5k | { |
706 | 75.5k | return *sourceUnit().annotation().path; |
707 | 75.5k | } |
708 | | |
709 | | bool Declaration::isEnumValue() const |
710 | 149k | { |
711 | 149k | solAssert(scope(), ""); |
712 | 149k | return dynamic_cast<EnumDefinition const*>(scope()); |
713 | 149k | } |
714 | | |
715 | | bool Declaration::isStructMember() const |
716 | 169k | { |
717 | 169k | solAssert(scope(), ""); |
718 | 169k | return dynamic_cast<StructDefinition const*>(scope()); |
719 | 169k | } |
720 | | |
721 | | bool Declaration::isEventOrErrorParameter() const |
722 | 249k | { |
723 | 249k | solAssert(scope(), ""); |
724 | 249k | return dynamic_cast<EventDefinition const*>(scope()) || dynamic_cast<ErrorDefinition const*>(scope()); |
725 | 249k | } |
726 | | |
727 | | bool Declaration::isVisibleAsUnqualifiedName() const |
728 | 169k | { |
729 | 169k | if (!scope()) |
730 | 199 | return true; |
731 | 169k | if (isStructMember() || isEnumValue() || isEventOrErrorParameter()) |
732 | 22.5k | return false; |
733 | 146k | if (auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(scope())) |
734 | 15.7k | if (!functionDefinition->isImplemented()) |
735 | 99 | return false; // parameter of a function without body |
736 | 146k | return true; |
737 | 146k | } |
738 | | |
739 | | DeclarationAnnotation& Declaration::annotation() const |
740 | 66.8k | { |
741 | 66.8k | return initAnnotation<DeclarationAnnotation>(); |
742 | 66.8k | } |
743 | | |
744 | | bool VariableDeclaration::isLValue() const |
745 | 114k | { |
746 | | // Constant declared variables are Read-Only |
747 | 114k | return !isConstant(); |
748 | 114k | } |
749 | | |
750 | | bool VariableDeclaration::isLocalVariable() const |
751 | 214k | { |
752 | 214k | auto s = scope(); |
753 | 214k | return |
754 | 214k | dynamic_cast<FunctionTypeName const*>(s) || |
755 | 213k | dynamic_cast<CallableDeclaration const*>(s) || |
756 | 102k | dynamic_cast<Block const*>(s) || |
757 | 56.5k | dynamic_cast<TryCatchClause const*>(s) || |
758 | 56.2k | dynamic_cast<ForStatement const*>(s); |
759 | 214k | } |
760 | | |
761 | | bool VariableDeclaration::isCallableOrCatchParameter() const |
762 | 153k | { |
763 | 153k | if (isReturnParameter() || isTryCatchParameter()) |
764 | 32.9k | return true; |
765 | | |
766 | 121k | std::vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr; |
767 | | |
768 | 121k | if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope())) |
769 | 643 | parameters = &funTypeName->parameterTypes(); |
770 | 120k | else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope())) |
771 | 63.7k | parameters = &callable->parameters(); |
772 | | |
773 | 121k | if (parameters) |
774 | 64.3k | for (auto const& variable: *parameters) |
775 | 90.8k | if (variable.get() == this) |
776 | 64.3k | return true; |
777 | 56.6k | return false; |
778 | 121k | } |
779 | | |
780 | | bool VariableDeclaration::isLocalOrReturn() const |
781 | 60 | { |
782 | 60 | return isReturnParameter() || (isLocalVariable() && !isCallableOrCatchParameter()); |
783 | 60 | } |
784 | | |
785 | | bool VariableDeclaration::isReturnParameter() const |
786 | 182k | { |
787 | 182k | std::vector<ASTPointer<VariableDeclaration>> const* returnParameters = nullptr; |
788 | | |
789 | 182k | if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope())) |
790 | 868 | returnParameters = &funTypeName->returnParameterTypes(); |
791 | 182k | else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope())) |
792 | 124k | if (callable->returnParameterList()) |
793 | 116k | returnParameters = &callable->returnParameterList()->parameters(); |
794 | | |
795 | 182k | if (returnParameters) |
796 | 117k | for (auto const& variable: *returnParameters) |
797 | 147k | if (variable.get() == this) |
798 | 45.7k | return true; |
799 | 137k | return false; |
800 | 182k | } |
801 | | |
802 | | bool VariableDeclaration::isTryCatchParameter() const |
803 | 130k | { |
804 | 130k | return dynamic_cast<TryCatchClause const*>(scope()); |
805 | 130k | } |
806 | | |
807 | | bool VariableDeclaration::isExternalCallableParameter() const |
808 | 50 | { |
809 | 50 | if (!isCallableOrCatchParameter()) |
810 | 0 | return false; |
811 | | |
812 | 50 | if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope())) |
813 | 43 | if (callable->visibility() == Visibility::External) |
814 | 26 | return !isReturnParameter(); |
815 | | |
816 | 24 | return false; |
817 | 50 | } |
818 | | |
819 | | bool VariableDeclaration::isPublicCallableParameter() const |
820 | 16.4k | { |
821 | 16.4k | if (!isCallableOrCatchParameter()) |
822 | 7.74k | return false; |
823 | | |
824 | 8.73k | if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope())) |
825 | 8.55k | if (callable->visibility() == Visibility::Public) |
826 | 3.94k | return !isReturnParameter(); |
827 | | |
828 | 4.78k | return false; |
829 | 8.73k | } |
830 | | |
831 | | bool VariableDeclaration::isInternalCallableParameter() const |
832 | 7.57k | { |
833 | 7.57k | if (!isCallableOrCatchParameter()) |
834 | 0 | return false; |
835 | | |
836 | 7.57k | if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope())) |
837 | 112 | return funTypeName->visibility() == Visibility::Internal; |
838 | 7.46k | else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope())) |
839 | 7.35k | return callable->visibility() <= Visibility::Internal; |
840 | 104 | return false; |
841 | 7.57k | } |
842 | | |
843 | | bool VariableDeclaration::isConstructorParameter() const |
844 | 48.2k | { |
845 | 48.2k | if (!isCallableOrCatchParameter()) |
846 | 15.5k | return false; |
847 | 32.7k | if (auto const* function = dynamic_cast<FunctionDefinition const*>(scope())) |
848 | 29.1k | return function->isConstructor(); |
849 | 3.66k | return false; |
850 | 32.7k | } |
851 | | |
852 | | bool VariableDeclaration::isLibraryFunctionParameter() const |
853 | 22.1k | { |
854 | 22.1k | if (!isCallableOrCatchParameter()) |
855 | 7.74k | return false; |
856 | 14.4k | if (auto const* funDef = dynamic_cast<FunctionDefinition const*>(scope())) |
857 | 12.5k | return funDef->libraryFunction(); |
858 | 1.82k | return false; |
859 | 14.4k | } |
860 | | |
861 | | bool VariableDeclaration::hasReferenceOrMappingType() const |
862 | 118k | { |
863 | 118k | solAssert(typeName().annotation().type, "Can only be called after reference resolution"); |
864 | 118k | Type const* type = typeName().annotation().type; |
865 | 118k | return type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type); |
866 | 118k | } |
867 | | |
868 | | bool VariableDeclaration::isStateVariable() const |
869 | 939k | { |
870 | 939k | return dynamic_cast<ContractDefinition const*>(scope()); |
871 | 939k | } |
872 | | |
873 | | bool VariableDeclaration::isFileLevelVariable() const |
874 | 284k | { |
875 | 284k | return dynamic_cast<SourceUnit const*>(scope()); |
876 | 284k | } |
877 | | |
878 | | std::set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const |
879 | 75.8k | { |
880 | 75.8k | using Location = VariableDeclaration::Location; |
881 | | |
882 | 75.8k | if (isStateVariable()) |
883 | 10.1k | return std::set<Location>{Location::Unspecified, Location::Transient}; |
884 | 65.7k | else if (!hasReferenceOrMappingType() || isEventOrErrorParameter()) |
885 | 42.0k | return std::set<Location>{ Location::Unspecified }; |
886 | 23.6k | else if (isCallableOrCatchParameter()) |
887 | 7.63k | { |
888 | 7.63k | std::set<Location> locations{ Location::Memory }; |
889 | 7.63k | if ( |
890 | 7.63k | isConstructorParameter() || |
891 | 7.57k | isInternalCallableParameter() || |
892 | 5.63k | isLibraryFunctionParameter() |
893 | 7.63k | ) |
894 | 2.21k | locations.insert(Location::Storage); |
895 | 7.63k | if (!isTryCatchParameter() && !isConstructorParameter()) |
896 | 7.46k | locations.insert(Location::CallData); |
897 | | |
898 | 7.63k | return locations; |
899 | 7.63k | } |
900 | 16.0k | else if (isLocalVariable()) |
901 | | // Further restrictions will be imposed later on. |
902 | 3.59k | return std::set<Location>{ Location::Memory, Location::Storage, Location::CallData }; |
903 | 12.4k | else |
904 | | // Struct members etc. |
905 | 12.4k | return std::set<Location>{ Location::Unspecified }; |
906 | 75.8k | } |
907 | | |
908 | | std::string VariableDeclaration::externalIdentifierHex() const |
909 | 0 | { |
910 | 0 | solAssert(isStateVariable() && isPublic(), "Can only be called for public state variables"); |
911 | 0 | return TypeProvider::function(*this)->externalIdentifierHex(); |
912 | 0 | } |
913 | | |
914 | | Type const* VariableDeclaration::type() const |
915 | 687k | { |
916 | 687k | return annotation().type; |
917 | 687k | } |
918 | | |
919 | | FunctionTypePointer VariableDeclaration::functionType(bool _internal) const |
920 | 7.35k | { |
921 | 7.35k | if (_internal) |
922 | 0 | return nullptr; |
923 | 7.35k | switch (visibility()) |
924 | 7.35k | { |
925 | 0 | case Visibility::Default: |
926 | 0 | solAssert(false, "visibility() should not return Default"); |
927 | 15 | case Visibility::Private: |
928 | 5.03k | case Visibility::Internal: |
929 | 5.03k | return nullptr; |
930 | 2.31k | case Visibility::Public: |
931 | 2.31k | case Visibility::External: |
932 | 2.31k | return TypeProvider::function(*this); |
933 | 7.35k | } |
934 | | |
935 | | // To make the compiler happy |
936 | 0 | return nullptr; |
937 | 7.35k | } |
938 | | |
939 | | VariableDeclarationAnnotation& VariableDeclaration::annotation() const |
940 | 13.1M | { |
941 | 13.1M | return initAnnotation<VariableDeclarationAnnotation>(); |
942 | 13.1M | } |
943 | | |
944 | | StatementAnnotation& Statement::annotation() const |
945 | 195k | { |
946 | 195k | return initAnnotation<StatementAnnotation>(); |
947 | 195k | } |
948 | | |
949 | | InlineAssemblyAnnotation& InlineAssembly::annotation() const |
950 | 33.8k | { |
951 | 33.8k | return initAnnotation<InlineAssemblyAnnotation>(); |
952 | 33.8k | } |
953 | | |
954 | | BlockAnnotation& Block::annotation() const |
955 | 166k | { |
956 | 166k | return initAnnotation<BlockAnnotation>(); |
957 | 166k | } |
958 | | |
959 | | TryCatchClauseAnnotation& TryCatchClause::annotation() const |
960 | 3.72k | { |
961 | 3.72k | return initAnnotation<TryCatchClauseAnnotation>(); |
962 | 3.72k | } |
963 | | |
964 | | ForStatementAnnotation& ForStatement::annotation() const |
965 | 24.4k | { |
966 | 24.4k | return initAnnotation<ForStatementAnnotation>(); |
967 | 24.4k | } |
968 | | |
969 | | ReturnAnnotation& Return::annotation() const |
970 | 357k | { |
971 | 357k | return initAnnotation<ReturnAnnotation>(); |
972 | 357k | } |
973 | | |
974 | | ExpressionAnnotation& Expression::annotation() const |
975 | 7.28M | { |
976 | 7.28M | return initAnnotation<ExpressionAnnotation>(); |
977 | 7.28M | } |
978 | | |
979 | | MemberAccessAnnotation& MemberAccess::annotation() const |
980 | 5.16M | { |
981 | 5.16M | return initAnnotation<MemberAccessAnnotation>(); |
982 | 5.16M | } |
983 | | |
984 | | OperationAnnotation& UnaryOperation::annotation() const |
985 | 468k | { |
986 | 468k | return initAnnotation<OperationAnnotation>(); |
987 | 468k | } |
988 | | |
989 | | FunctionType const* UnaryOperation::userDefinedFunctionType() const |
990 | 17.3k | { |
991 | 17.3k | if (*annotation().userDefinedFunction == nullptr) |
992 | 17.2k | return nullptr; |
993 | | |
994 | 88 | FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction; |
995 | 88 | return dynamic_cast<FunctionType const*>(userDefinedFunction->typeWhenAttached()); |
996 | 17.3k | } |
997 | | |
998 | | FunctionType const* BinaryOperation::userDefinedFunctionType() const |
999 | 68.2k | { |
1000 | 68.2k | if (*annotation().userDefinedFunction == nullptr) |
1001 | 68.0k | return nullptr; |
1002 | | |
1003 | 128 | FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction; |
1004 | 128 | return dynamic_cast<FunctionType const*>(userDefinedFunction->typeWhenAttached()); |
1005 | 68.2k | } |
1006 | | |
1007 | | BinaryOperationAnnotation& BinaryOperation::annotation() const |
1008 | 1.43M | { |
1009 | 1.43M | return initAnnotation<BinaryOperationAnnotation>(); |
1010 | 1.43M | } |
1011 | | |
1012 | | FunctionCallAnnotation& FunctionCall::annotation() const |
1013 | 756k | { |
1014 | 756k | return initAnnotation<FunctionCallAnnotation>(); |
1015 | 756k | } |
1016 | | |
1017 | | std::vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const |
1018 | 30.1k | { |
1019 | | // normal arguments |
1020 | 30.1k | if (m_names.empty()) |
1021 | 29.8k | return arguments(); |
1022 | | |
1023 | | // named arguments |
1024 | 324 | FunctionTypePointer functionType; |
1025 | 324 | if (*annotation().kind == FunctionCallKind::StructConstructorCall) |
1026 | 85 | { |
1027 | 85 | auto const& type = dynamic_cast<TypeType const&>(*m_expression->annotation().type); |
1028 | 85 | auto const& structType = dynamic_cast<StructType const&>(*type.actualType()); |
1029 | 85 | functionType = structType.constructorType(); |
1030 | 85 | } |
1031 | 239 | else |
1032 | 239 | functionType = dynamic_cast<FunctionType const*>(m_expression->annotation().type); |
1033 | | |
1034 | 324 | std::vector<ASTPointer<Expression const>> sorted; |
1035 | 324 | for (auto const& parameterName: functionType->parameterNames()) |
1036 | 837 | { |
1037 | 837 | bool found = false; |
1038 | 2.39k | for (size_t j = 0; j < m_names.size() && !found; j++) |
1039 | 1.55k | if ((found = (parameterName == *m_names.at(j)))) |
1040 | | // we found the actual parameter position |
1041 | 837 | sorted.push_back(m_arguments.at(j)); |
1042 | 837 | solAssert(found, ""); |
1043 | 837 | } |
1044 | | |
1045 | 324 | if (!functionType->takesArbitraryParameters()) |
1046 | 324 | { |
1047 | 324 | solAssert(m_arguments.size() == functionType->parameterTypes().size(), ""); |
1048 | 324 | solAssert(m_arguments.size() == m_names.size(), ""); |
1049 | 324 | solAssert(m_arguments.size() == sorted.size(), ""); |
1050 | 324 | } |
1051 | | |
1052 | 324 | return sorted; |
1053 | 30.1k | } |
1054 | | |
1055 | | IdentifierAnnotation& Identifier::annotation() const |
1056 | 4.40M | { |
1057 | 4.40M | return initAnnotation<IdentifierAnnotation>(); |
1058 | 4.40M | } |
1059 | | |
1060 | | ASTString Literal::valueWithoutUnderscores() const |
1061 | 726k | { |
1062 | 726k | return boost::erase_all_copy(value(), "_"); |
1063 | 726k | } |
1064 | | |
1065 | | bool Literal::isHexNumber() const |
1066 | 1.46M | { |
1067 | 1.46M | if (token() != Token::Number) |
1068 | 77.5k | return false; |
1069 | 1.38M | return boost::starts_with(value(), "0x"); |
1070 | 1.46M | } |
1071 | | |
1072 | | bool Literal::looksLikeAddress() const |
1073 | 264k | { |
1074 | 264k | if (subDenomination() != SubDenomination::None) |
1075 | 317 | return false; |
1076 | | |
1077 | 263k | if (!isHexNumber()) |
1078 | 257k | return false; |
1079 | | |
1080 | 6.54k | return abs(int(valueWithoutUnderscores().length()) - 42) <= 1; |
1081 | 263k | } |
1082 | | |
1083 | | bool Literal::passesAddressChecksum() const |
1084 | 86 | { |
1085 | 86 | solAssert(isHexNumber(), "Expected hex number"); |
1086 | 86 | return util::passesAddressChecksum(valueWithoutUnderscores(), true); |
1087 | 86 | } |
1088 | | |
1089 | | std::string Literal::getChecksummedAddress() const |
1090 | 24 | { |
1091 | 24 | solAssert(isHexNumber(), "Expected hex number"); |
1092 | | /// Pad literal to be a proper hex address. |
1093 | 24 | std::string address = valueWithoutUnderscores().substr(2); |
1094 | 24 | if (address.length() > 40) |
1095 | 0 | return std::string(); |
1096 | 24 | address.insert(address.begin(), 40 - address.size(), '0'); |
1097 | 24 | return util::getChecksummedAddress(address); |
1098 | 24 | } |
1099 | | |
1100 | | TryCatchClause const* TryStatement::successClause() const |
1101 | 648 | { |
1102 | 648 | solAssert(m_clauses.size() > 0, ""); |
1103 | 648 | return m_clauses[0].get(); |
1104 | 648 | } |
1105 | | |
1106 | 106 | TryCatchClause const* TryStatement::panicClause() const { |
1107 | 106 | return findClause(m_clauses, "Panic"); |
1108 | 106 | } |
1109 | | |
1110 | 106 | TryCatchClause const* TryStatement::errorClause() const { |
1111 | 106 | return findClause(m_clauses, "Error"); |
1112 | 106 | } |
1113 | | |
1114 | 106 | TryCatchClause const* TryStatement::fallbackClause() const { |
1115 | 106 | return findClause(m_clauses); |
1116 | 106 | } |
1117 | | |
1118 | | /// Experimental Solidity nodes |
1119 | | /// @{ |
1120 | | TypeClassDefinitionAnnotation& TypeClassDefinition::annotation() const |
1121 | 264 | { |
1122 | 264 | return initAnnotation<TypeClassDefinitionAnnotation>(); |
1123 | 264 | } |
1124 | | TypeDeclarationAnnotation& TypeDefinition::annotation() const |
1125 | 1.27k | { |
1126 | 1.27k | return initAnnotation<TypeDeclarationAnnotation>(); |
1127 | 1.27k | } |
1128 | | /// @} |