diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 6520a5260..a63b3f27d 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1790,7 +1790,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation) _operation.annotation().isConstant = false; // Check if the operator is built-in or user-defined. - FunctionDefinitionResult userDefinedOperatorResult = leftType->userDefinedOperator( + Result userDefinedOperatorResult = leftType->userDefinedOperator( _operation.getOperator(), *currentDefinitionScope(), false // _unaryOperation diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index df408853e..13e6b8028 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -59,6 +59,8 @@ using namespace solidity; using namespace solidity::langutil; using namespace solidity::frontend; +using util::Result; + namespace { @@ -384,7 +386,7 @@ vector usingForDirectivesForType(Type const& _type, AS } -FunctionDefinitionResult Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const +Result Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const { if (!typeDefinition()) return nullptr; @@ -412,12 +414,10 @@ FunctionDefinitionResult Type::userDefinedOperator(Token _token, ASTNode const& if (seenFunctions.size() == 1) return *seenFunctions.begin(); - else if (!!typeDefinition() && seenFunctions.size() == 0) - return FunctionDefinitionResult::err("Operator has not been user-defined."); - else if (!!typeDefinition()) - return FunctionDefinitionResult::err("Multiple user-defined functions provided for this operator."); + else if (seenFunctions.size() == 0) + return Result::err("No matching user-defined operator found."); else - return nullptr; + return Result::err("Multiple user-defined functions provided for this operator."); } MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 818238b61..0918372aa 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -54,7 +54,6 @@ using TypePointers = std::vector; using rational = boost::rational; using TypeResult = util::Result; using BoolResult = util::Result; -using FunctionDefinitionResult = util::Result; } @@ -378,7 +377,7 @@ public: /// Clears all internally cached values (if any). virtual void clearCache() const; - FunctionDefinitionResult userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const; + util::Result userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const; private: /// @returns a member list containing all members added to this type by `using for` directives. diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 7cace48e5..42756a8de 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -416,7 +416,8 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) solAssert(function->isFree(), "Only free functions can be bound to a user type operator."); FunctionType const* functionType = dynamic_cast( - function->libraryFunction() ? function->typeViaContractName() : function->type()); + function->libraryFunction() ? function->typeViaContractName() : function->type() + ); solAssert(functionType); functionType = dynamic_cast(*functionType).asBoundFunction(); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 7ac9bca26..5beddf3a3 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -694,21 +694,22 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation) "Functions with parameters other than self parameter cannot be bound to a user type unary operator." ); - string parameter = expressionAsType(_unaryOperation.subExpression(), *functionType->selfType()); - solAssert(!parameter.empty()); + string argument = expressionAsType(_unaryOperation.subExpression(), *functionType->selfType()); + solAssert(!argument.empty()); solAssert(function->isImplemented(), ""); solAssert( function->returnParameters().size() == 1, "A function bound to the user type operator is supposed to return exactly one value." ); - solAssert(*_unaryOperation.annotation().type == *function->returnParameters().at(0)->type(), + solAssert( + *_unaryOperation.annotation().type == *function->returnParameters().at(0)->type(), "A return type of the bound function is supposed to be same as a operator type." ); define(_unaryOperation) << m_context.enqueueFunctionForCodeGeneration(*function) << - ("(" + parameter + ")\n"); + ("(" + argument + ")\n"); return false; } diff --git a/test/libsolidity/syntaxTests/controlFlow/localStorageVariables/and_operator_err.sol b/test/libsolidity/syntaxTests/controlFlow/localStorageVariables/and_operator_err.sol index 61db13507..28f7e8f02 100644 --- a/test/libsolidity/syntaxTests/controlFlow/localStorageVariables/and_operator_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/localStorageVariables/and_operator_err.sol @@ -1,11 +1,22 @@ -struct S { bool f; } +struct S { + uint v; +} + +using {bitand as &} for S; + +function bitand(S storage, S storage) returns (S storage) { + S storage rTmp; + return rTmp; +} contract C { - function f() public view { - S storage s; - s.f && true; + S s; + function f() public { + S storage sTmp; + sTmp & s; } } // ---- -// TypeError 3464: (95-96): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError 3464: (145-149): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError 3464: (234-238): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/controlFlow/localStorageVariables/or_operator_err.sol b/test/libsolidity/syntaxTests/controlFlow/localStorageVariables/or_operator_err.sol index 77f302d64..a439062b2 100644 --- a/test/libsolidity/syntaxTests/controlFlow/localStorageVariables/or_operator_err.sol +++ b/test/libsolidity/syntaxTests/controlFlow/localStorageVariables/or_operator_err.sol @@ -1,11 +1,22 @@ -struct S { bool f; } +struct S { + uint v; +} + +using {bitor as |} for S; + +function bitor(S storage, S storage) returns (S storage) { + S storage rTmp; + return rTmp; +} contract C { - function f() public view { - S storage s; - s.f || true; + S s; + function f() public { + S storage sTmp; + sTmp | s; } } // ---- -// TypeError 3464: (95-96): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError 3464: (143-147): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. +// TypeError 3464: (232-236): This variable is of storage pointer type and can be accessed without prior assignment, which would lead to undefined behaviour. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol index caf55376d..9594a2a9f 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/203_struct_reference_compare_operators.sol @@ -7,4 +7,4 @@ contract test { } } // ---- -// TypeError 2271: (79-85): Operator == not compatible with types struct test.s storage ref and struct test.s storage ref. Operator has not been user-defined. +// TypeError 2271: (79-85): Operator == not compatible with types struct test.s storage ref and struct test.s storage ref. 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 b14f28438..8c4be929c 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 @@ -2,7 +2,7 @@ type Int is int128; using { add as +, sub as -, mul as *, div as / - } for Int; +} for Int; function add(Int, Int) pure returns (Int) { return Int.wrap(1); diff --git a/test/libsolidity/syntaxTests/operators/custom/operator_wrong_number_params_return.sol b/test/libsolidity/syntaxTests/operators/custom/operator_wrong_number_params_return.sol index 81b6eb2f0..34b69a259 100644 --- a/test/libsolidity/syntaxTests/operators/custom/operator_wrong_number_params_return.sol +++ b/test/libsolidity/syntaxTests/operators/custom/operator_wrong_number_params_return.sol @@ -4,7 +4,7 @@ using { add as +, sub as -, mul as *, div as /, gt as >, lt as < - } for Int; +} for Int; function add(Int) pure returns (Int) { return Int.wrap(0);