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/Keccak256.h>
31
32 #include <boost/algorithm/string.hpp>
33
34 #include <functional>
35 #include <utility>
36
37 using namespace std;
38 using namespace solidity;
39 using namespace solidity::frontend;
40
ASTNode(int64_t _id,SourceLocation _location)41 ASTNode::ASTNode(int64_t _id, SourceLocation _location):
42 m_id(static_cast<size_t>(_id)),
43 m_location(std::move(_location))
44 {
45 }
46
referencedDeclaration(Expression const & _expression)47 Declaration const* ASTNode::referencedDeclaration(Expression const& _expression)
48 {
49 if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_expression))
50 return memberAccess->annotation().referencedDeclaration;
51 else if (auto const* identifierPath = dynamic_cast<IdentifierPath const*>(&_expression))
52 return identifierPath->annotation().referencedDeclaration;
53 else if (auto const* identifier = dynamic_cast<Identifier const*>(&_expression))
54 return identifier->annotation().referencedDeclaration;
55 else
56 return nullptr;
57 }
58
resolveFunctionCall(FunctionCall const & _functionCall,ContractDefinition const * _mostDerivedContract)59 FunctionDefinition const* ASTNode::resolveFunctionCall(FunctionCall const& _functionCall, ContractDefinition const* _mostDerivedContract)
60 {
61 auto const* functionDef = dynamic_cast<FunctionDefinition const*>(
62 ASTNode::referencedDeclaration(_functionCall.expression())
63 );
64
65 if (!functionDef)
66 return nullptr;
67
68 if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression()))
69 {
70 if (*memberAccess->annotation().requiredLookup == VirtualLookup::Super)
71 {
72 if (auto const typeType = dynamic_cast<TypeType const*>(memberAccess->expression().annotation().type))
73 if (auto const contractType = dynamic_cast<ContractType const*>(typeType->actualType()))
74 {
75 solAssert(_mostDerivedContract, "");
76 solAssert(contractType->isSuper(), "");
77 ContractDefinition const* superContract = contractType->contractDefinition().superContract(*_mostDerivedContract);
78
79 return &functionDef->resolveVirtual(
80 *_mostDerivedContract,
81 superContract
82 );
83 }
84 }
85 else
86 solAssert(*memberAccess->annotation().requiredLookup == VirtualLookup::Static, "");
87 }
88 else if (auto const* identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
89 {
90 solAssert(*identifier->annotation().requiredLookup == VirtualLookup::Virtual, "");
91 if (functionDef->virtualSemantics())
92 {
93 solAssert(_mostDerivedContract, "");
94 return &functionDef->resolveVirtual(*_mostDerivedContract);
95 }
96 }
97 else
98 solAssert(false, "");
99
100 return functionDef;
101 }
102
annotation() const103 ASTAnnotation& ASTNode::annotation() const
104 {
105 if (!m_annotation)
106 m_annotation = make_unique<ASTAnnotation>();
107 return *m_annotation;
108 }
109
annotation() const110 SourceUnitAnnotation& SourceUnit::annotation() const
111 {
112 return initAnnotation<SourceUnitAnnotation>();
113 }
114
referencedSourceUnits(bool _recurse,set<SourceUnit const * > _skipList) const115 set<SourceUnit const*> SourceUnit::referencedSourceUnits(bool _recurse, set<SourceUnit const*> _skipList) const
116 {
117 set<SourceUnit const*> sourceUnits;
118 for (ImportDirective const* importDirective: filteredNodes<ImportDirective>(nodes()))
119 {
120 auto const& sourceUnit = importDirective->annotation().sourceUnit;
121 if (!_skipList.count(sourceUnit))
122 {
123 _skipList.insert(sourceUnit);
124 sourceUnits.insert(sourceUnit);
125 if (_recurse)
126 sourceUnits += sourceUnit->referencedSourceUnits(true, _skipList);
127 }
128 }
129 return sourceUnits;
130 }
131
annotation() const132 ImportAnnotation& ImportDirective::annotation() const
133 {
134 return initAnnotation<ImportAnnotation>();
135 }
136
type() const137 Type const* ImportDirective::type() const
138 {
139 solAssert(!!annotation().sourceUnit, "");
140 return TypeProvider::module(*annotation().sourceUnit);
141 }
142
derivesFrom(ContractDefinition const & _base) const143 bool ContractDefinition::derivesFrom(ContractDefinition const& _base) const
144 {
145 return util::contains(annotation().linearizedBaseContracts, &_base);
146 }
147
interfaceFunctions(bool _includeInheritedFunctions) const148 map<util::FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions(bool _includeInheritedFunctions) const
149 {
150 auto exportedFunctionList = interfaceFunctionList(_includeInheritedFunctions);
151
152 map<util::FixedHash<4>, FunctionTypePointer> exportedFunctions;
153 for (auto const& it: exportedFunctionList)
154 exportedFunctions.insert(it);
155
156 solAssert(
157 exportedFunctionList.size() == exportedFunctions.size(),
158 "Hash collision at Function Definition Hash calculation"
159 );
160
161 return exportedFunctions;
162 }
163
constructor() const164 FunctionDefinition const* ContractDefinition::constructor() const
165 {
166 for (FunctionDefinition const* f: definedFunctions())
167 if (f->isConstructor())
168 return f;
169 return nullptr;
170 }
171
canBeDeployed() const172 bool ContractDefinition::canBeDeployed() const
173 {
174 return !abstract() && !isInterface();
175 }
176
fallbackFunction() const177 FunctionDefinition const* ContractDefinition::fallbackFunction() const
178 {
179 for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
180 for (FunctionDefinition const* f: contract->definedFunctions())
181 if (f->isFallback())
182 return f;
183 return nullptr;
184 }
185
receiveFunction() const186 FunctionDefinition const* ContractDefinition::receiveFunction() const
187 {
188 for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
189 for (FunctionDefinition const* f: contract->definedFunctions())
190 if (f->isReceive())
191 return f;
192 return nullptr;
193 }
194
interfaceEvents() const195 vector<EventDefinition const*> const& ContractDefinition::interfaceEvents() const
196 {
197 return m_interfaceEvents.init([&]{
198 set<string> eventsSeen;
199 vector<EventDefinition const*> interfaceEvents;
200
201 for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
202 for (EventDefinition const* e: contract->events())
203 {
204 /// NOTE: this requires the "internal" version of an Event,
205 /// though here internal strictly refers to visibility,
206 /// and not to function encoding (jump vs. call)
207 auto const& function = e->functionType(true);
208 solAssert(function, "");
209 string eventSignature = function->externalSignature();
210 if (eventsSeen.count(eventSignature) == 0)
211 {
212 eventsSeen.insert(eventSignature);
213 interfaceEvents.push_back(e);
214 }
215 }
216
217 return interfaceEvents;
218 });
219 }
220
interfaceErrors(bool _requireCallGraph) const221 vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const
222 {
223 set<ErrorDefinition const*, CompareByID> result;
224 for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
225 result += filteredNodes<ErrorDefinition>(contract->m_subNodes);
226 solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set(), "");
227 if (_requireCallGraph)
228 solAssert(annotation().creationCallGraph.set(), "");
229 if (annotation().creationCallGraph.set())
230 {
231 result += (*annotation().creationCallGraph)->usedErrors;
232 result += (*annotation().deployedCallGraph)->usedErrors;
233 }
234 return convertContainer<vector<ErrorDefinition const*>>(move(result));
235 }
236
interfaceFunctionList(bool _includeInheritedFunctions) const237 vector<pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::interfaceFunctionList(bool _includeInheritedFunctions) const
238 {
239 return m_interfaceFunctionList[_includeInheritedFunctions].init([&]{
240 set<string> signaturesSeen;
241 vector<pair<util::FixedHash<4>, FunctionTypePointer>> interfaceFunctionList;
242
243 for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
244 {
245 if (_includeInheritedFunctions == false && contract != this)
246 continue;
247 vector<FunctionTypePointer> functions;
248 for (FunctionDefinition const* f: contract->definedFunctions())
249 if (f->isPartOfExternalInterface())
250 functions.push_back(TypeProvider::function(*f, FunctionType::Kind::External));
251 for (VariableDeclaration const* v: contract->stateVariables())
252 if (v->isPartOfExternalInterface())
253 functions.push_back(TypeProvider::function(*v));
254 for (FunctionTypePointer const& fun: functions)
255 {
256 if (!fun->interfaceFunctionType())
257 // Fails hopefully because we already registered the error
258 continue;
259 string functionSignature = fun->externalSignature();
260 if (signaturesSeen.count(functionSignature) == 0)
261 {
262 signaturesSeen.insert(functionSignature);
263 util::FixedHash<4> hash(util::keccak256(functionSignature));
264 interfaceFunctionList.emplace_back(hash, fun);
265 }
266 }
267 }
268
269 return interfaceFunctionList;
270 });
271 }
272
interfaceId() const273 uint32_t ContractDefinition::interfaceId() const
274 {
275 uint32_t result{0};
276 for (auto const& function: interfaceFunctionList(false))
277 result ^= fromBigEndian<uint32_t>(function.first.ref());
278 return result;
279 }
280
type() const281 Type const* ContractDefinition::type() const
282 {
283 return TypeProvider::typeType(TypeProvider::contract(*this));
284 }
285
annotation() const286 ContractDefinitionAnnotation& ContractDefinition::annotation() const
287 {
288 return initAnnotation<ContractDefinitionAnnotation>();
289 }
290
superContract(ContractDefinition const & _mostDerivedContract) const291 ContractDefinition const* ContractDefinition::superContract(ContractDefinition const& _mostDerivedContract) const
292 {
293 auto const& hierarchy = _mostDerivedContract.annotation().linearizedBaseContracts;
294 auto it = find(hierarchy.begin(), hierarchy.end(), this);
295 solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy.");
296 ++it;
297 if (it == hierarchy.end())
298 return nullptr;
299 else
300 {
301 solAssert(*it != this, "");
302 return *it;
303 }
304 }
305
nextConstructor(ContractDefinition const & _mostDerivedContract) const306 FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition const& _mostDerivedContract) const
307 {
308 ContractDefinition const* next = superContract(_mostDerivedContract);
309 if (next == nullptr)
310 return nullptr;
311 for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
312 if (c == next || next == nullptr)
313 {
314 if (c->constructor())
315 return c->constructor();
316 next = nullptr;
317 }
318
319 return nullptr;
320 }
321
definedFunctionsByName() const322 multimap<std::string, FunctionDefinition const*> const& ContractDefinition::definedFunctionsByName() const
323 {
324 return m_definedFunctionsByName.init([&]{
325 std::multimap<std::string, FunctionDefinition const*> result;
326 for (FunctionDefinition const* fun: filteredNodes<FunctionDefinition>(m_subNodes))
327 result.insert({fun->name(), fun});
328 return result;
329 });
330 }
331
332
annotation() const333 TypeNameAnnotation& TypeName::annotation() const
334 {
335 return initAnnotation<TypeNameAnnotation>();
336 }
337
type() const338 Type const* UserDefinedValueTypeDefinition::type() const
339 {
340 solAssert(m_underlyingType->annotation().type, "");
341 return TypeProvider::typeType(TypeProvider::userDefinedValueType(*this));
342 }
343
annotation() const344 TypeDeclarationAnnotation& UserDefinedValueTypeDefinition::annotation() const
345 {
346 return initAnnotation<TypeDeclarationAnnotation>();
347 }
348
type() const349 Type const* StructDefinition::type() const
350 {
351 solAssert(annotation().recursive.has_value(), "Requested struct type before DeclarationTypeChecker.");
352 return TypeProvider::typeType(TypeProvider::structType(*this, DataLocation::Storage));
353 }
354
annotation() const355 StructDeclarationAnnotation& StructDefinition::annotation() const
356 {
357 return initAnnotation<StructDeclarationAnnotation>();
358 }
359
type() const360 Type const* EnumValue::type() const
361 {
362 auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
363 solAssert(parentDef, "Enclosing Scope of EnumValue was not set");
364 return TypeProvider::enumType(*parentDef);
365 }
366
type() const367 Type const* EnumDefinition::type() const
368 {
369 return TypeProvider::typeType(TypeProvider::enumType(*this));
370 }
371
annotation() const372 TypeDeclarationAnnotation& EnumDefinition::annotation() const
373 {
374 return initAnnotation<TypeDeclarationAnnotation>();
375 }
376
libraryFunction() const377 bool FunctionDefinition::libraryFunction() const
378 {
379 if (auto const* contractDef = dynamic_cast<ContractDefinition const*>(scope()))
380 return contractDef->isLibrary();
381 return false;
382 }
383
defaultVisibility() const384 Visibility FunctionDefinition::defaultVisibility() const
385 {
386 solAssert(!isConstructor(), "");
387 return isFree() ? Visibility::Internal : Declaration::defaultVisibility();
388 }
389
functionType(bool _internal) const390 FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
391 {
392 if (_internal)
393 {
394 switch (visibility())
395 {
396 case Visibility::Default:
397 solAssert(false, "visibility() should not return Default");
398 case Visibility::Private:
399 case Visibility::Internal:
400 case Visibility::Public:
401 return TypeProvider::function(*this, FunctionType::Kind::Internal);
402 case Visibility::External:
403 return {};
404 }
405 }
406 else
407 {
408 switch (visibility())
409 {
410 case Visibility::Default:
411 solAssert(false, "visibility() should not return Default");
412 case Visibility::Private:
413 case Visibility::Internal:
414 return {};
415 case Visibility::Public:
416 case Visibility::External:
417 return TypeProvider::function(*this, FunctionType::Kind::External);
418 }
419 }
420
421 // To make the compiler happy
422 return {};
423 }
424
type() const425 Type const* FunctionDefinition::type() const
426 {
427 solAssert(visibility() != Visibility::External, "");
428 return TypeProvider::function(*this, FunctionType::Kind::Internal);
429 }
430
typeViaContractName() const431 Type const* FunctionDefinition::typeViaContractName() const
432 {
433 if (libraryFunction())
434 {
435 if (isPublic())
436 return FunctionType(*this).asExternallyCallableFunction(true);
437 else
438 return TypeProvider::function(*this, FunctionType::Kind::Internal);
439 }
440 else
441 return TypeProvider::function(*this, FunctionType::Kind::Declaration);
442 }
443
externalSignature() const444 string FunctionDefinition::externalSignature() const
445 {
446 return TypeProvider::function(*this)->externalSignature();
447 }
448
externalIdentifierHex() const449 string FunctionDefinition::externalIdentifierHex() const
450 {
451 return TypeProvider::function(*this)->externalIdentifierHex();
452 }
453
annotation() const454 FunctionDefinitionAnnotation& FunctionDefinition::annotation() const
455 {
456 return initAnnotation<FunctionDefinitionAnnotation>();
457 }
458
resolveVirtual(ContractDefinition const & _mostDerivedContract,ContractDefinition const * _searchStart) const459 FunctionDefinition const& FunctionDefinition::resolveVirtual(
460 ContractDefinition const& _mostDerivedContract,
461 ContractDefinition const* _searchStart
462 ) const
463 {
464 solAssert(!isConstructor(), "");
465 solAssert(!name().empty(), "");
466
467 // If we are not doing super-lookup and the function is not virtual, we can stop here.
468 if (_searchStart == nullptr && !virtualSemantics())
469 return *this;
470
471 solAssert(!isFree(), "");
472 solAssert(isOrdinary(), "");
473 solAssert(!libraryFunction(), "");
474
475 FunctionType const* functionType = TypeProvider::function(*this)->asExternallyCallableFunction(false);
476
477 bool foundSearchStart = (_searchStart == nullptr);
478 for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
479 {
480 if (!foundSearchStart && c != _searchStart)
481 continue;
482 else
483 foundSearchStart = true;
484
485 for (FunctionDefinition const* function: c->definedFunctions(name()))
486 if (
487 // With super lookup analysis guarantees that there is an implemented function in the chain.
488 // With virtual lookup there are valid cases where returning an unimplemented one is fine.
489 (function->isImplemented() || _searchStart == nullptr) &&
490 FunctionType(*function).asExternallyCallableFunction(false)->hasEqualParameterTypes(*functionType)
491 )
492 return *function;
493 }
494
495 solAssert(false, "Virtual function " + name() + " not found.");
496 return *this; // not reached
497 }
498
type() const499 Type const* ModifierDefinition::type() const
500 {
501 return TypeProvider::modifier(*this);
502 }
503
annotation() const504 ModifierDefinitionAnnotation& ModifierDefinition::annotation() const
505 {
506 return initAnnotation<ModifierDefinitionAnnotation>();
507 }
508
resolveVirtual(ContractDefinition const & _mostDerivedContract,ContractDefinition const * _searchStart) const509 ModifierDefinition const& ModifierDefinition::resolveVirtual(
510 ContractDefinition const& _mostDerivedContract,
511 ContractDefinition const* _searchStart
512 ) const
513 {
514 solAssert(_searchStart == nullptr, "Used super in connection with modifiers.");
515
516 // If we are not doing super-lookup and the modifier is not virtual, we can stop here.
517 if (_searchStart == nullptr && !virtualSemantics())
518 return *this;
519
520 solAssert(!dynamic_cast<ContractDefinition const&>(*scope()).isLibrary(), "");
521
522 for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
523 {
524 if (_searchStart != nullptr && c != _searchStart)
525 continue;
526 _searchStart = nullptr;
527 for (ModifierDefinition const* modifier: c->functionModifiers())
528 if (modifier->name() == name())
529 return *modifier;
530 }
531 solAssert(false, "Virtual modifier " + name() + " not found.");
532 return *this; // not reached
533 }
534
535
type() const536 Type const* EventDefinition::type() const
537 {
538 return TypeProvider::function(*this);
539 }
540
functionType(bool _internal) const541 FunctionTypePointer EventDefinition::functionType(bool _internal) const
542 {
543 if (_internal)
544 return TypeProvider::function(*this);
545 else
546 return nullptr;
547 }
548
annotation() const549 EventDefinitionAnnotation& EventDefinition::annotation() const
550 {
551 return initAnnotation<EventDefinitionAnnotation>();
552 }
553
type() const554 Type const* ErrorDefinition::type() const
555 {
556 return TypeProvider::function(*this);
557 }
558
functionType(bool _internal) const559 FunctionTypePointer ErrorDefinition::functionType(bool _internal) const
560 {
561 if (_internal)
562 return TypeProvider::function(*this);
563 else
564 return nullptr;
565 }
566
annotation() const567 ErrorDefinitionAnnotation& ErrorDefinition::annotation() const
568 {
569 return initAnnotation<ErrorDefinitionAnnotation>();
570 }
571
sourceUnit() const572 SourceUnit const& Scopable::sourceUnit() const
573 {
574 ASTNode const* s = scope();
575 solAssert(s, "");
576 // will not always be a declaration
577 while (dynamic_cast<Scopable const*>(s) && dynamic_cast<Scopable const*>(s)->scope())
578 s = dynamic_cast<Scopable const*>(s)->scope();
579 return dynamic_cast<SourceUnit const&>(*s);
580 }
581
functionOrModifierDefinition() const582 CallableDeclaration const* Scopable::functionOrModifierDefinition() const
583 {
584 ASTNode const* s = scope();
585 solAssert(s, "");
586 while (dynamic_cast<Scopable const*>(s))
587 {
588 if (auto funDef = dynamic_cast<FunctionDefinition const*>(s))
589 return funDef;
590 if (auto modDef = dynamic_cast<ModifierDefinition const*>(s))
591 return modDef;
592 s = dynamic_cast<Scopable const*>(s)->scope();
593 }
594 return nullptr;
595 }
596
sourceUnitName() const597 string Scopable::sourceUnitName() const
598 {
599 return *sourceUnit().annotation().path;
600 }
601
isEnumValue() const602 bool Declaration::isEnumValue() const
603 {
604 solAssert(scope(), "");
605 return dynamic_cast<EnumDefinition const*>(scope());
606 }
607
isStructMember() const608 bool Declaration::isStructMember() const
609 {
610 solAssert(scope(), "");
611 return dynamic_cast<StructDefinition const*>(scope());
612 }
613
isEventOrErrorParameter() const614 bool Declaration::isEventOrErrorParameter() const
615 {
616 solAssert(scope(), "");
617 return dynamic_cast<EventDefinition const*>(scope()) || dynamic_cast<ErrorDefinition const*>(scope());
618 }
619
isVisibleAsUnqualifiedName() const620 bool Declaration::isVisibleAsUnqualifiedName() const
621 {
622 if (!scope())
623 return true;
624 if (isStructMember() || isEnumValue() || isEventOrErrorParameter())
625 return false;
626 if (auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(scope()))
627 if (!functionDefinition->isImplemented())
628 return false; // parameter of a function without body
629 return true;
630 }
631
annotation() const632 DeclarationAnnotation& Declaration::annotation() const
633 {
634 return initAnnotation<DeclarationAnnotation>();
635 }
636
isLValue() const637 bool VariableDeclaration::isLValue() const
638 {
639 // Constant declared variables are Read-Only
640 return !isConstant();
641 }
642
isLocalVariable() const643 bool VariableDeclaration::isLocalVariable() const
644 {
645 auto s = scope();
646 return
647 dynamic_cast<FunctionTypeName const*>(s) ||
648 dynamic_cast<CallableDeclaration const*>(s) ||
649 dynamic_cast<Block const*>(s) ||
650 dynamic_cast<TryCatchClause const*>(s) ||
651 dynamic_cast<ForStatement const*>(s);
652 }
653
isCallableOrCatchParameter() const654 bool VariableDeclaration::isCallableOrCatchParameter() const
655 {
656 if (isReturnParameter() || isTryCatchParameter())
657 return true;
658
659 vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
660
661 if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
662 parameters = &funTypeName->parameterTypes();
663 else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
664 parameters = &callable->parameters();
665
666 if (parameters)
667 for (auto const& variable: *parameters)
668 if (variable.get() == this)
669 return true;
670 return false;
671 }
672
isLocalOrReturn() const673 bool VariableDeclaration::isLocalOrReturn() const
674 {
675 return isReturnParameter() || (isLocalVariable() && !isCallableOrCatchParameter());
676 }
677
isReturnParameter() const678 bool VariableDeclaration::isReturnParameter() const
679 {
680 vector<ASTPointer<VariableDeclaration>> const* returnParameters = nullptr;
681
682 if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
683 returnParameters = &funTypeName->returnParameterTypes();
684 else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
685 if (callable->returnParameterList())
686 returnParameters = &callable->returnParameterList()->parameters();
687
688 if (returnParameters)
689 for (auto const& variable: *returnParameters)
690 if (variable.get() == this)
691 return true;
692 return false;
693 }
694
isTryCatchParameter() const695 bool VariableDeclaration::isTryCatchParameter() const
696 {
697 return dynamic_cast<TryCatchClause const*>(scope());
698 }
699
isExternalCallableParameter() const700 bool VariableDeclaration::isExternalCallableParameter() const
701 {
702 if (!isCallableOrCatchParameter())
703 return false;
704
705 if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
706 if (callable->visibility() == Visibility::External)
707 return !isReturnParameter();
708
709 return false;
710 }
711
isPublicCallableParameter() const712 bool VariableDeclaration::isPublicCallableParameter() const
713 {
714 if (!isCallableOrCatchParameter())
715 return false;
716
717 if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
718 if (callable->visibility() == Visibility::Public)
719 return !isReturnParameter();
720
721 return false;
722 }
723
isInternalCallableParameter() const724 bool VariableDeclaration::isInternalCallableParameter() const
725 {
726 if (!isCallableOrCatchParameter())
727 return false;
728
729 if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
730 return funTypeName->visibility() == Visibility::Internal;
731 else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
732 return callable->visibility() <= Visibility::Internal;
733 return false;
734 }
735
isConstructorParameter() const736 bool VariableDeclaration::isConstructorParameter() const
737 {
738 if (!isCallableOrCatchParameter())
739 return false;
740 if (auto const* function = dynamic_cast<FunctionDefinition const*>(scope()))
741 return function->isConstructor();
742 return false;
743 }
744
isLibraryFunctionParameter() const745 bool VariableDeclaration::isLibraryFunctionParameter() const
746 {
747 if (!isCallableOrCatchParameter())
748 return false;
749 if (auto const* funDef = dynamic_cast<FunctionDefinition const*>(scope()))
750 return funDef->libraryFunction();
751 return false;
752 }
753
hasReferenceOrMappingType() const754 bool VariableDeclaration::hasReferenceOrMappingType() const
755 {
756 solAssert(typeName().annotation().type, "Can only be called after reference resolution");
757 Type const* type = typeName().annotation().type;
758 return type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type);
759 }
760
isStateVariable() const761 bool VariableDeclaration::isStateVariable() const
762 {
763 return dynamic_cast<ContractDefinition const*>(scope());
764 }
765
isFileLevelVariable() const766 bool VariableDeclaration::isFileLevelVariable() const
767 {
768 return dynamic_cast<SourceUnit const*>(scope());
769 }
770
allowedDataLocations() const771 set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
772 {
773 using Location = VariableDeclaration::Location;
774
775 if (!hasReferenceOrMappingType() || isStateVariable() || isEventOrErrorParameter())
776 return set<Location>{ Location::Unspecified };
777 else if (isCallableOrCatchParameter())
778 {
779 set<Location> locations{ Location::Memory };
780 if (
781 isConstructorParameter() ||
782 isInternalCallableParameter() ||
783 isLibraryFunctionParameter()
784 )
785 locations.insert(Location::Storage);
786 if (!isTryCatchParameter() && !isConstructorParameter())
787 locations.insert(Location::CallData);
788
789 return locations;
790 }
791 else if (isLocalVariable())
792 // Further restrictions will be imposed later on.
793 return set<Location>{ Location::Memory, Location::Storage, Location::CallData };
794 else
795 // Struct members etc.
796 return set<Location>{ Location::Unspecified };
797 }
798
externalIdentifierHex() const799 string VariableDeclaration::externalIdentifierHex() const
800 {
801 solAssert(isStateVariable() && isPublic(), "Can only be called for public state variables");
802 return TypeProvider::function(*this)->externalIdentifierHex();
803 }
804
type() const805 Type const* VariableDeclaration::type() const
806 {
807 return annotation().type;
808 }
809
functionType(bool _internal) const810 FunctionTypePointer VariableDeclaration::functionType(bool _internal) const
811 {
812 if (_internal)
813 return nullptr;
814 switch (visibility())
815 {
816 case Visibility::Default:
817 solAssert(false, "visibility() should not return Default");
818 case Visibility::Private:
819 case Visibility::Internal:
820 return nullptr;
821 case Visibility::Public:
822 case Visibility::External:
823 return TypeProvider::function(*this);
824 }
825
826 // To make the compiler happy
827 return nullptr;
828 }
829
annotation() const830 VariableDeclarationAnnotation& VariableDeclaration::annotation() const
831 {
832 return initAnnotation<VariableDeclarationAnnotation>();
833 }
834
annotation() const835 StatementAnnotation& Statement::annotation() const
836 {
837 return initAnnotation<StatementAnnotation>();
838 }
839
annotation() const840 InlineAssemblyAnnotation& InlineAssembly::annotation() const
841 {
842 return initAnnotation<InlineAssemblyAnnotation>();
843 }
844
annotation() const845 BlockAnnotation& Block::annotation() const
846 {
847 return initAnnotation<BlockAnnotation>();
848 }
849
annotation() const850 TryCatchClauseAnnotation& TryCatchClause::annotation() const
851 {
852 return initAnnotation<TryCatchClauseAnnotation>();
853 }
854
annotation() const855 ForStatementAnnotation& ForStatement::annotation() const
856 {
857 return initAnnotation<ForStatementAnnotation>();
858 }
859
annotation() const860 ReturnAnnotation& Return::annotation() const
861 {
862 return initAnnotation<ReturnAnnotation>();
863 }
864
annotation() const865 ExpressionAnnotation& Expression::annotation() const
866 {
867 return initAnnotation<ExpressionAnnotation>();
868 }
869
annotation() const870 MemberAccessAnnotation& MemberAccess::annotation() const
871 {
872 return initAnnotation<MemberAccessAnnotation>();
873 }
874
annotation() const875 BinaryOperationAnnotation& BinaryOperation::annotation() const
876 {
877 return initAnnotation<BinaryOperationAnnotation>();
878 }
879
annotation() const880 FunctionCallAnnotation& FunctionCall::annotation() const
881 {
882 return initAnnotation<FunctionCallAnnotation>();
883 }
884
sortedArguments() const885 vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const
886 {
887 // normal arguments
888 if (m_names.empty())
889 return arguments();
890
891 // named arguments
892 FunctionTypePointer functionType;
893 if (*annotation().kind == FunctionCallKind::StructConstructorCall)
894 {
895 auto const& type = dynamic_cast<TypeType const&>(*m_expression->annotation().type);
896 auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
897 functionType = structType.constructorType();
898 }
899 else
900 functionType = dynamic_cast<FunctionType const*>(m_expression->annotation().type);
901
902 vector<ASTPointer<Expression const>> sorted;
903 for (auto const& parameterName: functionType->parameterNames())
904 {
905 bool found = false;
906 for (size_t j = 0; j < m_names.size() && !found; j++)
907 if ((found = (parameterName == *m_names.at(j))))
908 // we found the actual parameter position
909 sorted.push_back(m_arguments.at(j));
910 solAssert(found, "");
911 }
912
913 if (!functionType->takesArbitraryParameters())
914 {
915 solAssert(m_arguments.size() == functionType->parameterTypes().size(), "");
916 solAssert(m_arguments.size() == m_names.size(), "");
917 solAssert(m_arguments.size() == sorted.size(), "");
918 }
919
920 return sorted;
921 }
922
annotation() const923 IdentifierAnnotation& Identifier::annotation() const
924 {
925 return initAnnotation<IdentifierAnnotation>();
926 }
927
valueWithoutUnderscores() const928 ASTString Literal::valueWithoutUnderscores() const
929 {
930 return boost::erase_all_copy(value(), "_");
931 }
932
isHexNumber() const933 bool Literal::isHexNumber() const
934 {
935 if (token() != Token::Number)
936 return false;
937 return boost::starts_with(value(), "0x");
938 }
939
looksLikeAddress() const940 bool Literal::looksLikeAddress() const
941 {
942 if (subDenomination() != SubDenomination::None)
943 return false;
944
945 if (!isHexNumber())
946 return false;
947
948 return abs(int(valueWithoutUnderscores().length()) - 42) <= 1;
949 }
950
passesAddressChecksum() const951 bool Literal::passesAddressChecksum() const
952 {
953 solAssert(isHexNumber(), "Expected hex number");
954 return util::passesAddressChecksum(valueWithoutUnderscores(), true);
955 }
956
getChecksummedAddress() const957 string Literal::getChecksummedAddress() const
958 {
959 solAssert(isHexNumber(), "Expected hex number");
960 /// Pad literal to be a proper hex address.
961 string address = valueWithoutUnderscores().substr(2);
962 if (address.length() > 40)
963 return string();
964 address.insert(address.begin(), 40 - address.size(), '0');
965 return util::getChecksummedAddress(address);
966 }
967
successClause() const968 TryCatchClause const* TryStatement::successClause() const
969 {
970 solAssert(m_clauses.size() > 0, "");
971 return m_clauses[0].get();
972 }
973
panicClause() const974 TryCatchClause const* TryStatement::panicClause() const
975 {
976 for (size_t i = 1; i < m_clauses.size(); ++i)
977 if (m_clauses[i]->errorName() == "Panic")
978 return m_clauses[i].get();
979 return nullptr;
980 }
981
errorClause() const982 TryCatchClause const* TryStatement::errorClause() const
983 {
984 for (size_t i = 1; i < m_clauses.size(); ++i)
985 if (m_clauses[i]->errorName() == "Error")
986 return m_clauses[i].get();
987 return nullptr;
988 }
989
fallbackClause() const990 TryCatchClause const* TryStatement::fallbackClause() const
991 {
992 for (size_t i = 1; i < m_clauses.size(); ++i)
993 if (m_clauses[i]->errorName().empty())
994 return m_clauses[i].get();
995 return nullptr;
996 }
997