diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 1948541a4..9dd0f7155 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -4029,26 +4029,35 @@ void TypeChecker::endVisit(UsingForDirective const& _usingFor) TokenTraits::friendlyName(*operator_) + "." ); - else if ( - !TokenTraits::isCompareOp(*operator_) && - ( + else if (!TokenTraits::isCompareOp(*operator_)) + { + if ( functionType->returnParameterTypes().size() != 1 || ( *TypeProvider::withLocationIfReference(DataLocation::Storage, functionType->returnParameterTypes().front()) != *TypeProvider::withLocationIfReference(DataLocation::Storage, _usingFor.typeName()->annotation().type) ) ) - ) - m_errorReporter.typeError( - 7743_error, - path->location(), - "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ - "needs to return exactly one value of type " + - _usingFor.typeName()->annotation().type->canonicalName() + - " to be used for the operator " + - TokenTraits::friendlyName(*operator_) + - "." - ); + m_errorReporter.typeError( + 7743_error, + path->location(), + "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ + "needs to return exactly one value of type " + + _usingFor.typeName()->annotation().type->canonicalName() + + " to be used for the operator " + + TokenTraits::friendlyName(*operator_) + + "." + ); + else if (*functionType->returnParameterTypes().front() != *functionType->parameterTypesIncludingSelf().front()) + m_errorReporter.typeError( + 3605_error, + path->location(), + "The function \"" + joinHumanReadable(path->path(), ".") + "\" "+ + "needs to have parameters and return value of the same type to be used for the operator " + + TokenTraits::friendlyName(*operator_) + + "." + ); + } } } } diff --git a/test/libsolidity/semanticTests/operators/custom/operator_overloaded_by_data_location.sol b/test/libsolidity/semanticTests/operators/custom/operator_overloaded_by_data_location.sol index b3397a1a4..06753f85c 100644 --- a/test/libsolidity/semanticTests/operators/custom/operator_overloaded_by_data_location.sol +++ b/test/libsolidity/semanticTests/operators/custom/operator_overloaded_by_data_location.sol @@ -1,3 +1,5 @@ +pragma abicoder v2; + using { addC as +, addM as +, diff --git a/test/libsolidity/syntaxTests/operators/custom/different_data_location_of_parameters_and_return_parameter.sol b/test/libsolidity/syntaxTests/operators/custom/different_data_location_of_parameters_and_return_parameter.sol new file mode 100644 index 000000000..66f0e1110 --- /dev/null +++ b/test/libsolidity/syntaxTests/operators/custom/different_data_location_of_parameters_and_return_parameter.sol @@ -0,0 +1,21 @@ +using {add as +} for S; + +struct S { + int v; +} + +function add(S storage _a, S storage) returns (S memory) { + _a.v = 7; + return _a; +} + + +contract C { + S s; + function f() public returns (S memory) { + return s + s; + } +} + +// ---- +// TypeError 3605: (7-10): The function "add" needs to have parameters and return value of the same type to be used for the operator +. diff --git a/test/libsolidity/syntaxTests/operators/custom/operator_invalid_parameters.sol b/test/libsolidity/syntaxTests/operators/custom/operator_invalid_parameters.sol index 9844a4871..df2c1ac8c 100644 --- a/test/libsolidity/syntaxTests/operators/custom/operator_invalid_parameters.sol +++ b/test/libsolidity/syntaxTests/operators/custom/operator_invalid_parameters.sol @@ -28,6 +28,7 @@ function f() pure { // TypeError 1884: (33-36): The function "add" needs to have two parameters of type Int and the same data location to be used for the operator +. // TypeError 8112: (47-50): The function "sub" needs to have one or two parameters of type Int and the same data location to be used for the operator -. // TypeError 7617: (61-64): The function "div" needs to have one or two parameters of type Int and the same data location to be used for the operator /. +// TypeError 3605: (61-64): The function "div" needs to have parameters and return value of the same type to be used for the operator /. // TypeError 2271: (325-350): Operator + not compatible with types Int and Int. No matching user-defined operator found. // TypeError 2271: (356-381): Operator - not compatible with types Int and Int. No matching user-defined operator found. // TypeError 2271: (387-412): Operator / not compatible with types Int and Int. No matching user-defined operator found. diff --git a/test/libsolidity/syntaxTests/operators/custom/operator_with_calldata_parameters.sol b/test/libsolidity/syntaxTests/operators/custom/operator_with_calldata_parameters.sol index 49ea805e4..1f1c46ecb 100644 --- a/test/libsolidity/syntaxTests/operators/custom/operator_with_calldata_parameters.sol +++ b/test/libsolidity/syntaxTests/operators/custom/operator_with_calldata_parameters.sol @@ -62,6 +62,7 @@ function test(S calldata s) pure { // TypeError 7743: (54-57): The function "div" needs to return exactly one value of type S to be used for the operator /. // TypeError 7743: (68-71): The function "mod" needs to return exactly one value of type S to be used for the operator %. // TypeError 7617: (82-87): The function "unsub" needs to have one or two parameters of type S and the same data location to be used for the operator -. +// TypeError 3605: (82-87): The function "unsub" needs to have parameters and return value of the same type to be used for the operator -. // TypeError 7743: (98-104): The function "bitnot" needs to return exactly one value of type S to be used for the operator ~. // TypeError 2271: (758-763): Operator * not compatible with types struct S calldata and struct S calldata. No matching user-defined operator found. // TypeError 4907: (791-793): Unary operator - cannot be applied to type struct S calldata. No matching user-defined operator found. diff --git a/test/libsolidity/syntaxTests/operators/custom/operator_with_different_param_return_types.sol b/test/libsolidity/syntaxTests/operators/custom/operator_with_different_param_return_types.sol index 3b0c6e22e..b13fe0efd 100644 --- a/test/libsolidity/syntaxTests/operators/custom/operator_with_different_param_return_types.sol +++ b/test/libsolidity/syntaxTests/operators/custom/operator_with_different_param_return_types.sol @@ -38,4 +38,6 @@ function bitor(S storage, S storage) pure returns (S memory) { // TypeError 7617: (71-74): The function "sub" needs to have one or two parameters of type Int and the same data location to be used for the operator -. // TypeError 7743: (71-74): The function "sub" needs to return exactly one value of type Int to be used for the operator -. // TypeError 1884: (85-88): The function "mul" needs to have two parameters of type Int and the same data location to be used for the operator *. +// TypeError 3605: (85-88): The function "mul" needs to have parameters and return value of the same type to be used for the operator *. // TypeError 7743: (95-98): The function "div" needs to return exactly one value of type Int to be used for the operator /. +// TypeError 3605: (128-133): The function "bitor" needs to have parameters and return value of the same type to be used for the operator |.