Add option member for function type.

This commit is contained in:
chriseth 2021-12-20 13:23:40 +01:00
parent f94279a437
commit 7620bfaad8
3 changed files with 24 additions and 37 deletions

View File

@ -455,8 +455,8 @@ FunctionType const* TypeProvider::function(
_parameterTypes, _parameterTypes,
_returnParameterTypes, _returnParameterTypes,
_kind, _kind,
_options.arbitraryParameters, _stateMutability,
_stateMutability std::move(_options)
); );
} }
@ -477,13 +477,9 @@ FunctionType const* TypeProvider::function(
_parameterNames, _parameterNames,
_returnParameterNames, _returnParameterNames,
_kind, _kind,
_options.arbitraryParameters,
_stateMutability, _stateMutability,
_declaration, _declaration,
_options.gasSet, std::move(_options)
_options.valueSet,
_options.saltSet,
_options.bound
); );
} }

View File

@ -1295,18 +1295,21 @@ public:
strings const& _parameterTypes, strings const& _parameterTypes,
strings const& _returnParameterTypes, strings const& _returnParameterTypes,
Kind _kind, Kind _kind,
bool _arbitraryParameters = false, StateMutability _stateMutability = StateMutability::NonPayable,
StateMutability _stateMutability = StateMutability::NonPayable Options _options = Options{false, false, false, false, false}
): FunctionType( ): FunctionType(
parseElementaryTypeVector(_parameterTypes), parseElementaryTypeVector(_parameterTypes),
parseElementaryTypeVector(_returnParameterTypes), parseElementaryTypeVector(_returnParameterTypes),
strings(_parameterTypes.size(), ""), strings(_parameterTypes.size(), ""),
strings(_returnParameterTypes.size(), ""), strings(_returnParameterTypes.size(), ""),
_kind, _kind,
_arbitraryParameters, _stateMutability,
_stateMutability nullptr,
std::move(_options)
) )
{ {
// In this constructor, only the "arbitrary Parameters" option should be used.
solAssert(!bound() && !gasSet() && !valueSet() && !saltSet());
} }
/// Detailed constructor, use with care. /// Detailed constructor, use with care.
@ -1316,13 +1319,9 @@ public:
strings _parameterNames = strings(), strings _parameterNames = strings(),
strings _returnParameterNames = strings(), strings _returnParameterNames = strings(),
Kind _kind = Kind::Internal, Kind _kind = Kind::Internal,
bool _arbitraryParameters = false,
StateMutability _stateMutability = StateMutability::NonPayable, StateMutability _stateMutability = StateMutability::NonPayable,
Declaration const* _declaration = nullptr, Declaration const* _declaration = nullptr,
bool _gasSet = false, Options _options = Options{false, false, false, false, false}
bool _valueSet = false,
bool _saltSet = false,
bool _bound = false
): ):
m_parameterTypes(std::move(_parameterTypes)), m_parameterTypes(std::move(_parameterTypes)),
m_returnParameterTypes(std::move(_returnParameterTypes)), m_returnParameterTypes(std::move(_returnParameterTypes)),
@ -1330,12 +1329,8 @@ public:
m_returnParameterNames(std::move(_returnParameterNames)), m_returnParameterNames(std::move(_returnParameterNames)),
m_kind(_kind), m_kind(_kind),
m_stateMutability(_stateMutability), m_stateMutability(_stateMutability),
m_arbitraryParameters(_arbitraryParameters),
m_gasSet(_gasSet),
m_valueSet(_valueSet),
m_bound(_bound),
m_declaration(_declaration), m_declaration(_declaration),
m_saltSet(_saltSet) m_options(std::move(_options))
{ {
solAssert( solAssert(
m_parameterNames.size() == m_parameterTypes.size(), m_parameterNames.size() == m_parameterTypes.size(),
@ -1440,7 +1435,7 @@ public:
/// The only functions that do not pad are hash functions, the low-level call functions /// The only functions that do not pad are hash functions, the low-level call functions
/// and abi.encodePacked. /// and abi.encodePacked.
bool padArguments() const; bool padArguments() const;
bool takesArbitraryParameters() const { return m_arbitraryParameters; } bool takesArbitraryParameters() const { return m_options.arbitraryParameters; }
/// true iff the function takes a single bytes parameter and it is passed on without padding. /// true iff the function takes a single bytes parameter and it is passed on without padding.
bool takesSinglePackedBytesParameter() const bool takesSinglePackedBytesParameter() const
{ {
@ -1459,10 +1454,10 @@ public:
} }
} }
bool gasSet() const { return m_gasSet; } bool gasSet() const { return m_options.gasSet; }
bool valueSet() const { return m_valueSet; } bool valueSet() const { return m_options.valueSet; }
bool saltSet() const { return m_saltSet; } bool saltSet() const { return m_options.saltSet; }
bool bound() const { return m_bound; } bool bound() const { return m_options.bound; }
/// @returns a copy of this type, where gas or value are set manually. This will never set one /// @returns a copy of this type, where gas or value are set manually. This will never set one
/// of the parameters to false. /// of the parameters to false.
@ -1490,15 +1485,8 @@ private:
std::vector<std::string> m_returnParameterNames; std::vector<std::string> m_returnParameterNames;
Kind const m_kind; Kind const m_kind;
StateMutability m_stateMutability = StateMutability::NonPayable; StateMutability m_stateMutability = StateMutability::NonPayable;
/// true if the function takes an arbitrary number of arguments of arbitrary types
bool const m_arbitraryParameters = false;
bool const m_gasSet = false; ///< true iff the gas value to be used is on the stack
bool const m_valueSet = false; ///< true iff the value to be sent is on the stack
/// true iff the function is called as arg1.fun(arg2, ..., argn).
/// This is achieved through the "using for" directive.
bool const m_bound = false;
Declaration const* m_declaration = nullptr; Declaration const* m_declaration = nullptr;
bool m_saltSet = false; ///< true iff the salt value to be used is on the stack Options const m_options;
}; };
/** /**

View File

@ -780,6 +780,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
break; break;
case FunctionType::Kind::Send: case FunctionType::Kind::Send:
case FunctionType::Kind::Transfer: case FunctionType::Kind::Transfer:
{
_functionCall.expression().accept(*this); _functionCall.expression().accept(*this);
// Provide the gas stipend manually at first because we may send zero ether. // Provide the gas stipend manually at first because we may send zero ether.
// Will be zeroed if we send more than zero ether. // Will be zeroed if we send more than zero ether.
@ -788,6 +789,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// gas <- gas * !value // gas <- gas * !value
m_context << Instruction::SWAP1 << Instruction::DUP2; m_context << Instruction::SWAP1 << Instruction::DUP2;
m_context << Instruction::ISZERO << Instruction::MUL << Instruction::SWAP1; m_context << Instruction::ISZERO << Instruction::MUL << Instruction::SWAP1;
FunctionType::Options callOptions;
callOptions.valueSet = true;
callOptions.gasSet = true;
appendExternalFunctionCall( appendExternalFunctionCall(
FunctionType( FunctionType(
TypePointers{}, TypePointers{},
@ -795,11 +799,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
strings(), strings(),
strings(), strings(),
FunctionType::Kind::BareCall, FunctionType::Kind::BareCall,
false,
StateMutability::NonPayable, StateMutability::NonPayable,
nullptr, nullptr,
true, callOptions
true
), ),
{}, {},
false false
@ -812,6 +814,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context.appendConditionalRevert(true); m_context.appendConditionalRevert(true);
} }
break; break;
}
case FunctionType::Kind::Selfdestruct: case FunctionType::Kind::Selfdestruct:
acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), true); acceptAndConvert(*arguments.front(), *function.parameterTypes().front(), true);
m_context << Instruction::SELFDESTRUCT; m_context << Instruction::SELFDESTRUCT;