mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
OperationAnnotation::userDefinedFunction can be set only once
This commit is contained in:
parent
59c8ec0e65
commit
c507d24a78
@ -65,7 +65,7 @@ bool ControlFlowBuilder::visit(BinaryOperation const& _operation)
|
|||||||
case Token::And:
|
case Token::And:
|
||||||
{
|
{
|
||||||
visitNode(_operation);
|
visitNode(_operation);
|
||||||
solAssert(!_operation.annotation().userDefinedFunction);
|
solAssert(!_operation.annotation().userDefinedFunction.set());
|
||||||
appendControlFlow(_operation.leftExpression());
|
appendControlFlow(_operation.leftExpression());
|
||||||
|
|
||||||
auto nodes = splitFlow<2>();
|
auto nodes = splitFlow<2>();
|
||||||
@ -75,13 +75,13 @@ bool ControlFlowBuilder::visit(BinaryOperation const& _operation)
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (_operation.annotation().userDefinedFunction)
|
if (_operation.annotation().userDefinedFunction.set())
|
||||||
{
|
{
|
||||||
visitNode(_operation);
|
visitNode(_operation);
|
||||||
_operation.leftExpression().accept(*this);
|
_operation.leftExpression().accept(*this);
|
||||||
_operation.rightExpression().accept(*this);
|
_operation.rightExpression().accept(*this);
|
||||||
|
|
||||||
m_currentNode->functionDefinition = _operation.annotation().userDefinedFunction;
|
m_currentNode->functionDefinition = *_operation.annotation().userDefinedFunction;
|
||||||
|
|
||||||
auto nextNode = newLabel();
|
auto nextNode = newLabel();
|
||||||
|
|
||||||
@ -99,10 +99,10 @@ bool ControlFlowBuilder::visit(UnaryOperation const& _operation)
|
|||||||
{
|
{
|
||||||
solAssert(!!m_currentNode);
|
solAssert(!!m_currentNode);
|
||||||
|
|
||||||
if (_operation.annotation().userDefinedFunction)
|
if (_operation.annotation().userDefinedFunction.set())
|
||||||
{
|
{
|
||||||
visitNode(_operation);
|
visitNode(_operation);
|
||||||
m_currentNode->functionDefinition = _operation.annotation().userDefinedFunction;
|
m_currentNode->functionDefinition = *_operation.annotation().userDefinedFunction;
|
||||||
|
|
||||||
auto nextNode = newLabel();
|
auto nextNode = newLabel();
|
||||||
|
|
||||||
|
@ -206,15 +206,15 @@ bool FunctionCallGraphBuilder::visit(MemberAccess const& _memberAccess)
|
|||||||
|
|
||||||
bool FunctionCallGraphBuilder::visit(BinaryOperation const& _binaryOperation)
|
bool FunctionCallGraphBuilder::visit(BinaryOperation const& _binaryOperation)
|
||||||
{
|
{
|
||||||
if (FunctionDefinition const* function = _binaryOperation.annotation().userDefinedFunction)
|
if (_binaryOperation.annotation().userDefinedFunction.set())
|
||||||
functionReferenced(*function, true /* called directly */);
|
functionReferenced(**_binaryOperation.annotation().userDefinedFunction, true /* called directly */);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FunctionCallGraphBuilder::visit(UnaryOperation const& _unaryOperation)
|
bool FunctionCallGraphBuilder::visit(UnaryOperation const& _unaryOperation)
|
||||||
{
|
{
|
||||||
if (FunctionDefinition const* function = _unaryOperation.annotation().userDefinedFunction)
|
if (_unaryOperation.annotation().userDefinedFunction.set())
|
||||||
functionReferenced(*function, true /* called directly */);
|
functionReferenced(**_unaryOperation.annotation().userDefinedFunction, true /* called directly */);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1736,7 +1736,8 @@ bool TypeChecker::visit(UnaryOperation const& _operation)
|
|||||||
*currentDefinitionScope(),
|
*currentDefinitionScope(),
|
||||||
true // _unaryOperation
|
true // _unaryOperation
|
||||||
);
|
);
|
||||||
_operation.annotation().userDefinedFunction = userDefinedOperatorResult;
|
if (userDefinedOperatorResult)
|
||||||
|
_operation.annotation().userDefinedFunction = userDefinedOperatorResult;
|
||||||
FunctionType const* userDefinedFunctionType = nullptr;
|
FunctionType const* userDefinedFunctionType = nullptr;
|
||||||
if (userDefinedOperatorResult)
|
if (userDefinedOperatorResult)
|
||||||
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
|
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
|
||||||
@ -1792,7 +1793,8 @@ void TypeChecker::endVisit(BinaryOperation const& _operation)
|
|||||||
*currentDefinitionScope(),
|
*currentDefinitionScope(),
|
||||||
false // _unaryOperation
|
false // _unaryOperation
|
||||||
);
|
);
|
||||||
_operation.annotation().userDefinedFunction = userDefinedOperatorResult;
|
if (userDefinedOperatorResult)
|
||||||
|
_operation.annotation().userDefinedFunction = userDefinedOperatorResult;
|
||||||
FunctionType const* userDefinedFunctionType = nullptr;
|
FunctionType const* userDefinedFunctionType = nullptr;
|
||||||
if (userDefinedOperatorResult)
|
if (userDefinedOperatorResult)
|
||||||
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
|
userDefinedFunctionType = &dynamic_cast<FunctionType const&>(
|
||||||
|
@ -333,14 +333,20 @@ void ViewPureChecker::reportFunctionCallMutability(StateMutability _mutability,
|
|||||||
|
|
||||||
void ViewPureChecker::endVisit(BinaryOperation const& _binaryOperation)
|
void ViewPureChecker::endVisit(BinaryOperation const& _binaryOperation)
|
||||||
{
|
{
|
||||||
if (_binaryOperation.annotation().userDefinedFunction)
|
if (_binaryOperation.annotation().userDefinedFunction.set())
|
||||||
reportFunctionCallMutability(_binaryOperation.annotation().userDefinedFunction->stateMutability(), _binaryOperation.location());
|
{
|
||||||
|
solAssert(*_binaryOperation.annotation().userDefinedFunction);
|
||||||
|
reportFunctionCallMutability((*_binaryOperation.annotation().userDefinedFunction)->stateMutability(), _binaryOperation.location());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewPureChecker::endVisit(UnaryOperation const& _unaryOperation)
|
void ViewPureChecker::endVisit(UnaryOperation const& _unaryOperation)
|
||||||
{
|
{
|
||||||
if (_unaryOperation.annotation().userDefinedFunction)
|
if (_unaryOperation.annotation().userDefinedFunction.set())
|
||||||
reportFunctionCallMutability(_unaryOperation.annotation().userDefinedFunction->stateMutability(), _unaryOperation.location());
|
{
|
||||||
|
solAssert((*_unaryOperation.annotation().userDefinedFunction));
|
||||||
|
reportFunctionCallMutability((*_unaryOperation.annotation().userDefinedFunction)->stateMutability(), _unaryOperation.location());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewPureChecker::endVisit(FunctionCall const& _functionCall)
|
void ViewPureChecker::endVisit(FunctionCall const& _functionCall)
|
||||||
|
@ -314,7 +314,7 @@ struct MemberAccessAnnotation: ExpressionAnnotation
|
|||||||
|
|
||||||
struct OperationAnnotation: ExpressionAnnotation
|
struct OperationAnnotation: ExpressionAnnotation
|
||||||
{
|
{
|
||||||
FunctionDefinition const* userDefinedFunction = nullptr;
|
util::SetOnce<FunctionDefinition const*> userDefinedFunction;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BinaryOperationAnnotation: OperationAnnotation
|
struct BinaryOperationAnnotation: OperationAnnotation
|
||||||
|
@ -833,8 +833,8 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node)
|
|||||||
make_pair("operator", TokenTraits::toString(_node.getOperator())),
|
make_pair("operator", TokenTraits::toString(_node.getOperator())),
|
||||||
make_pair("subExpression", toJson(_node.subExpression()))
|
make_pair("subExpression", toJson(_node.subExpression()))
|
||||||
};
|
};
|
||||||
if (FunctionDefinition const* referencedDeclaration = _node.annotation().userDefinedFunction)
|
if (_node.annotation().userDefinedFunction.set())
|
||||||
attributes.emplace_back("function", nodeId(*referencedDeclaration));
|
attributes.emplace_back("function", nodeId(**_node.annotation().userDefinedFunction));
|
||||||
appendExpressionAttributes(attributes, _node.annotation());
|
appendExpressionAttributes(attributes, _node.annotation());
|
||||||
setJsonNode(_node, "UnaryOperation", std::move(attributes));
|
setJsonNode(_node, "UnaryOperation", std::move(attributes));
|
||||||
return false;
|
return false;
|
||||||
@ -848,8 +848,8 @@ bool ASTJsonExporter::visit(BinaryOperation const& _node)
|
|||||||
make_pair("rightExpression", toJson(_node.rightExpression())),
|
make_pair("rightExpression", toJson(_node.rightExpression())),
|
||||||
make_pair("commonType", typePointerToJson(_node.annotation().commonType)),
|
make_pair("commonType", typePointerToJson(_node.annotation().commonType)),
|
||||||
};
|
};
|
||||||
if (FunctionDefinition const* function = _node.annotation().userDefinedFunction)
|
if (_node.annotation().userDefinedFunction.set())
|
||||||
attributes.emplace_back("function", nodeId(*function));
|
attributes.emplace_back("function", nodeId(**_node.annotation().userDefinedFunction));
|
||||||
appendExpressionAttributes(attributes, _node.annotation());
|
appendExpressionAttributes(attributes, _node.annotation());
|
||||||
setJsonNode(_node, "BinaryOperation", std::move(attributes));
|
setJsonNode(_node, "BinaryOperation", std::move(attributes));
|
||||||
return false;
|
return false;
|
||||||
|
@ -411,8 +411,10 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation)
|
|||||||
{
|
{
|
||||||
CompilerContext::LocationSetter locationSetter(m_context, _unaryOperation);
|
CompilerContext::LocationSetter locationSetter(m_context, _unaryOperation);
|
||||||
|
|
||||||
if (FunctionDefinition const* function = _unaryOperation.annotation().userDefinedFunction)
|
if (_unaryOperation.annotation().userDefinedFunction.set())
|
||||||
{
|
{
|
||||||
|
FunctionDefinition const* function = *_unaryOperation.annotation().userDefinedFunction;
|
||||||
|
solAssert(function);
|
||||||
solAssert(
|
solAssert(
|
||||||
function->isFree() || function->libraryFunction(),
|
function->isFree() || function->libraryFunction(),
|
||||||
"Only file-level functions and library functions can be bound to a user type operator."
|
"Only file-level functions and library functions can be bound to a user type operator."
|
||||||
@ -538,8 +540,10 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation)
|
|||||||
CompilerContext::LocationSetter locationSetter(m_context, _binaryOperation);
|
CompilerContext::LocationSetter locationSetter(m_context, _binaryOperation);
|
||||||
Expression const& leftExpression = _binaryOperation.leftExpression();
|
Expression const& leftExpression = _binaryOperation.leftExpression();
|
||||||
Expression const& rightExpression = _binaryOperation.rightExpression();
|
Expression const& rightExpression = _binaryOperation.rightExpression();
|
||||||
if (FunctionDefinition const* function =_binaryOperation.annotation().userDefinedFunction)
|
if (_binaryOperation.annotation().userDefinedFunction.set())
|
||||||
{
|
{
|
||||||
|
FunctionDefinition const* function = *_binaryOperation.annotation().userDefinedFunction;
|
||||||
|
solAssert(function);
|
||||||
solAssert(
|
solAssert(
|
||||||
function->isFree() || function->libraryFunction(),
|
function->isFree() || function->libraryFunction(),
|
||||||
"Only file-level functions and library functions can be bound to a user type operator."
|
"Only file-level functions and library functions can be bound to a user type operator."
|
||||||
|
@ -673,11 +673,13 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation)
|
|||||||
{
|
{
|
||||||
setLocation(_unaryOperation);
|
setLocation(_unaryOperation);
|
||||||
|
|
||||||
if (FunctionDefinition const* function = _unaryOperation.annotation().userDefinedFunction)
|
if (_unaryOperation.annotation().userDefinedFunction.set())
|
||||||
{
|
{
|
||||||
_unaryOperation.subExpression().accept(*this);
|
_unaryOperation.subExpression().accept(*this);
|
||||||
setLocation(_unaryOperation);
|
setLocation(_unaryOperation);
|
||||||
|
|
||||||
|
FunctionDefinition const* function = *_unaryOperation.annotation().userDefinedFunction;
|
||||||
|
solAssert(function);
|
||||||
solAssert(
|
solAssert(
|
||||||
function->isFree() || function->libraryFunction(),
|
function->isFree() || function->libraryFunction(),
|
||||||
"Only file-level functions and library functions can be bound to a user type operator."
|
"Only file-level functions and library functions can be bound to a user type operator."
|
||||||
@ -817,12 +819,14 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp)
|
|||||||
{
|
{
|
||||||
setLocation(_binOp);
|
setLocation(_binOp);
|
||||||
|
|
||||||
if (FunctionDefinition const* function = _binOp.annotation().userDefinedFunction)
|
if (_binOp.annotation().userDefinedFunction.set())
|
||||||
{
|
{
|
||||||
_binOp.leftExpression().accept(*this);
|
_binOp.leftExpression().accept(*this);
|
||||||
_binOp.rightExpression().accept(*this);
|
_binOp.rightExpression().accept(*this);
|
||||||
setLocation(_binOp);
|
setLocation(_binOp);
|
||||||
|
|
||||||
|
FunctionDefinition const* function = *_binOp.annotation().userDefinedFunction;
|
||||||
|
solAssert(function);
|
||||||
solAssert(
|
solAssert(
|
||||||
function->isFree() || function->libraryFunction(),
|
function->isFree() || function->libraryFunction(),
|
||||||
"Only file-level functions and library functions can be bound to a user type operator."
|
"Only file-level functions and library functions can be bound to a user type operator."
|
||||||
|
Loading…
Reference in New Issue
Block a user