mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #4895 from ethereum/abidecodesingle
Fix abi.decode returning single value.
This commit is contained in:
commit
e6aa15bae1
@ -525,7 +525,7 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
|
||||
);
|
||||
}
|
||||
|
||||
TypePointer TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2)
|
||||
TypePointers TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2)
|
||||
{
|
||||
vector<ASTPointer<Expression const>> arguments = _functionCall.arguments();
|
||||
if (arguments.size() != 2)
|
||||
@ -544,10 +544,8 @@ TypePointer TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall co
|
||||
" to bytes memory requested."
|
||||
);
|
||||
|
||||
TypePointer returnType = make_shared<TupleType>();
|
||||
|
||||
if (arguments.size() < 2)
|
||||
return returnType;
|
||||
return {};
|
||||
|
||||
// The following is a rather syntactic restriction, but we check it here anyway:
|
||||
// The second argument has to be a tuple expression containing type names.
|
||||
@ -558,10 +556,10 @@ TypePointer TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall co
|
||||
arguments[1]->location(),
|
||||
"The second argument to \"abi.decode\" has to be a tuple of types."
|
||||
);
|
||||
return returnType;
|
||||
return {};
|
||||
}
|
||||
|
||||
vector<TypePointer> components;
|
||||
TypePointers components;
|
||||
for (auto const& typeArgument: tupleExpression->components())
|
||||
{
|
||||
solAssert(typeArgument, "");
|
||||
@ -591,7 +589,7 @@ TypePointer TypeChecker::typeCheckABIDecodeAndRetrieveReturnType(FunctionCall co
|
||||
components.push_back(make_shared<TupleType>());
|
||||
}
|
||||
}
|
||||
return make_shared<TupleType>(components);
|
||||
return components;
|
||||
}
|
||||
|
||||
void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
|
||||
@ -1782,15 +1780,6 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
if (functionType->kind() == FunctionType::Kind::BareStaticCall && !m_evmVersion.hasStaticCall())
|
||||
m_errorReporter.typeError(_functionCall.location(), "\"staticcall\" is not supported by the VM version.");
|
||||
|
||||
auto returnTypes =
|
||||
allowDynamicTypes ?
|
||||
functionType->returnParameterTypes() :
|
||||
functionType->returnParameterTypesWithoutDynamicTypes();
|
||||
if (returnTypes.size() == 1)
|
||||
_functionCall.annotation().type = returnTypes.front();
|
||||
else
|
||||
_functionCall.annotation().type = make_shared<TupleType>(returnTypes);
|
||||
|
||||
if (auto functionName = dynamic_cast<Identifier const*>(&_functionCall.expression()))
|
||||
{
|
||||
if (functionName->name() == "sha3" && functionType->kind() == FunctionType::Kind::KECCAK256)
|
||||
@ -1826,8 +1815,14 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
|
||||
bool const abiEncoderV2 = m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2);
|
||||
|
||||
// Will be assigned to .type at the end (turning multi-elements into a tuple).
|
||||
TypePointers returnTypes =
|
||||
allowDynamicTypes ?
|
||||
functionType->returnParameterTypes() :
|
||||
functionType->returnParameterTypesWithoutDynamicTypes();
|
||||
|
||||
if (functionType->kind() == FunctionType::Kind::ABIDecode)
|
||||
_functionCall.annotation().type = typeCheckABIDecodeAndRetrieveReturnType(_functionCall, abiEncoderV2);
|
||||
returnTypes = typeCheckABIDecodeAndRetrieveReturnType(_functionCall, abiEncoderV2);
|
||||
else if (functionType->takesArbitraryParameters() && arguments.size() < parameterTypes.size())
|
||||
{
|
||||
solAssert(_functionCall.annotation().kind == FunctionCallKind::FunctionCall, "");
|
||||
@ -1985,6 +1980,11 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
}
|
||||
}
|
||||
|
||||
if (returnTypes.size() == 1)
|
||||
_functionCall.annotation().type = returnTypes.front();
|
||||
else
|
||||
_functionCall.annotation().type = make_shared<TupleType>(returnTypes);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -92,9 +92,9 @@ private:
|
||||
void checkExpressionAssignment(Type const& _type, Expression const& _expression);
|
||||
|
||||
/// Performs type checks for ``abi.decode(bytes memory, (...))`` and returns the
|
||||
/// return type (which is basically the second argument) if successful. It returns
|
||||
/// the empty tuple type or error.
|
||||
TypePointer typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2);
|
||||
/// vector of return types (which is basically the second argument) if successful. It returns
|
||||
/// the empty vector on error.
|
||||
TypePointers typeCheckABIDecodeAndRetrieveReturnType(FunctionCall const& _functionCall, bool _abiEncoderV2);
|
||||
|
||||
virtual void endVisit(InheritanceSpecifier const& _inheritance) override;
|
||||
virtual void endVisit(UsingForDirective const& _usingFor) override;
|
||||
|
@ -1074,7 +1074,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
arguments.front()->accept(*this);
|
||||
TypePointer firstArgType = arguments.front()->annotation().type;
|
||||
TypePointers const& targetTypes = dynamic_cast<TupleType const&>(*_functionCall.annotation().type).components();
|
||||
TypePointers targetTypes;
|
||||
if (TupleType const* targetTupleType = dynamic_cast<TupleType const*>(_functionCall.annotation().type.get()))
|
||||
targetTypes = targetTupleType->components();
|
||||
else
|
||||
targetTypes = TypePointers{_functionCall.annotation().type};
|
||||
if (
|
||||
*firstArgType == ArrayType(DataLocation::CallData) ||
|
||||
*firstArgType == ArrayType(DataLocation::CallData, true)
|
||||
|
@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
function f() public pure {
|
||||
abi.decode("abc", ());
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (52-73): Statement has no effect.
|
@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function f() public pure returns (bool) {
|
||||
return abi.decode("abc", (uint)) == 2;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user