From f94279a4374a05ec3c253449ed3b11e2d8ee0c54 Mon Sep 17 00:00:00 2001 From: chriseth Date: Mon, 20 Dec 2021 12:40:43 +0100 Subject: [PATCH] Use options struct for function type factory function. --- libsolidity/analysis/GlobalContext.cpp | 32 ++++----- libsolidity/analysis/TypeChecker.cpp | 1 - libsolidity/ast/TypeProvider.cpp | 29 ++++---- libsolidity/ast/TypeProvider.h | 10 +-- libsolidity/ast/Types.cpp | 94 +++++++++++--------------- libsolidity/ast/Types.h | 32 +++++++++ 6 files changed, 107 insertions(+), 91 deletions(-) diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index 17d5b8c3e..58ebea7b1 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -73,24 +73,24 @@ inline vector> constructMagicVariable return { magicVarDecl("abi", TypeProvider::magic(MagicType::Kind::ABI)), - magicVarDecl("addmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, false, StateMutability::Pure)), - magicVarDecl("assert", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Assert, false, StateMutability::Pure)), + magicVarDecl("addmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::AddMod, StateMutability::Pure)), + magicVarDecl("assert", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Assert, StateMutability::Pure)), magicVarDecl("block", TypeProvider::magic(MagicType::Kind::Block)), - magicVarDecl("blockhash", TypeProvider::function(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)), - magicVarDecl("ecrecover", TypeProvider::function(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), - magicVarDecl("gasleft", TypeProvider::function(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)), - magicVarDecl("keccak256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)), + magicVarDecl("blockhash", TypeProvider::function(strings{"uint256"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)), + magicVarDecl("ecrecover", TypeProvider::function(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, StateMutability::Pure)), + magicVarDecl("gasleft", TypeProvider::function(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, StateMutability::View)), + magicVarDecl("keccak256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, StateMutability::Pure)), magicVarDecl("msg", TypeProvider::magic(MagicType::Kind::Message)), - magicVarDecl("mulmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)), + magicVarDecl("mulmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, StateMutability::Pure)), magicVarDecl("now", TypeProvider::uint256()), - magicVarDecl("require", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), - magicVarDecl("require", TypeProvider::function(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)), - magicVarDecl("revert", TypeProvider::function(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)), - magicVarDecl("revert", TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)), - magicVarDecl("ripemd160", TypeProvider::function(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)), + magicVarDecl("require", TypeProvider::function(strings{"bool"}, strings{}, FunctionType::Kind::Require, StateMutability::Pure)), + magicVarDecl("require", TypeProvider::function(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, StateMutability::Pure)), + magicVarDecl("revert", TypeProvider::function(strings(), strings(), FunctionType::Kind::Revert, StateMutability::Pure)), + magicVarDecl("revert", TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::Revert, StateMutability::Pure)), + magicVarDecl("ripemd160", TypeProvider::function(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, StateMutability::Pure)), magicVarDecl("selfdestruct", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)), - magicVarDecl("sha256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)), - magicVarDecl("sha3", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)), + magicVarDecl("sha256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, StateMutability::Pure)), + magicVarDecl("sha3", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, StateMutability::Pure)), magicVarDecl("suicide", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)), magicVarDecl("tx", TypeProvider::magic(MagicType::Kind::Transaction)), // Accepts a MagicType that can be any contract type or an Integer type and returns a @@ -99,8 +99,8 @@ inline vector> constructMagicVariable strings{}, strings{}, FunctionType::Kind::MetaType, - true, - StateMutability::Pure + StateMutability::Pure, + FunctionType::Options::withArbitraryParameters() )), }; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index d6c589f75..be8275a93 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2866,7 +2866,6 @@ void TypeChecker::endVisit(NewExpression const& _newExpression) strings(1, ""), strings(1, ""), FunctionType::Kind::ObjectCreation, - false, StateMutability::Pure ); _newExpression.annotation().isPure = true; diff --git a/libsolidity/ast/TypeProvider.cpp b/libsolidity/ast/TypeProvider.cpp index 6183493b4..f5af82f94 100644 --- a/libsolidity/ast/TypeProvider.cpp +++ b/libsolidity/ast/TypeProvider.cpp @@ -445,13 +445,18 @@ FunctionType const* TypeProvider::function( strings const& _parameterTypes, strings const& _returnParameterTypes, FunctionType::Kind _kind, - bool _arbitraryParameters, - StateMutability _stateMutability + StateMutability _stateMutability, + FunctionType::Options _options ) { + // Can only use this constructor for "arbitraryParameters". + solAssert(!_options.valueSet && !_options.gasSet && !_options.saltSet && !_options.bound); return createAndGet( - _parameterTypes, _returnParameterTypes, - _kind, _arbitraryParameters, _stateMutability + _parameterTypes, + _returnParameterTypes, + _kind, + _options.arbitraryParameters, + _stateMutability ); } @@ -461,13 +466,9 @@ FunctionType const* TypeProvider::function( strings _parameterNames, strings _returnParameterNames, FunctionType::Kind _kind, - bool _arbitraryParameters, StateMutability _stateMutability, Declaration const* _declaration, - bool _gasSet, - bool _valueSet, - bool _bound, - bool _saltSet + FunctionType::Options _options ) { return createAndGet( @@ -476,13 +477,13 @@ FunctionType const* TypeProvider::function( _parameterNames, _returnParameterNames, _kind, - _arbitraryParameters, + _options.arbitraryParameters, _stateMutability, _declaration, - _gasSet, - _valueSet, - _bound, - _saltSet + _options.gasSet, + _options.valueSet, + _options.saltSet, + _options.bound ); } diff --git a/libsolidity/ast/TypeProvider.h b/libsolidity/ast/TypeProvider.h index 78b8378ca..b089ff1ef 100644 --- a/libsolidity/ast/TypeProvider.h +++ b/libsolidity/ast/TypeProvider.h @@ -149,8 +149,8 @@ public: strings const& _parameterTypes, strings const& _returnParameterTypes, FunctionType::Kind _kind = FunctionType::Kind::Internal, - bool _arbitraryParameters = false, - StateMutability _stateMutability = StateMutability::NonPayable + StateMutability _stateMutability = StateMutability::NonPayable, + FunctionType::Options _options = {} ); /// @returns a highly customized FunctionType, use with care. @@ -160,13 +160,9 @@ public: strings _parameterNames = strings{}, strings _returnParameterNames = strings{}, FunctionType::Kind _kind = FunctionType::Kind::Internal, - bool _arbitraryParameters = false, StateMutability _stateMutability = StateMutability::NonPayable, Declaration const* _declaration = nullptr, - bool _gasSet = false, - bool _valueSet = false, - bool _bound = false, - bool _saltSet = false + FunctionType::Options _options = {} ); /// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index ed16d2b35..da2811a21 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -470,15 +470,15 @@ MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const {"balance", TypeProvider::uint256()}, {"code", TypeProvider::array(DataLocation::Memory)}, {"codehash", TypeProvider::fixedBytes(32)}, - {"call", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)}, - {"callcode", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)}, - {"delegatecall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false, StateMutability::NonPayable)}, - {"staticcall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)} + {"call", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, StateMutability::Payable)}, + {"callcode", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, StateMutability::Payable)}, + {"delegatecall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, StateMutability::NonPayable)}, + {"staticcall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, StateMutability::View)} }; if (m_stateMutability == StateMutability::Payable) { - members.emplace_back(MemberList::Member{"send", TypeProvider::function(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send, false, StateMutability::NonPayable)}); - members.emplace_back(MemberList::Member{"transfer", TypeProvider::function(strings{"uint"}, strings(), FunctionType::Kind::Transfer, false, StateMutability::NonPayable)}); + members.emplace_back(MemberList::Member{"send", TypeProvider::function(strings{"uint"}, strings{"bool"}, FunctionType::Kind::Send, StateMutability::NonPayable)}); + members.emplace_back(MemberList::Member{"transfer", TypeProvider::function(strings{"uint"}, strings(), FunctionType::Kind::Transfer, StateMutability::NonPayable)}); } return members; } @@ -2848,7 +2848,6 @@ FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _c parameterNames, strings{""}, Kind::Creation, - false, stateMutability ); } @@ -3176,13 +3175,13 @@ FunctionTypePointer FunctionType::interfaceFunctionType() const if (variable && retParamTypes.get().empty()) return FunctionTypePointer(); + solAssert(!takesArbitraryParameters()); return TypeProvider::function( paramTypes, retParamTypes, m_parameterNames, m_returnParameterNames, m_kind, - takesArbitraryParameters(), m_stateMutability, m_declaration ); @@ -3237,12 +3236,9 @@ MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const strings(1, ""), strings(1, ""), Kind::SetValue, - false, StateMutability::Pure, nullptr, - gasSet(), - valueSet(), - saltSet() + Options::fromFunctionType(*this) ) ); } @@ -3255,12 +3251,9 @@ MemberList::MemberMap FunctionType::nativeMembers(ASTNode const* _scope) const strings(1, ""), strings(1, ""), Kind::SetGas, - false, StateMutability::Pure, nullptr, - gasSet(), - valueSet(), - saltSet() + Options::fromFunctionType(*this) ) ); return members; @@ -3317,13 +3310,9 @@ Type const* FunctionType::mobileType() const strings(m_parameterTypes.size()), strings(m_returnParameterNames.size()), m_kind, - takesArbitraryParameters(), m_stateMutability, m_declaration, - gasSet(), - valueSet(), - bound(), - saltSet() + Options::fromFunctionType(*this) ); } @@ -3520,19 +3509,19 @@ TypePointers FunctionType::parseElementaryTypeVector(strings const& _types) Type const* FunctionType::copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const { solAssert(m_kind != Kind::Declaration, ""); + Options options = Options::fromFunctionType(*this); + if (_setGas) options.gasSet = true; + if (_setValue) options.valueSet = true; + if (_setSalt) options.saltSet = true; return TypeProvider::function( m_parameterTypes, m_returnParameterTypes, m_parameterNames, m_returnParameterNames, m_kind, - takesArbitraryParameters(), m_stateMutability, m_declaration, - gasSet() || _setGas, - valueSet() || _setValue, - saltSet() || _setSalt, - bound() + options ); } @@ -3542,19 +3531,17 @@ FunctionTypePointer FunctionType::asBoundFunction() const solAssert(!gasSet(), ""); solAssert(!valueSet(), ""); solAssert(!saltSet(), ""); + Options options = Options::fromFunctionType(*this); + options.bound = true; return TypeProvider::function( m_parameterTypes, m_returnParameterTypes, m_parameterNames, m_returnParameterNames, m_kind, - takesArbitraryParameters(), m_stateMutability, m_declaration, - gasSet(), - valueSet(), - saltSet(), - true + options ); } @@ -3592,13 +3579,9 @@ FunctionTypePointer FunctionType::asExternallyCallableFunction(bool _inLibrary) m_parameterNames, m_returnParameterNames, kind, - takesArbitraryParameters(), m_stateMutability, m_declaration, - gasSet(), - valueSet(), - saltSet(), - bound() + Options::fromFunctionType(*this) ); } @@ -3803,7 +3786,6 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons strings{string{}}, strings{string{}}, FunctionType::Kind::Wrap, - false, /*_arbitraryParameters */ StateMutability::Pure ) ); @@ -3815,7 +3797,6 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons strings{string{}}, strings{string{}}, FunctionType::Kind::Unwrap, - false, /* _arbitraryParameters */ StateMutability::Pure ) ); @@ -3830,8 +3811,9 @@ MemberList::MemberMap TypeType::nativeMembers(ASTNode const* _currentScope) cons strings{}, strings{string()}, FunctionType::Kind::BytesConcat, - /* _arbitraryParameters */ true, - StateMutability::Pure + StateMutability::Pure, + nullptr, + FunctionType::Options::withArbitraryParameters() )); return members; @@ -3954,7 +3936,7 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const return MemberList::MemberMap({ {"coinbase", TypeProvider::payableAddress()}, {"timestamp", TypeProvider::uint256()}, - {"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, false, StateMutability::View)}, + {"blockhash", TypeProvider::function(strings{"uint"}, strings{"bytes32"}, FunctionType::Kind::BlockHash, StateMutability::View)}, {"difficulty", TypeProvider::uint256()}, {"number", TypeProvider::uint256()}, {"gaslimit", TypeProvider::uint256()}, @@ -3982,8 +3964,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const strings{}, strings{1, ""}, FunctionType::Kind::ABIEncode, - true, - StateMutability::Pure + StateMutability::Pure, + nullptr, + FunctionType::Options::withArbitraryParameters() )}, {"encodePacked", TypeProvider::function( TypePointers{}, @@ -3991,8 +3974,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const strings{}, strings{1, ""}, FunctionType::Kind::ABIEncodePacked, - true, - StateMutability::Pure + StateMutability::Pure, + nullptr, + FunctionType::Options::withArbitraryParameters() )}, {"encodeWithSelector", TypeProvider::function( TypePointers{TypeProvider::fixedBytes(4)}, @@ -4000,8 +3984,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const strings{1, ""}, strings{1, ""}, FunctionType::Kind::ABIEncodeWithSelector, - true, - StateMutability::Pure + StateMutability::Pure, + nullptr, + FunctionType::Options::withArbitraryParameters() )}, {"encodeCall", TypeProvider::function( TypePointers{}, @@ -4009,8 +3994,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const strings{}, strings{1, ""}, FunctionType::Kind::ABIEncodeCall, - true, - StateMutability::Pure + StateMutability::Pure, + nullptr, + FunctionType::Options::withArbitraryParameters() )}, {"encodeWithSignature", TypeProvider::function( TypePointers{TypeProvider::array(DataLocation::Memory, true)}, @@ -4018,8 +4004,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const strings{1, ""}, strings{1, ""}, FunctionType::Kind::ABIEncodeWithSignature, - true, - StateMutability::Pure + StateMutability::Pure, + nullptr, + FunctionType::Options::withArbitraryParameters() )}, {"decode", TypeProvider::function( TypePointers(), @@ -4027,8 +4014,9 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const strings{}, strings{}, FunctionType::Kind::ABIDecode, - true, - StateMutability::Pure + StateMutability::Pure, + nullptr, + FunctionType::Options::withArbitraryParameters() )} }); case Kind::MetaType: diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 94ee41052..dc6bda477 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1247,6 +1247,38 @@ public: /// Cannot be called. Declaration, }; + struct Options + { + /// true iff the function takes an arbitrary number of arguments of arbitrary types + bool arbitraryParameters = false; + /// true iff the gas value to be used is on the stack + bool gasSet = false; + /// true iff the value to be sent is on the stack + bool valueSet = false; + /// iff the salt value (for create2) to be used is on the stack + bool saltSet = false; + /// true iff the function is called as arg1.fun(arg2, ..., argn). + /// This is achieved through the "using for" directive. + bool bound = false; + + static Options withArbitraryParameters() + { + Options result; + result.arbitraryParameters = true; + return result; + } + static Options fromFunctionType(FunctionType const& _type) + { + Options result; + result.arbitraryParameters = _type.takesArbitraryParameters(); + result.gasSet = _type.gasSet(); + result.valueSet = _type.valueSet(); + result.saltSet = _type.saltSet(); + result.bound = _type.bound(); + return result; + } + }; + /// Creates the type of a function. /// @arg _kind must be Kind::Internal, Kind::External or Kind::Declaration.