2014-10-07 16:25:04 +00:00
|
|
|
/*
|
2019-02-13 15:56:46 +00:00
|
|
|
This file is part of solidity.
|
2014-10-07 16:25:04 +00:00
|
|
|
|
2019-02-13 15:56:46 +00:00
|
|
|
solidity is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
2014-10-07 16:25:04 +00:00
|
|
|
|
2019-02-13 15:56:46 +00:00
|
|
|
solidity is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2014-10-07 16:25:04 +00:00
|
|
|
|
2019-02-13 15:56:46 +00:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
2014-10-07 16:25:04 +00:00
|
|
|
*/
|
2020-07-17 14:54:12 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0
|
2014-10-07 16:25:04 +00:00
|
|
|
/**
|
|
|
|
* @author Christian <c@ethdev.com>
|
|
|
|
* @date 2014
|
|
|
|
* Solidity abstract syntax tree.
|
|
|
|
*/
|
|
|
|
|
2015-10-20 22:21:52 +00:00
|
|
|
#include <libsolidity/ast/AST.h>
|
2018-12-17 14:33:15 +00:00
|
|
|
|
2021-03-18 12:28:04 +00:00
|
|
|
#include <libsolidity/ast/CallGraph.h>
|
2015-10-20 22:21:52 +00:00
|
|
|
#include <libsolidity/ast/ASTVisitor.h>
|
|
|
|
#include <libsolidity/ast/AST_accept.h>
|
2019-04-15 13:33:39 +00:00
|
|
|
#include <libsolidity/ast/TypeProvider.h>
|
2022-09-27 12:13:44 +00:00
|
|
|
#include <libsolutil/FunctionSelector.h>
|
2020-01-06 10:52:23 +00:00
|
|
|
#include <libsolutil/Keccak256.h>
|
2015-01-07 15:39:21 +00:00
|
|
|
|
2022-07-06 07:17:59 +00:00
|
|
|
#include <range/v3/range/conversion.hpp>
|
2022-08-17 17:43:51 +00:00
|
|
|
#include <range/v3/view/tail.hpp>
|
2022-07-06 07:17:59 +00:00
|
|
|
#include <range/v3/view/zip.hpp>
|
2022-08-17 17:43:51 +00:00
|
|
|
|
2017-01-24 16:38:06 +00:00
|
|
|
#include <boost/algorithm/string.hpp>
|
2020-04-01 03:04:29 +00:00
|
|
|
|
2017-01-24 16:38:06 +00:00
|
|
|
#include <functional>
|
2020-04-01 03:04:29 +00:00
|
|
|
#include <utility>
|
2017-01-24 16:38:06 +00:00
|
|
|
|
2019-12-11 16:31:36 +00:00
|
|
|
using namespace solidity;
|
|
|
|
using namespace solidity::frontend;
|
2014-10-24 17:06:30 +00:00
|
|
|
|
2022-08-17 17:43:51 +00:00
|
|
|
namespace
|
|
|
|
{
|
2023-08-14 12:39:16 +00:00
|
|
|
TryCatchClause const* findClause(std::vector<ASTPointer<TryCatchClause>> const& _clauses, std::optional<std::string> _errorName = {})
|
2022-08-17 17:43:51 +00:00
|
|
|
{
|
|
|
|
for (auto const& clause: ranges::views::tail(_clauses))
|
|
|
|
if (_errorName.has_value() ? clause->errorName() == _errorName : clause->errorName().empty())
|
|
|
|
return clause.get();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-01 03:04:29 +00:00
|
|
|
ASTNode::ASTNode(int64_t _id, SourceLocation _location):
|
2020-06-02 13:42:46 +00:00
|
|
|
m_id(static_cast<size_t>(_id)),
|
2020-04-01 03:04:29 +00:00
|
|
|
m_location(std::move(_location))
|
2014-10-16 12:08:54 +00:00
|
|
|
{
|
2014-10-23 17:22:30 +00:00
|
|
|
}
|
|
|
|
|
2021-03-24 15:14:58 +00:00
|
|
|
Declaration const* ASTNode::referencedDeclaration(Expression const& _expression)
|
|
|
|
{
|
|
|
|
if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_expression))
|
|
|
|
return memberAccess->annotation().referencedDeclaration;
|
|
|
|
else if (auto const* identifierPath = dynamic_cast<IdentifierPath const*>(&_expression))
|
|
|
|
return identifierPath->annotation().referencedDeclaration;
|
|
|
|
else if (auto const* identifier = dynamic_cast<Identifier const*>(&_expression))
|
|
|
|
return identifier->annotation().referencedDeclaration;
|
|
|
|
else
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-06-03 11:09:13 +00:00
|
|
|
FunctionDefinition const* ASTNode::resolveFunctionCall(FunctionCall const& _functionCall, ContractDefinition const* _mostDerivedContract)
|
|
|
|
{
|
|
|
|
auto const* functionDef = dynamic_cast<FunctionDefinition const*>(
|
|
|
|
ASTNode::referencedDeclaration(_functionCall.expression())
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!functionDef)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (auto const* memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression()))
|
|
|
|
{
|
|
|
|
if (*memberAccess->annotation().requiredLookup == VirtualLookup::Super)
|
|
|
|
{
|
|
|
|
if (auto const typeType = dynamic_cast<TypeType const*>(memberAccess->expression().annotation().type))
|
|
|
|
if (auto const contractType = dynamic_cast<ContractType const*>(typeType->actualType()))
|
|
|
|
{
|
|
|
|
solAssert(_mostDerivedContract, "");
|
|
|
|
solAssert(contractType->isSuper(), "");
|
|
|
|
ContractDefinition const* superContract = contractType->contractDefinition().superContract(*_mostDerivedContract);
|
|
|
|
|
|
|
|
return &functionDef->resolveVirtual(
|
|
|
|
*_mostDerivedContract,
|
|
|
|
superContract
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
solAssert(*memberAccess->annotation().requiredLookup == VirtualLookup::Static, "");
|
|
|
|
}
|
|
|
|
else if (auto const* identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
|
|
|
|
{
|
|
|
|
solAssert(*identifier->annotation().requiredLookup == VirtualLookup::Virtual, "");
|
|
|
|
if (functionDef->virtualSemantics())
|
|
|
|
{
|
|
|
|
solAssert(_mostDerivedContract, "");
|
|
|
|
return &functionDef->resolveVirtual(*_mostDerivedContract);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
solAssert(false, "");
|
|
|
|
|
|
|
|
return functionDef;
|
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
ASTAnnotation& ASTNode::annotation() const
|
|
|
|
{
|
|
|
|
if (!m_annotation)
|
2023-08-14 12:39:16 +00:00
|
|
|
m_annotation = std::make_unique<ASTAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
return *m_annotation;
|
2015-01-22 00:02:38 +00:00
|
|
|
}
|
|
|
|
|
2015-12-15 14:46:03 +00:00
|
|
|
SourceUnitAnnotation& SourceUnit::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<SourceUnitAnnotation>();
|
2015-12-15 14:46:03 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::set<SourceUnit const*> SourceUnit::referencedSourceUnits(bool _recurse, std::set<SourceUnit const*> _skipList) const
|
2017-07-12 23:08:28 +00:00
|
|
|
{
|
2023-08-14 12:39:16 +00:00
|
|
|
std::set<SourceUnit const*> sourceUnits;
|
2017-07-12 23:08:28 +00:00
|
|
|
for (ImportDirective const* importDirective: filteredNodes<ImportDirective>(nodes()))
|
|
|
|
{
|
2017-07-13 00:07:23 +00:00
|
|
|
auto const& sourceUnit = importDirective->annotation().sourceUnit;
|
|
|
|
if (!_skipList.count(sourceUnit))
|
2017-07-12 23:17:25 +00:00
|
|
|
{
|
2017-07-13 00:07:23 +00:00
|
|
|
_skipList.insert(sourceUnit);
|
|
|
|
sourceUnits.insert(sourceUnit);
|
|
|
|
if (_recurse)
|
2017-07-13 23:17:52 +00:00
|
|
|
sourceUnits += sourceUnit->referencedSourceUnits(true, _skipList);
|
2017-07-12 23:17:25 +00:00
|
|
|
}
|
2017-07-12 23:08:28 +00:00
|
|
|
}
|
|
|
|
return sourceUnits;
|
|
|
|
}
|
|
|
|
|
2015-12-09 16:35:20 +00:00
|
|
|
ImportAnnotation& ImportDirective::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<ImportAnnotation>();
|
2015-12-09 16:35:20 +00:00
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* ImportDirective::type() const
|
2015-12-15 14:46:03 +00:00
|
|
|
{
|
|
|
|
solAssert(!!annotation().sourceUnit, "");
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::module(*annotation().sourceUnit);
|
2015-12-15 14:46:03 +00:00
|
|
|
}
|
|
|
|
|
2020-01-14 13:00:51 +00:00
|
|
|
bool ContractDefinition::derivesFrom(ContractDefinition const& _base) const
|
|
|
|
{
|
|
|
|
return util::contains(annotation().linearizedBaseContracts, &_base);
|
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::map<util::FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions(bool _includeInheritedFunctions) const
|
2014-11-11 16:41:48 +00:00
|
|
|
{
|
2020-04-08 22:08:49 +00:00
|
|
|
auto exportedFunctionList = interfaceFunctionList(_includeInheritedFunctions);
|
2015-01-23 15:37:06 +00:00
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::map<util::FixedHash<4>, FunctionTypePointer> exportedFunctions;
|
2015-01-23 15:37:06 +00:00
|
|
|
for (auto const& it: exportedFunctionList)
|
2015-01-29 15:39:30 +00:00
|
|
|
exportedFunctions.insert(it);
|
2015-01-22 16:40:22 +00:00
|
|
|
|
2015-09-10 08:17:17 +00:00
|
|
|
solAssert(
|
|
|
|
exportedFunctionList.size() == exportedFunctions.size(),
|
2015-09-08 12:30:21 +00:00
|
|
|
"Hash collision at Function Definition Hash calculation"
|
|
|
|
);
|
2014-11-11 16:41:48 +00:00
|
|
|
|
|
|
|
return exportedFunctions;
|
|
|
|
}
|
|
|
|
|
2015-08-31 16:44:29 +00:00
|
|
|
FunctionDefinition const* ContractDefinition::constructor() const
|
2014-12-12 15:49:26 +00:00
|
|
|
{
|
2015-11-23 22:57:17 +00:00
|
|
|
for (FunctionDefinition const* f: definedFunctions())
|
2015-01-20 14:58:04 +00:00
|
|
|
if (f->isConstructor())
|
2015-11-23 22:57:17 +00:00
|
|
|
return f;
|
2014-12-12 15:49:26 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-17 19:08:17 +00:00
|
|
|
bool ContractDefinition::canBeDeployed() const
|
|
|
|
{
|
2020-06-10 16:19:42 +00:00
|
|
|
return !abstract() && !isInterface();
|
2019-01-17 19:08:17 +00:00
|
|
|
}
|
|
|
|
|
2015-08-31 16:44:29 +00:00
|
|
|
FunctionDefinition const* ContractDefinition::fallbackFunction() const
|
2015-01-29 21:50:20 +00:00
|
|
|
{
|
2015-09-16 14:56:30 +00:00
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
2015-11-23 22:57:17 +00:00
|
|
|
for (FunctionDefinition const* f: contract->definedFunctions())
|
2017-07-27 19:55:55 +00:00
|
|
|
if (f->isFallback())
|
2015-11-23 22:57:17 +00:00
|
|
|
return f;
|
2015-01-29 21:50:20 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-09-09 16:22:02 +00:00
|
|
|
FunctionDefinition const* ContractDefinition::receiveFunction() const
|
|
|
|
{
|
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
|
|
|
for (FunctionDefinition const* f: contract->definedFunctions())
|
|
|
|
if (f->isReceive())
|
|
|
|
return f;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<EventDefinition const*> const& ContractDefinition::definedInterfaceEvents() const
|
2015-01-31 13:41:11 +00:00
|
|
|
{
|
2020-05-13 17:57:20 +00:00
|
|
|
return m_interfaceEvents.init([&]{
|
2023-08-14 12:39:16 +00:00
|
|
|
std::set<std::string> eventsSeen;
|
|
|
|
std::vector<EventDefinition const*> interfaceEvents;
|
2020-05-13 17:57:20 +00:00
|
|
|
|
2015-09-16 14:56:30 +00:00
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
2015-11-23 22:57:17 +00:00
|
|
|
for (EventDefinition const* e: contract->events())
|
2017-08-25 09:41:48 +00:00
|
|
|
{
|
|
|
|
/// NOTE: this requires the "internal" version of an Event,
|
|
|
|
/// though here internal strictly refers to visibility,
|
|
|
|
/// and not to function encoding (jump vs. call)
|
2021-02-23 13:13:52 +00:00
|
|
|
FunctionType const* functionType = e->functionType(true);
|
|
|
|
solAssert(functionType, "");
|
2023-08-14 12:39:16 +00:00
|
|
|
std::string eventSignature = functionType->externalSignature();
|
2017-08-25 09:41:48 +00:00
|
|
|
if (eventsSeen.count(eventSignature) == 0)
|
2015-01-31 13:41:11 +00:00
|
|
|
{
|
2017-08-25 09:41:48 +00:00
|
|
|
eventsSeen.insert(eventSignature);
|
2020-05-13 17:57:20 +00:00
|
|
|
interfaceEvents.push_back(e);
|
2015-01-31 13:41:11 +00:00
|
|
|
}
|
2017-08-25 09:41:48 +00:00
|
|
|
}
|
2020-05-13 17:57:20 +00:00
|
|
|
return interfaceEvents;
|
|
|
|
});
|
2015-01-31 13:41:11 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<EventDefinition const*> const ContractDefinition::usedInterfaceEvents() const
|
2022-02-01 14:42:08 +00:00
|
|
|
{
|
|
|
|
solAssert(annotation().creationCallGraph.set(), "");
|
|
|
|
|
2022-03-07 04:25:35 +00:00
|
|
|
return util::convertContainer<std::vector<EventDefinition const*>>(
|
2022-02-01 14:42:08 +00:00
|
|
|
(*annotation().creationCallGraph)->emittedEvents +
|
|
|
|
(*annotation().deployedCallGraph)->emittedEvents
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<EventDefinition const*> ContractDefinition::interfaceEvents(bool _requireCallGraph) const
|
2021-02-23 13:13:52 +00:00
|
|
|
{
|
2023-08-14 12:39:16 +00:00
|
|
|
std::set<EventDefinition const*, CompareByID> result;
|
2021-02-23 13:13:52 +00:00
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
|
|
|
result += contract->events();
|
|
|
|
solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set());
|
|
|
|
if (_requireCallGraph)
|
|
|
|
solAssert(annotation().creationCallGraph.set());
|
|
|
|
if (annotation().creationCallGraph.set())
|
|
|
|
result += usedInterfaceEvents();
|
|
|
|
// We could filter out all events that do not have an external interface
|
|
|
|
// if _requireCallGraph is false.
|
2023-08-14 12:39:16 +00:00
|
|
|
return util::convertContainer<std::vector<EventDefinition const*>>(std::move(result));
|
2021-02-23 13:13:52 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<ErrorDefinition const*> ContractDefinition::interfaceErrors(bool _requireCallGraph) const
|
2021-01-28 11:56:22 +00:00
|
|
|
{
|
2023-08-14 12:39:16 +00:00
|
|
|
std::set<ErrorDefinition const*, CompareByID> result;
|
2021-01-28 11:56:22 +00:00
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
|
|
|
result += filteredNodes<ErrorDefinition>(contract->m_subNodes);
|
2021-03-18 12:28:04 +00:00
|
|
|
solAssert(annotation().creationCallGraph.set() == annotation().deployedCallGraph.set(), "");
|
|
|
|
if (_requireCallGraph)
|
|
|
|
solAssert(annotation().creationCallGraph.set(), "");
|
|
|
|
if (annotation().creationCallGraph.set())
|
2022-02-01 14:42:08 +00:00
|
|
|
result +=
|
|
|
|
(*annotation().creationCallGraph)->usedErrors +
|
|
|
|
(*annotation().deployedCallGraph)->usedErrors;
|
2023-08-14 12:39:16 +00:00
|
|
|
return util::convertContainer<std::vector<ErrorDefinition const*>>(std::move(result));
|
2021-01-28 11:56:22 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::interfaceFunctionList(bool _includeInheritedFunctions) const
|
2015-01-16 16:50:10 +00:00
|
|
|
{
|
2020-05-13 17:59:15 +00:00
|
|
|
return m_interfaceFunctionList[_includeInheritedFunctions].init([&]{
|
2023-08-14 12:39:16 +00:00
|
|
|
std::set<std::string> signaturesSeen;
|
|
|
|
std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>> interfaceFunctionList;
|
2020-05-13 17:59:15 +00:00
|
|
|
|
2015-09-16 14:56:30 +00:00
|
|
|
for (ContractDefinition const* contract: annotation().linearizedBaseContracts)
|
2015-01-22 16:40:22 +00:00
|
|
|
{
|
2020-04-08 22:08:49 +00:00
|
|
|
if (_includeInheritedFunctions == false && contract != this)
|
|
|
|
continue;
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<FunctionTypePointer> functions;
|
2015-11-23 22:57:17 +00:00
|
|
|
for (FunctionDefinition const* f: contract->definedFunctions())
|
2015-10-16 11:11:16 +00:00
|
|
|
if (f->isPartOfExternalInterface())
|
2020-01-07 10:42:37 +00:00
|
|
|
functions.push_back(TypeProvider::function(*f, FunctionType::Kind::External));
|
2015-11-23 22:57:17 +00:00
|
|
|
for (VariableDeclaration const* v: contract->stateVariables())
|
2015-10-16 11:11:16 +00:00
|
|
|
if (v->isPartOfExternalInterface())
|
2019-04-17 11:40:50 +00:00
|
|
|
functions.push_back(TypeProvider::function(*v));
|
2015-10-16 11:11:16 +00:00
|
|
|
for (FunctionTypePointer const& fun: functions)
|
2015-03-01 03:34:39 +00:00
|
|
|
{
|
2015-10-16 11:11:16 +00:00
|
|
|
if (!fun->interfaceFunctionType())
|
|
|
|
// Fails hopefully because we already registered the error
|
2015-06-26 14:52:30 +00:00
|
|
|
continue;
|
2023-08-14 12:39:16 +00:00
|
|
|
std::string functionSignature = fun->externalSignature();
|
2015-06-26 14:52:30 +00:00
|
|
|
if (signaturesSeen.count(functionSignature) == 0)
|
2015-01-16 16:50:10 +00:00
|
|
|
{
|
2015-03-01 03:34:39 +00:00
|
|
|
signaturesSeen.insert(functionSignature);
|
2022-09-27 12:13:44 +00:00
|
|
|
interfaceFunctionList.emplace_back(util::selectorFromSignatureH32(functionSignature), fun);
|
2015-01-16 16:50:10 +00:00
|
|
|
}
|
2015-03-01 03:34:39 +00:00
|
|
|
}
|
2015-01-22 16:40:22 +00:00
|
|
|
}
|
2020-05-13 17:59:15 +00:00
|
|
|
|
|
|
|
return interfaceFunctionList;
|
|
|
|
});
|
2015-01-14 09:16:58 +00:00
|
|
|
}
|
|
|
|
|
2020-11-11 18:36:50 +00:00
|
|
|
uint32_t ContractDefinition::interfaceId() const
|
2020-09-14 10:39:38 +00:00
|
|
|
{
|
2020-11-11 18:36:50 +00:00
|
|
|
uint32_t result{0};
|
2020-09-14 10:39:38 +00:00
|
|
|
for (auto const& function: interfaceFunctionList(false))
|
2021-09-16 14:33:28 +00:00
|
|
|
result ^= fromBigEndian<uint32_t>(function.first.ref());
|
2020-09-14 10:39:38 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* ContractDefinition::type() const
|
2015-02-10 12:40:21 +00:00
|
|
|
{
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::typeType(TypeProvider::contract(*this));
|
2015-01-19 20:05:47 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
ContractDefinitionAnnotation& ContractDefinition::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<ContractDefinitionAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
2020-04-06 15:30:01 +00:00
|
|
|
ContractDefinition const* ContractDefinition::superContract(ContractDefinition const& _mostDerivedContract) const
|
|
|
|
{
|
|
|
|
auto const& hierarchy = _mostDerivedContract.annotation().linearizedBaseContracts;
|
|
|
|
auto it = find(hierarchy.begin(), hierarchy.end(), this);
|
|
|
|
solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy.");
|
|
|
|
++it;
|
|
|
|
if (it == hierarchy.end())
|
|
|
|
return nullptr;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
solAssert(*it != this, "");
|
|
|
|
return *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition const& _mostDerivedContract) const
|
|
|
|
{
|
|
|
|
ContractDefinition const* next = superContract(_mostDerivedContract);
|
|
|
|
if (next == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
|
|
|
|
if (c == next || next == nullptr)
|
|
|
|
{
|
|
|
|
if (c->constructor())
|
|
|
|
return c->constructor();
|
|
|
|
next = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::multimap<std::string, FunctionDefinition const*> const& ContractDefinition::definedFunctionsByName() const
|
2021-06-01 12:55:35 +00:00
|
|
|
{
|
|
|
|
return m_definedFunctionsByName.init([&]{
|
|
|
|
std::multimap<std::string, FunctionDefinition const*> result;
|
|
|
|
for (FunctionDefinition const* fun: filteredNodes<FunctionDefinition>(m_subNodes))
|
|
|
|
result.insert({fun->name(), fun});
|
|
|
|
return result;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
TypeNameAnnotation& TypeName::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<TypeNameAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
2021-07-28 08:32:59 +00:00
|
|
|
Type const* UserDefinedValueTypeDefinition::type() const
|
|
|
|
{
|
|
|
|
solAssert(m_underlyingType->annotation().type, "");
|
|
|
|
return TypeProvider::typeType(TypeProvider::userDefinedValueType(*this));
|
|
|
|
}
|
|
|
|
|
2021-09-14 15:31:00 +00:00
|
|
|
TypeDeclarationAnnotation& UserDefinedValueTypeDefinition::annotation() const
|
|
|
|
{
|
|
|
|
return initAnnotation<TypeDeclarationAnnotation>();
|
|
|
|
}
|
|
|
|
|
2022-07-06 07:17:59 +00:00
|
|
|
std::vector<std::pair<ASTPointer<IdentifierPath>, std::optional<Token>>> UsingForDirective::functionsAndOperators() const
|
|
|
|
{
|
2023-08-14 12:39:16 +00:00
|
|
|
return ranges::zip_view(m_functionsOrLibrary, m_operators) | ranges::to<std::vector>;
|
2022-07-06 07:17:59 +00:00
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* StructDefinition::type() const
|
2015-01-22 00:02:38 +00:00
|
|
|
{
|
2020-04-14 14:36:37 +00:00
|
|
|
solAssert(annotation().recursive.has_value(), "Requested struct type before DeclarationTypeChecker.");
|
2019-04-15 15:28:32 +00:00
|
|
|
return TypeProvider::typeType(TypeProvider::structType(*this, DataLocation::Storage));
|
2015-01-22 00:02:38 +00:00
|
|
|
}
|
|
|
|
|
2020-04-14 14:36:37 +00:00
|
|
|
StructDeclarationAnnotation& StructDefinition::annotation() const
|
2015-10-05 15:19:23 +00:00
|
|
|
{
|
2020-04-14 14:36:37 +00:00
|
|
|
return initAnnotation<StructDeclarationAnnotation>();
|
2015-10-05 15:19:23 +00:00
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* EnumValue::type() const
|
2014-12-03 06:46:55 +00:00
|
|
|
{
|
2015-09-16 14:56:30 +00:00
|
|
|
auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
|
|
|
|
solAssert(parentDef, "Enclosing Scope of EnumValue was not set");
|
2019-04-15 13:33:39 +00:00
|
|
|
return TypeProvider::enumType(*parentDef);
|
2014-12-03 06:46:55 +00:00
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* EnumDefinition::type() const
|
2015-02-09 17:08:56 +00:00
|
|
|
{
|
2019-04-15 13:33:39 +00:00
|
|
|
return TypeProvider::typeType(TypeProvider::enumType(*this));
|
2015-02-09 17:08:56 +00:00
|
|
|
}
|
|
|
|
|
2015-10-05 15:19:23 +00:00
|
|
|
TypeDeclarationAnnotation& EnumDefinition::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<TypeDeclarationAnnotation>();
|
2015-10-05 15:19:23 +00:00
|
|
|
}
|
|
|
|
|
2020-06-09 15:56:58 +00:00
|
|
|
bool FunctionDefinition::libraryFunction() const
|
2018-03-14 15:56:06 +00:00
|
|
|
{
|
2020-06-09 15:56:58 +00:00
|
|
|
if (auto const* contractDef = dynamic_cast<ContractDefinition const*>(scope()))
|
|
|
|
return contractDef->isLibrary();
|
|
|
|
return false;
|
2018-03-14 15:56:06 +00:00
|
|
|
}
|
|
|
|
|
2020-06-18 15:34:05 +00:00
|
|
|
Visibility FunctionDefinition::defaultVisibility() const
|
|
|
|
{
|
|
|
|
solAssert(!isConstructor(), "");
|
2020-06-16 01:35:09 +00:00
|
|
|
return isFree() ? Visibility::Internal : Declaration::defaultVisibility();
|
2020-06-18 15:34:05 +00:00
|
|
|
}
|
|
|
|
|
2017-12-30 12:44:09 +00:00
|
|
|
FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
|
2017-01-10 15:26:13 +00:00
|
|
|
{
|
|
|
|
if (_internal)
|
|
|
|
{
|
|
|
|
switch (visibility())
|
|
|
|
{
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::Default:
|
2017-01-10 15:26:13 +00:00
|
|
|
solAssert(false, "visibility() should not return Default");
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::Private:
|
|
|
|
case Visibility::Internal:
|
|
|
|
case Visibility::Public:
|
2020-01-07 10:42:37 +00:00
|
|
|
return TypeProvider::function(*this, FunctionType::Kind::Internal);
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::External:
|
2017-01-10 15:26:13 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (visibility())
|
|
|
|
{
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::Default:
|
2017-01-10 15:26:13 +00:00
|
|
|
solAssert(false, "visibility() should not return Default");
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::Private:
|
|
|
|
case Visibility::Internal:
|
2017-01-10 15:26:13 +00:00
|
|
|
return {};
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::Public:
|
|
|
|
case Visibility::External:
|
2020-01-07 10:42:37 +00:00
|
|
|
return TypeProvider::function(*this, FunctionType::Kind::External);
|
2017-01-10 15:26:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// To make the compiler happy
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* FunctionDefinition::type() const
|
2015-01-22 00:02:38 +00:00
|
|
|
{
|
2019-12-10 14:54:09 +00:00
|
|
|
solAssert(visibility() != Visibility::External, "");
|
2020-01-07 10:42:37 +00:00
|
|
|
return TypeProvider::function(*this, FunctionType::Kind::Internal);
|
2015-01-22 00:02:38 +00:00
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* FunctionDefinition::typeViaContractName() const
|
2020-01-14 13:00:51 +00:00
|
|
|
{
|
2020-05-04 16:38:00 +00:00
|
|
|
if (libraryFunction())
|
2020-05-25 17:30:17 +00:00
|
|
|
{
|
|
|
|
if (isPublic())
|
2020-05-26 08:48:17 +00:00
|
|
|
return FunctionType(*this).asExternallyCallableFunction(true);
|
2020-05-25 17:30:17 +00:00
|
|
|
else
|
|
|
|
return TypeProvider::function(*this, FunctionType::Kind::Internal);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return TypeProvider::function(*this, FunctionType::Kind::Declaration);
|
2020-01-14 13:00:51 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::string FunctionDefinition::externalSignature() const
|
2015-01-06 16:42:38 +00:00
|
|
|
{
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this)->externalSignature();
|
2015-01-06 16:42:38 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::string FunctionDefinition::externalIdentifierHex() const
|
2019-12-09 00:26:23 +00:00
|
|
|
{
|
|
|
|
return TypeProvider::function(*this)->externalIdentifierHex();
|
|
|
|
}
|
|
|
|
|
2015-10-26 14:13:36 +00:00
|
|
|
FunctionDefinitionAnnotation& FunctionDefinition::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<FunctionDefinitionAnnotation>();
|
2015-10-26 14:13:36 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 17:25:59 +00:00
|
|
|
FunctionDefinition const& FunctionDefinition::resolveVirtual(
|
|
|
|
ContractDefinition const& _mostDerivedContract,
|
|
|
|
ContractDefinition const* _searchStart
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
solAssert(!isConstructor(), "");
|
2021-06-01 12:55:35 +00:00
|
|
|
solAssert(!name().empty(), "");
|
2021-06-01 15:16:09 +00:00
|
|
|
|
2020-03-24 17:25:59 +00:00
|
|
|
// If we are not doing super-lookup and the function is not virtual, we can stop here.
|
|
|
|
if (_searchStart == nullptr && !virtualSemantics())
|
|
|
|
return *this;
|
|
|
|
|
2020-05-04 16:38:00 +00:00
|
|
|
solAssert(!isFree(), "");
|
|
|
|
solAssert(isOrdinary(), "");
|
|
|
|
solAssert(!libraryFunction(), "");
|
2020-03-24 17:25:59 +00:00
|
|
|
|
2022-03-24 14:03:02 +00:00
|
|
|
// We actually do not want the externally callable function here.
|
|
|
|
// This is just to add an assertion since the comparison used to be less strict.
|
|
|
|
FunctionType const* externalFunctionType = TypeProvider::function(*this)->asExternallyCallableFunction(false);
|
2020-03-24 17:25:59 +00:00
|
|
|
|
2021-06-01 15:16:09 +00:00
|
|
|
bool foundSearchStart = (_searchStart == nullptr);
|
2020-03-24 17:25:59 +00:00
|
|
|
for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
|
|
|
|
{
|
2021-06-01 15:16:09 +00:00
|
|
|
if (!foundSearchStart && c != _searchStart)
|
2020-03-24 17:25:59 +00:00
|
|
|
continue;
|
2021-06-01 15:16:09 +00:00
|
|
|
else
|
|
|
|
foundSearchStart = true;
|
|
|
|
|
2021-06-01 12:55:35 +00:00
|
|
|
for (FunctionDefinition const* function: c->definedFunctions(name()))
|
2020-03-24 17:25:59 +00:00
|
|
|
if (
|
2021-06-01 15:16:09 +00:00
|
|
|
// With super lookup analysis guarantees that there is an implemented function in the chain.
|
|
|
|
// With virtual lookup there are valid cases where returning an unimplemented one is fine.
|
|
|
|
(function->isImplemented() || _searchStart == nullptr) &&
|
2022-03-24 14:03:02 +00:00
|
|
|
FunctionType(*function).asExternallyCallableFunction(false)->hasEqualParameterTypes(*externalFunctionType)
|
2020-03-24 17:25:59 +00:00
|
|
|
)
|
2022-03-24 14:03:02 +00:00
|
|
|
{
|
|
|
|
solAssert(FunctionType(*function).hasEqualParameterTypes(*TypeProvider::function(*this)));
|
2020-03-24 17:25:59 +00:00
|
|
|
return *function;
|
2022-03-24 14:03:02 +00:00
|
|
|
}
|
2020-03-24 17:25:59 +00:00
|
|
|
}
|
2021-06-01 15:16:09 +00:00
|
|
|
|
2020-03-24 17:25:59 +00:00
|
|
|
solAssert(false, "Virtual function " + name() + " not found.");
|
|
|
|
return *this; // not reached
|
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* ModifierDefinition::type() const
|
2015-01-22 00:02:38 +00:00
|
|
|
{
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::modifier(*this);
|
2015-02-14 00:22:44 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 14:13:36 +00:00
|
|
|
ModifierDefinitionAnnotation& ModifierDefinition::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<ModifierDefinitionAnnotation>();
|
2015-10-26 14:13:36 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 17:25:59 +00:00
|
|
|
ModifierDefinition const& ModifierDefinition::resolveVirtual(
|
|
|
|
ContractDefinition const& _mostDerivedContract,
|
|
|
|
ContractDefinition const* _searchStart
|
|
|
|
) const
|
|
|
|
{
|
2021-12-28 17:29:20 +00:00
|
|
|
// Super is not possible with modifiers
|
2020-03-24 17:25:59 +00:00
|
|
|
solAssert(_searchStart == nullptr, "Used super in connection with modifiers.");
|
|
|
|
|
2021-12-28 17:29:20 +00:00
|
|
|
// The modifier is not virtual, we can stop here.
|
|
|
|
if (!virtualSemantics())
|
2020-03-24 17:25:59 +00:00
|
|
|
return *this;
|
|
|
|
|
|
|
|
solAssert(!dynamic_cast<ContractDefinition const&>(*scope()).isLibrary(), "");
|
|
|
|
|
|
|
|
for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
|
|
|
|
for (ModifierDefinition const* modifier: c->functionModifiers())
|
|
|
|
if (modifier->name() == name())
|
|
|
|
return *modifier;
|
2021-12-28 17:29:20 +00:00
|
|
|
|
2020-03-24 17:25:59 +00:00
|
|
|
solAssert(false, "Virtual modifier " + name() + " not found.");
|
|
|
|
return *this; // not reached
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* EventDefinition::type() const
|
2015-02-17 15:21:38 +00:00
|
|
|
{
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this);
|
2015-09-16 14:56:30 +00:00
|
|
|
}
|
2015-03-08 22:26:36 +00:00
|
|
|
|
2017-12-30 12:44:09 +00:00
|
|
|
FunctionTypePointer EventDefinition::functionType(bool _internal) const
|
2017-01-10 17:55:36 +00:00
|
|
|
{
|
|
|
|
if (_internal)
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this);
|
2017-01-10 17:55:36 +00:00
|
|
|
else
|
2019-04-15 13:33:39 +00:00
|
|
|
return nullptr;
|
2017-01-10 17:55:36 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 14:13:36 +00:00
|
|
|
EventDefinitionAnnotation& EventDefinition::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<EventDefinitionAnnotation>();
|
2015-10-26 14:13:36 +00:00
|
|
|
}
|
|
|
|
|
2021-01-28 11:56:22 +00:00
|
|
|
Type const* ErrorDefinition::type() const
|
|
|
|
{
|
|
|
|
return TypeProvider::function(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionTypePointer ErrorDefinition::functionType(bool _internal) const
|
|
|
|
{
|
|
|
|
if (_internal)
|
|
|
|
return TypeProvider::function(*this);
|
|
|
|
else
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ErrorDefinitionAnnotation& ErrorDefinition::annotation() const
|
|
|
|
{
|
|
|
|
return initAnnotation<ErrorDefinitionAnnotation>();
|
|
|
|
}
|
|
|
|
|
2018-02-14 00:48:40 +00:00
|
|
|
SourceUnit const& Scopable::sourceUnit() const
|
|
|
|
{
|
|
|
|
ASTNode const* s = scope();
|
|
|
|
solAssert(s, "");
|
2018-08-16 05:42:46 +00:00
|
|
|
// will not always be a declaration
|
2018-02-14 00:48:40 +00:00
|
|
|
while (dynamic_cast<Scopable const*>(s) && dynamic_cast<Scopable const*>(s)->scope())
|
|
|
|
s = dynamic_cast<Scopable const*>(s)->scope();
|
|
|
|
return dynamic_cast<SourceUnit const&>(*s);
|
|
|
|
}
|
|
|
|
|
2019-05-07 09:51:32 +00:00
|
|
|
CallableDeclaration const* Scopable::functionOrModifierDefinition() const
|
|
|
|
{
|
|
|
|
ASTNode const* s = scope();
|
|
|
|
solAssert(s, "");
|
|
|
|
while (dynamic_cast<Scopable const*>(s))
|
|
|
|
{
|
|
|
|
if (auto funDef = dynamic_cast<FunctionDefinition const*>(s))
|
|
|
|
return funDef;
|
|
|
|
if (auto modDef = dynamic_cast<ModifierDefinition const*>(s))
|
|
|
|
return modDef;
|
|
|
|
s = dynamic_cast<Scopable const*>(s)->scope();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::string Scopable::sourceUnitName() const
|
2018-02-14 00:48:40 +00:00
|
|
|
{
|
2020-09-10 10:01:23 +00:00
|
|
|
return *sourceUnit().annotation().path;
|
2018-02-14 00:48:40 +00:00
|
|
|
}
|
|
|
|
|
2020-09-26 22:00:56 +00:00
|
|
|
bool Declaration::isEnumValue() const
|
|
|
|
{
|
|
|
|
solAssert(scope(), "");
|
|
|
|
return dynamic_cast<EnumDefinition const*>(scope());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Declaration::isStructMember() const
|
|
|
|
{
|
|
|
|
solAssert(scope(), "");
|
|
|
|
return dynamic_cast<StructDefinition const*>(scope());
|
|
|
|
}
|
|
|
|
|
2021-01-28 11:56:22 +00:00
|
|
|
bool Declaration::isEventOrErrorParameter() const
|
2020-09-26 22:00:56 +00:00
|
|
|
{
|
|
|
|
solAssert(scope(), "");
|
2021-01-28 11:56:22 +00:00
|
|
|
return dynamic_cast<EventDefinition const*>(scope()) || dynamic_cast<ErrorDefinition const*>(scope());
|
2020-09-26 22:00:56 +00:00
|
|
|
}
|
|
|
|
|
2021-02-08 04:50:58 +00:00
|
|
|
bool Declaration::isVisibleAsUnqualifiedName() const
|
|
|
|
{
|
|
|
|
if (!scope())
|
|
|
|
return true;
|
|
|
|
if (isStructMember() || isEnumValue() || isEventOrErrorParameter())
|
|
|
|
return false;
|
|
|
|
if (auto const* functionDefinition = dynamic_cast<FunctionDefinition const*>(scope()))
|
|
|
|
if (!functionDefinition->isImplemented())
|
|
|
|
return false; // parameter of a function without body
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-12-19 23:04:46 +00:00
|
|
|
DeclarationAnnotation& Declaration::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<DeclarationAnnotation>();
|
2019-12-19 23:04:46 +00:00
|
|
|
}
|
|
|
|
|
2015-09-16 14:56:30 +00:00
|
|
|
bool VariableDeclaration::isLValue() const
|
|
|
|
{
|
2019-08-12 15:06:10 +00:00
|
|
|
// Constant declared variables are Read-Only
|
2020-06-22 16:10:18 +00:00
|
|
|
return !isConstant();
|
2015-02-17 15:21:38 +00:00
|
|
|
}
|
|
|
|
|
2018-02-09 15:53:52 +00:00
|
|
|
bool VariableDeclaration::isLocalVariable() const
|
|
|
|
{
|
|
|
|
auto s = scope();
|
|
|
|
return
|
2018-08-07 13:58:34 +00:00
|
|
|
dynamic_cast<FunctionTypeName const*>(s) ||
|
2018-02-09 15:53:52 +00:00
|
|
|
dynamic_cast<CallableDeclaration const*>(s) ||
|
|
|
|
dynamic_cast<Block const*>(s) ||
|
2019-09-02 14:17:02 +00:00
|
|
|
dynamic_cast<TryCatchClause const*>(s) ||
|
2018-02-09 15:53:52 +00:00
|
|
|
dynamic_cast<ForStatement const*>(s);
|
|
|
|
}
|
|
|
|
|
2019-09-05 18:02:34 +00:00
|
|
|
bool VariableDeclaration::isCallableOrCatchParameter() const
|
2015-06-05 09:07:50 +00:00
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
if (isReturnParameter() || isTryCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
return true;
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<ASTPointer<VariableDeclaration>> const* parameters = nullptr;
|
2018-08-07 13:58:34 +00:00
|
|
|
|
|
|
|
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
|
|
|
|
parameters = &funTypeName->parameterTypes();
|
|
|
|
else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
|
|
|
parameters = &callable->parameters();
|
|
|
|
|
|
|
|
if (parameters)
|
|
|
|
for (auto const& variable: *parameters)
|
2015-06-09 12:26:08 +00:00
|
|
|
if (variable.get() == this)
|
|
|
|
return true;
|
2015-06-05 09:07:50 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-07-06 09:05:05 +00:00
|
|
|
bool VariableDeclaration::isLocalOrReturn() const
|
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
return isReturnParameter() || (isLocalVariable() && !isCallableOrCatchParameter());
|
2017-07-06 09:05:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool VariableDeclaration::isReturnParameter() const
|
|
|
|
{
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<ASTPointer<VariableDeclaration>> const* returnParameters = nullptr;
|
2018-08-07 13:58:34 +00:00
|
|
|
|
|
|
|
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
|
|
|
|
returnParameters = &funTypeName->returnParameterTypes();
|
|
|
|
else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
|
|
|
if (callable->returnParameterList())
|
|
|
|
returnParameters = &callable->returnParameterList()->parameters();
|
|
|
|
|
|
|
|
if (returnParameters)
|
|
|
|
for (auto const& variable: *returnParameters)
|
2017-07-06 09:05:05 +00:00
|
|
|
if (variable.get() == this)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-09-05 18:02:34 +00:00
|
|
|
bool VariableDeclaration::isTryCatchParameter() const
|
|
|
|
{
|
|
|
|
return dynamic_cast<TryCatchClause const*>(scope());
|
|
|
|
}
|
|
|
|
|
2015-06-09 12:26:08 +00:00
|
|
|
bool VariableDeclaration::isExternalCallableParameter() const
|
2015-02-14 00:22:44 +00:00
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
if (!isCallableOrCatchParameter())
|
2015-02-14 00:22:44 +00:00
|
|
|
return false;
|
2018-08-07 13:58:34 +00:00
|
|
|
|
|
|
|
if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
2019-12-10 14:54:09 +00:00
|
|
|
if (callable->visibility() == Visibility::External)
|
2018-08-07 13:58:34 +00:00
|
|
|
return !isReturnParameter();
|
|
|
|
|
2015-02-14 00:22:44 +00:00
|
|
|
return false;
|
2015-01-22 00:02:38 +00:00
|
|
|
}
|
|
|
|
|
2020-04-16 14:29:23 +00:00
|
|
|
bool VariableDeclaration::isPublicCallableParameter() const
|
|
|
|
{
|
|
|
|
if (!isCallableOrCatchParameter())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
|
|
|
if (callable->visibility() == Visibility::Public)
|
|
|
|
return !isReturnParameter();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-07 13:58:34 +00:00
|
|
|
bool VariableDeclaration::isInternalCallableParameter() const
|
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
if (!isCallableOrCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (auto const* funTypeName = dynamic_cast<FunctionTypeName const*>(scope()))
|
2019-12-10 14:54:09 +00:00
|
|
|
return funTypeName->visibility() == Visibility::Internal;
|
2018-08-07 13:58:34 +00:00
|
|
|
else if (auto const* callable = dynamic_cast<CallableDeclaration const*>(scope()))
|
2019-12-10 14:54:09 +00:00
|
|
|
return callable->visibility() <= Visibility::Internal;
|
2018-08-07 13:58:34 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-07-06 14:52:51 +00:00
|
|
|
bool VariableDeclaration::isConstructorParameter() const
|
|
|
|
{
|
|
|
|
if (!isCallableOrCatchParameter())
|
|
|
|
return false;
|
|
|
|
if (auto const* function = dynamic_cast<FunctionDefinition const*>(scope()))
|
|
|
|
return function->isConstructor();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-08-07 13:58:34 +00:00
|
|
|
bool VariableDeclaration::isLibraryFunctionParameter() const
|
|
|
|
{
|
2019-09-05 18:02:34 +00:00
|
|
|
if (!isCallableOrCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
return false;
|
|
|
|
if (auto const* funDef = dynamic_cast<FunctionDefinition const*>(scope()))
|
2020-05-04 16:38:00 +00:00
|
|
|
return funDef->libraryFunction();
|
|
|
|
return false;
|
2018-08-07 13:58:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool VariableDeclaration::hasReferenceOrMappingType() const
|
|
|
|
{
|
2020-07-15 17:50:59 +00:00
|
|
|
solAssert(typeName().annotation().type, "Can only be called after reference resolution");
|
|
|
|
Type const* type = typeName().annotation().type;
|
2019-04-15 13:33:39 +00:00
|
|
|
return type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type);
|
2018-08-07 13:58:34 +00:00
|
|
|
}
|
|
|
|
|
2020-09-28 17:31:54 +00:00
|
|
|
bool VariableDeclaration::isStateVariable() const
|
|
|
|
{
|
|
|
|
return dynamic_cast<ContractDefinition const*>(scope());
|
|
|
|
}
|
|
|
|
|
2020-09-25 10:15:31 +00:00
|
|
|
bool VariableDeclaration::isFileLevelVariable() const
|
|
|
|
{
|
|
|
|
return dynamic_cast<SourceUnit const*>(scope());
|
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
|
2018-08-07 13:58:34 +00:00
|
|
|
{
|
|
|
|
using Location = VariableDeclaration::Location;
|
|
|
|
|
2021-01-28 11:56:22 +00:00
|
|
|
if (!hasReferenceOrMappingType() || isStateVariable() || isEventOrErrorParameter())
|
2023-08-14 12:39:16 +00:00
|
|
|
return std::set<Location>{ Location::Unspecified };
|
2019-09-05 18:02:34 +00:00
|
|
|
else if (isCallableOrCatchParameter())
|
2018-08-07 13:58:34 +00:00
|
|
|
{
|
2023-08-14 12:39:16 +00:00
|
|
|
std::set<Location> locations{ Location::Memory };
|
2020-06-18 15:34:05 +00:00
|
|
|
if (
|
|
|
|
isConstructorParameter() ||
|
|
|
|
isInternalCallableParameter() ||
|
2021-05-31 09:21:04 +00:00
|
|
|
isLibraryFunctionParameter()
|
2020-06-18 15:34:05 +00:00
|
|
|
)
|
2018-08-07 13:58:34 +00:00
|
|
|
locations.insert(Location::Storage);
|
2020-07-06 14:52:51 +00:00
|
|
|
if (!isTryCatchParameter() && !isConstructorParameter())
|
2020-05-25 17:30:17 +00:00
|
|
|
locations.insert(Location::CallData);
|
|
|
|
|
2018-08-07 13:58:34 +00:00
|
|
|
return locations;
|
|
|
|
}
|
|
|
|
else if (isLocalVariable())
|
2020-07-15 17:50:59 +00:00
|
|
|
// Further restrictions will be imposed later on.
|
2023-08-14 12:39:16 +00:00
|
|
|
return std::set<Location>{ Location::Memory, Location::Storage, Location::CallData };
|
2018-08-07 13:58:34 +00:00
|
|
|
else
|
|
|
|
// Struct members etc.
|
2023-08-14 12:39:16 +00:00
|
|
|
return std::set<Location>{ Location::Unspecified };
|
2018-08-07 13:58:34 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::string VariableDeclaration::externalIdentifierHex() const
|
2019-12-09 00:26:23 +00:00
|
|
|
{
|
|
|
|
solAssert(isStateVariable() && isPublic(), "Can only be called for public state variables");
|
|
|
|
return TypeProvider::function(*this)->externalIdentifierHex();
|
|
|
|
}
|
|
|
|
|
2021-03-22 16:12:05 +00:00
|
|
|
Type const* VariableDeclaration::type() const
|
2014-10-13 16:22:15 +00:00
|
|
|
{
|
2015-09-16 14:56:30 +00:00
|
|
|
return annotation().type;
|
2014-10-16 12:08:54 +00:00
|
|
|
}
|
2015-09-21 16:55:58 +00:00
|
|
|
|
2017-12-30 12:44:09 +00:00
|
|
|
FunctionTypePointer VariableDeclaration::functionType(bool _internal) const
|
2017-01-10 15:26:13 +00:00
|
|
|
{
|
|
|
|
if (_internal)
|
2019-04-15 13:33:39 +00:00
|
|
|
return nullptr;
|
2017-01-10 15:26:13 +00:00
|
|
|
switch (visibility())
|
|
|
|
{
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::Default:
|
2017-01-10 15:26:13 +00:00
|
|
|
solAssert(false, "visibility() should not return Default");
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::Private:
|
|
|
|
case Visibility::Internal:
|
2019-04-15 13:33:39 +00:00
|
|
|
return nullptr;
|
2019-12-10 14:54:09 +00:00
|
|
|
case Visibility::Public:
|
|
|
|
case Visibility::External:
|
2019-04-17 11:40:50 +00:00
|
|
|
return TypeProvider::function(*this);
|
2017-01-10 15:26:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// To make the compiler happy
|
2019-04-15 13:33:39 +00:00
|
|
|
return nullptr;
|
2017-01-10 15:26:13 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
VariableDeclarationAnnotation& VariableDeclaration::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<VariableDeclarationAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
2015-10-26 16:20:29 +00:00
|
|
|
StatementAnnotation& Statement::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<StatementAnnotation>();
|
2015-10-26 16:20:29 +00:00
|
|
|
}
|
|
|
|
|
2016-03-01 21:56:39 +00:00
|
|
|
InlineAssemblyAnnotation& InlineAssembly::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<InlineAssemblyAnnotation>();
|
2016-03-01 21:56:39 +00:00
|
|
|
}
|
|
|
|
|
2019-12-20 01:20:27 +00:00
|
|
|
BlockAnnotation& Block::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<BlockAnnotation>();
|
2019-12-20 01:20:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TryCatchClauseAnnotation& TryCatchClause::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<TryCatchClauseAnnotation>();
|
2019-12-20 01:20:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ForStatementAnnotation& ForStatement::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<ForStatementAnnotation>();
|
2019-12-20 01:20:27 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
ReturnAnnotation& Return::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<ReturnAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ExpressionAnnotation& Expression::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<ExpressionAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MemberAccessAnnotation& MemberAccess::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<MemberAccessAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
2022-07-06 07:17:59 +00:00
|
|
|
OperationAnnotation& UnaryOperation::annotation() const
|
|
|
|
{
|
|
|
|
return initAnnotation<OperationAnnotation>();
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionType const* UnaryOperation::userDefinedFunctionType() const
|
|
|
|
{
|
|
|
|
if (*annotation().userDefinedFunction == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction;
|
|
|
|
return dynamic_cast<FunctionType const*>(
|
|
|
|
userDefinedFunction->libraryFunction() ?
|
|
|
|
userDefinedFunction->typeViaContractName() :
|
|
|
|
userDefinedFunction->type()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
FunctionType const* BinaryOperation::userDefinedFunctionType() const
|
|
|
|
{
|
|
|
|
if (*annotation().userDefinedFunction == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction;
|
|
|
|
return dynamic_cast<FunctionType const*>(
|
|
|
|
userDefinedFunction->libraryFunction() ?
|
|
|
|
userDefinedFunction->typeViaContractName() :
|
|
|
|
userDefinedFunction->type()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
BinaryOperationAnnotation& BinaryOperation::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<BinaryOperationAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FunctionCallAnnotation& FunctionCall::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<FunctionCallAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<ASTPointer<Expression const>> FunctionCall::sortedArguments() const
|
2020-11-09 13:09:34 +00:00
|
|
|
{
|
|
|
|
// normal arguments
|
|
|
|
if (m_names.empty())
|
|
|
|
return arguments();
|
|
|
|
|
|
|
|
// named arguments
|
|
|
|
FunctionTypePointer functionType;
|
|
|
|
if (*annotation().kind == FunctionCallKind::StructConstructorCall)
|
|
|
|
{
|
|
|
|
auto const& type = dynamic_cast<TypeType const&>(*m_expression->annotation().type);
|
|
|
|
auto const& structType = dynamic_cast<StructType const&>(*type.actualType());
|
|
|
|
functionType = structType.constructorType();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
functionType = dynamic_cast<FunctionType const*>(m_expression->annotation().type);
|
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::vector<ASTPointer<Expression const>> sorted;
|
2020-11-09 13:09:34 +00:00
|
|
|
for (auto const& parameterName: functionType->parameterNames())
|
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (size_t j = 0; j < m_names.size() && !found; j++)
|
|
|
|
if ((found = (parameterName == *m_names.at(j))))
|
|
|
|
// we found the actual parameter position
|
|
|
|
sorted.push_back(m_arguments.at(j));
|
|
|
|
solAssert(found, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!functionType->takesArbitraryParameters())
|
|
|
|
{
|
|
|
|
solAssert(m_arguments.size() == functionType->parameterTypes().size(), "");
|
|
|
|
solAssert(m_arguments.size() == m_names.size(), "");
|
|
|
|
solAssert(m_arguments.size() == sorted.size(), "");
|
|
|
|
}
|
|
|
|
|
|
|
|
return sorted;
|
|
|
|
}
|
|
|
|
|
2015-09-21 16:55:58 +00:00
|
|
|
IdentifierAnnotation& Identifier::annotation() const
|
|
|
|
{
|
2019-12-21 04:10:01 +00:00
|
|
|
return initAnnotation<IdentifierAnnotation>();
|
2015-09-21 16:55:58 +00:00
|
|
|
}
|
2017-01-24 16:38:06 +00:00
|
|
|
|
2018-10-01 12:36:57 +00:00
|
|
|
ASTString Literal::valueWithoutUnderscores() const
|
|
|
|
{
|
|
|
|
return boost::erase_all_copy(value(), "_");
|
|
|
|
}
|
|
|
|
|
2017-06-28 15:59:34 +00:00
|
|
|
bool Literal::isHexNumber() const
|
2017-06-26 11:49:05 +00:00
|
|
|
{
|
|
|
|
if (token() != Token::Number)
|
|
|
|
return false;
|
2017-06-28 16:00:14 +00:00
|
|
|
return boost::starts_with(value(), "0x");
|
2017-06-26 11:49:05 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 16:38:06 +00:00
|
|
|
bool Literal::looksLikeAddress() const
|
|
|
|
{
|
|
|
|
if (subDenomination() != SubDenomination::None)
|
|
|
|
return false;
|
2017-06-26 11:49:05 +00:00
|
|
|
|
2017-06-28 15:59:34 +00:00
|
|
|
if (!isHexNumber())
|
2017-06-22 14:39:42 +00:00
|
|
|
return false;
|
2017-01-24 16:38:06 +00:00
|
|
|
|
2018-10-01 12:36:57 +00:00
|
|
|
return abs(int(valueWithoutUnderscores().length()) - 42) <= 1;
|
2017-01-24 16:38:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Literal::passesAddressChecksum() const
|
|
|
|
{
|
2017-06-28 15:59:34 +00:00
|
|
|
solAssert(isHexNumber(), "Expected hex number");
|
2019-12-11 16:31:36 +00:00
|
|
|
return util::passesAddressChecksum(valueWithoutUnderscores(), true);
|
2017-01-24 16:38:06 +00:00
|
|
|
}
|
2017-10-05 13:28:25 +00:00
|
|
|
|
2023-08-14 12:39:16 +00:00
|
|
|
std::string Literal::getChecksummedAddress() const
|
2017-10-05 13:28:25 +00:00
|
|
|
{
|
|
|
|
solAssert(isHexNumber(), "Expected hex number");
|
2017-10-24 10:01:56 +00:00
|
|
|
/// Pad literal to be a proper hex address.
|
2023-08-14 12:39:16 +00:00
|
|
|
std::string address = valueWithoutUnderscores().substr(2);
|
2017-10-24 10:01:56 +00:00
|
|
|
if (address.length() > 40)
|
2023-08-14 12:39:16 +00:00
|
|
|
return std::string();
|
2017-10-24 10:01:56 +00:00
|
|
|
address.insert(address.begin(), 40 - address.size(), '0');
|
2019-12-11 16:31:36 +00:00
|
|
|
return util::getChecksummedAddress(address);
|
2017-10-05 13:28:25 +00:00
|
|
|
}
|
2020-03-16 10:47:39 +00:00
|
|
|
|
|
|
|
TryCatchClause const* TryStatement::successClause() const
|
|
|
|
{
|
|
|
|
solAssert(m_clauses.size() > 0, "");
|
|
|
|
return m_clauses[0].get();
|
|
|
|
}
|
|
|
|
|
2022-08-17 17:43:51 +00:00
|
|
|
TryCatchClause const* TryStatement::panicClause() const {
|
|
|
|
return findClause(m_clauses, "Panic");
|
2020-10-20 13:30:46 +00:00
|
|
|
}
|
|
|
|
|
2022-08-17 17:43:51 +00:00
|
|
|
TryCatchClause const* TryStatement::errorClause() const {
|
|
|
|
return findClause(m_clauses, "Error");
|
2020-03-16 10:47:39 +00:00
|
|
|
}
|
|
|
|
|
2022-08-17 17:43:51 +00:00
|
|
|
TryCatchClause const* TryStatement::fallbackClause() const {
|
|
|
|
return findClause(m_clauses);
|
2020-03-16 10:47:39 +00:00
|
|
|
}
|