mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Update code to review comments
This commit is contained in:
parent
c1dc8df9c9
commit
3be5114fb0
@ -1790,7 +1790,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
|||||||
_operation.annotation().isConstant = false;
|
_operation.annotation().isConstant = false;
|
||||||
|
|
||||||
// Check if the operator is built-in or user-defined.
|
// Check if the operator is built-in or user-defined.
|
||||||
FunctionDefinitionResult userDefinedOperatorResult = leftType->userDefinedOperator(
|
Result<FunctionDefinition const*> userDefinedOperatorResult = leftType->userDefinedOperator(
|
||||||
_operation.getOperator(),
|
_operation.getOperator(),
|
||||||
*currentDefinitionScope(),
|
*currentDefinitionScope(),
|
||||||
false // _unaryOperation
|
false // _unaryOperation
|
||||||
|
@ -59,6 +59,8 @@ using namespace solidity;
|
|||||||
using namespace solidity::langutil;
|
using namespace solidity::langutil;
|
||||||
using namespace solidity::frontend;
|
using namespace solidity::frontend;
|
||||||
|
|
||||||
|
using util::Result;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -384,7 +386,7 @@ vector<UsingForDirective const*> usingForDirectivesForType(Type const& _type, AS
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionDefinitionResult Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const
|
Result<FunctionDefinition const*> Type::userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const
|
||||||
{
|
{
|
||||||
if (!typeDefinition())
|
if (!typeDefinition())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -412,12 +414,10 @@ FunctionDefinitionResult Type::userDefinedOperator(Token _token, ASTNode const&
|
|||||||
|
|
||||||
if (seenFunctions.size() == 1)
|
if (seenFunctions.size() == 1)
|
||||||
return *seenFunctions.begin();
|
return *seenFunctions.begin();
|
||||||
else if (!!typeDefinition() && seenFunctions.size() == 0)
|
else if (seenFunctions.size() == 0)
|
||||||
return FunctionDefinitionResult::err("Operator has not been user-defined.");
|
return Result<FunctionDefinition const*>::err("No matching user-defined operator found.");
|
||||||
else if (!!typeDefinition())
|
|
||||||
return FunctionDefinitionResult::err("Multiple user-defined functions provided for this operator.");
|
|
||||||
else
|
else
|
||||||
return nullptr;
|
return Result<FunctionDefinition const*>::err("Multiple user-defined functions provided for this operator.");
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope)
|
MemberList::MemberMap Type::boundFunctions(Type const& _type, ASTNode const& _scope)
|
||||||
|
@ -54,7 +54,6 @@ using TypePointers = std::vector<Type const*>;
|
|||||||
using rational = boost::rational<bigint>;
|
using rational = boost::rational<bigint>;
|
||||||
using TypeResult = util::Result<Type const*>;
|
using TypeResult = util::Result<Type const*>;
|
||||||
using BoolResult = util::Result<bool>;
|
using BoolResult = util::Result<bool>;
|
||||||
using FunctionDefinitionResult = util::Result<FunctionDefinition const*>;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +377,7 @@ public:
|
|||||||
/// Clears all internally cached values (if any).
|
/// Clears all internally cached values (if any).
|
||||||
virtual void clearCache() const;
|
virtual void clearCache() const;
|
||||||
|
|
||||||
FunctionDefinitionResult userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const;
|
util::Result<FunctionDefinition const*> userDefinedOperator(Token _token, ASTNode const& _scope, bool _unaryOperation) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// @returns a member list containing all members added to this type by `using for` directives.
|
/// @returns a member list containing all members added to this type by `using for` directives.
|
||||||
|
@ -416,7 +416,8 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
|
|||||||
solAssert(function->isFree(), "Only free functions can be bound to a user type operator.");
|
solAssert(function->isFree(), "Only free functions can be bound to a user type operator.");
|
||||||
|
|
||||||
FunctionType const* functionType = dynamic_cast<FunctionType const*>(
|
FunctionType const* functionType = dynamic_cast<FunctionType const*>(
|
||||||
function->libraryFunction() ? function->typeViaContractName() : function->type());
|
function->libraryFunction() ? function->typeViaContractName() : function->type()
|
||||||
|
);
|
||||||
solAssert(functionType);
|
solAssert(functionType);
|
||||||
|
|
||||||
functionType = dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();
|
functionType = dynamic_cast<FunctionType const&>(*functionType).asBoundFunction();
|
||||||
|
@ -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."
|
"Functions with parameters other than self parameter cannot be bound to a user type unary operator."
|
||||||
);
|
);
|
||||||
|
|
||||||
string parameter = expressionAsType(_unaryOperation.subExpression(), *functionType->selfType());
|
string argument = expressionAsType(_unaryOperation.subExpression(), *functionType->selfType());
|
||||||
solAssert(!parameter.empty());
|
solAssert(!argument.empty());
|
||||||
solAssert(function->isImplemented(), "");
|
solAssert(function->isImplemented(), "");
|
||||||
|
|
||||||
solAssert(
|
solAssert(
|
||||||
function->returnParameters().size() == 1,
|
function->returnParameters().size() == 1,
|
||||||
"A function bound to the user type operator is supposed to return exactly one value."
|
"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."
|
"A return type of the bound function is supposed to be same as a operator type."
|
||||||
);
|
);
|
||||||
|
|
||||||
define(_unaryOperation) <<
|
define(_unaryOperation) <<
|
||||||
m_context.enqueueFunctionForCodeGeneration(*function) <<
|
m_context.enqueueFunctionForCodeGeneration(*function) <<
|
||||||
("(" + parameter + ")\n");
|
("(" + argument + ")\n");
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
contract C {
|
||||||
function f() public view {
|
S s;
|
||||||
S storage s;
|
function f() public {
|
||||||
s.f && true;
|
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.
|
||||||
|
@ -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 {
|
contract C {
|
||||||
function f() public view {
|
S s;
|
||||||
S storage s;
|
function f() public {
|
||||||
s.f || true;
|
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.
|
||||||
|
@ -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.
|
||||||
|
@ -2,7 +2,7 @@ type Int is int128;
|
|||||||
using {
|
using {
|
||||||
add as +, sub as -,
|
add as +, sub as -,
|
||||||
mul as *, div as /
|
mul as *, div as /
|
||||||
} for Int;
|
} for Int;
|
||||||
|
|
||||||
function add(Int, Int) pure returns (Int) {
|
function add(Int, Int) pure returns (Int) {
|
||||||
return Int.wrap(1);
|
return Int.wrap(1);
|
||||||
|
@ -4,7 +4,7 @@ using {
|
|||||||
add as +, sub as -,
|
add as +, sub as -,
|
||||||
mul as *, div as /,
|
mul as *, div as /,
|
||||||
gt as >, lt as <
|
gt as >, lt as <
|
||||||
} for Int;
|
} for Int;
|
||||||
|
|
||||||
function add(Int) pure returns (Int) {
|
function add(Int) pure returns (Int) {
|
||||||
return Int.wrap(0);
|
return Int.wrap(0);
|
||||||
|
Loading…
Reference in New Issue
Block a user