OperationAnnotation::userDefinedFunction can be set only once

This commit is contained in:
wechman 2022-09-01 10:04:33 +02:00
parent 59c8ec0e65
commit c507d24a78
8 changed files with 40 additions and 24 deletions

View File

@ -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();

View File

@ -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;
} }

View File

@ -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&>(

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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."

View File

@ -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."