diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index d660318ed..0c4bcfef3 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -65,7 +65,7 @@ bool ControlFlowBuilder::visit(BinaryOperation const& _operation) case Token::And: { visitNode(_operation); - solAssert(!_operation.annotation().userDefinedFunction); + solAssert(!_operation.annotation().userDefinedFunction.set()); appendControlFlow(_operation.leftExpression()); auto nodes = splitFlow<2>(); @@ -75,13 +75,13 @@ bool ControlFlowBuilder::visit(BinaryOperation const& _operation) } default: { - if (_operation.annotation().userDefinedFunction) + if (_operation.annotation().userDefinedFunction.set()) { visitNode(_operation); _operation.leftExpression().accept(*this); _operation.rightExpression().accept(*this); - m_currentNode->functionDefinition = _operation.annotation().userDefinedFunction; + m_currentNode->functionDefinition = *_operation.annotation().userDefinedFunction; auto nextNode = newLabel(); @@ -99,10 +99,10 @@ bool ControlFlowBuilder::visit(UnaryOperation const& _operation) { solAssert(!!m_currentNode); - if (_operation.annotation().userDefinedFunction) + if (_operation.annotation().userDefinedFunction.set()) { visitNode(_operation); - m_currentNode->functionDefinition = _operation.annotation().userDefinedFunction; + m_currentNode->functionDefinition = *_operation.annotation().userDefinedFunction; auto nextNode = newLabel(); diff --git a/libsolidity/analysis/FunctionCallGraph.cpp b/libsolidity/analysis/FunctionCallGraph.cpp index 8f7a816d3..502bd0221 100644 --- a/libsolidity/analysis/FunctionCallGraph.cpp +++ b/libsolidity/analysis/FunctionCallGraph.cpp @@ -206,15 +206,15 @@ bool FunctionCallGraphBuilder::visit(MemberAccess const& _memberAccess) bool FunctionCallGraphBuilder::visit(BinaryOperation const& _binaryOperation) { - if (FunctionDefinition const* function = _binaryOperation.annotation().userDefinedFunction) - functionReferenced(*function, true /* called directly */); + if (_binaryOperation.annotation().userDefinedFunction.set()) + functionReferenced(**_binaryOperation.annotation().userDefinedFunction, true /* called directly */); return true; } bool FunctionCallGraphBuilder::visit(UnaryOperation const& _unaryOperation) { - if (FunctionDefinition const* function = _unaryOperation.annotation().userDefinedFunction) - functionReferenced(*function, true /* called directly */); + if (_unaryOperation.annotation().userDefinedFunction.set()) + functionReferenced(**_unaryOperation.annotation().userDefinedFunction, true /* called directly */); return true; } diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 15c4ef1eb..cac55ceed 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1736,7 +1736,8 @@ bool TypeChecker::visit(UnaryOperation const& _operation) *currentDefinitionScope(), true // _unaryOperation ); - _operation.annotation().userDefinedFunction = userDefinedOperatorResult; + if (userDefinedOperatorResult) + _operation.annotation().userDefinedFunction = userDefinedOperatorResult; FunctionType const* userDefinedFunctionType = nullptr; if (userDefinedOperatorResult) userDefinedFunctionType = &dynamic_cast( @@ -1792,7 +1793,8 @@ void TypeChecker::endVisit(BinaryOperation const& _operation) *currentDefinitionScope(), false // _unaryOperation ); - _operation.annotation().userDefinedFunction = userDefinedOperatorResult; + if (userDefinedOperatorResult) + _operation.annotation().userDefinedFunction = userDefinedOperatorResult; FunctionType const* userDefinedFunctionType = nullptr; if (userDefinedOperatorResult) userDefinedFunctionType = &dynamic_cast( diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index a7f18f298..c73983c29 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -333,14 +333,20 @@ void ViewPureChecker::reportFunctionCallMutability(StateMutability _mutability, void ViewPureChecker::endVisit(BinaryOperation const& _binaryOperation) { - if (_binaryOperation.annotation().userDefinedFunction) - reportFunctionCallMutability(_binaryOperation.annotation().userDefinedFunction->stateMutability(), _binaryOperation.location()); + if (_binaryOperation.annotation().userDefinedFunction.set()) + { + solAssert(*_binaryOperation.annotation().userDefinedFunction); + reportFunctionCallMutability((*_binaryOperation.annotation().userDefinedFunction)->stateMutability(), _binaryOperation.location()); + } } void ViewPureChecker::endVisit(UnaryOperation const& _unaryOperation) { - if (_unaryOperation.annotation().userDefinedFunction) - reportFunctionCallMutability(_unaryOperation.annotation().userDefinedFunction->stateMutability(), _unaryOperation.location()); + if (_unaryOperation.annotation().userDefinedFunction.set()) + { + solAssert((*_unaryOperation.annotation().userDefinedFunction)); + reportFunctionCallMutability((*_unaryOperation.annotation().userDefinedFunction)->stateMutability(), _unaryOperation.location()); + } } void ViewPureChecker::endVisit(FunctionCall const& _functionCall) diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index a9f7abd21..b85eb3ad0 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -314,7 +314,7 @@ struct MemberAccessAnnotation: ExpressionAnnotation struct OperationAnnotation: ExpressionAnnotation { - FunctionDefinition const* userDefinedFunction = nullptr; + util::SetOnce userDefinedFunction; }; struct BinaryOperationAnnotation: OperationAnnotation diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 5e86cc70e..23aa0903f 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -833,8 +833,8 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node) make_pair("operator", TokenTraits::toString(_node.getOperator())), make_pair("subExpression", toJson(_node.subExpression())) }; - if (FunctionDefinition const* referencedDeclaration = _node.annotation().userDefinedFunction) - attributes.emplace_back("function", nodeId(*referencedDeclaration)); + if (_node.annotation().userDefinedFunction.set()) + attributes.emplace_back("function", nodeId(**_node.annotation().userDefinedFunction)); appendExpressionAttributes(attributes, _node.annotation()); setJsonNode(_node, "UnaryOperation", std::move(attributes)); return false; @@ -848,8 +848,8 @@ bool ASTJsonExporter::visit(BinaryOperation const& _node) make_pair("rightExpression", toJson(_node.rightExpression())), make_pair("commonType", typePointerToJson(_node.annotation().commonType)), }; - if (FunctionDefinition const* function = _node.annotation().userDefinedFunction) - attributes.emplace_back("function", nodeId(*function)); + if (_node.annotation().userDefinedFunction.set()) + attributes.emplace_back("function", nodeId(**_node.annotation().userDefinedFunction)); appendExpressionAttributes(attributes, _node.annotation()); setJsonNode(_node, "BinaryOperation", std::move(attributes)); return false; diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index f1fe2cac7..e703f1cfc 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -411,8 +411,10 @@ bool ExpressionCompiler::visit(UnaryOperation const& _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( function->isFree() || function->libraryFunction(), "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); Expression const& leftExpression = _binaryOperation.leftExpression(); 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( function->isFree() || function->libraryFunction(), "Only file-level functions and library functions can be bound to a user type operator." diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 94673959c..963b059d7 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -673,11 +673,13 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation) { setLocation(_unaryOperation); - if (FunctionDefinition const* function = _unaryOperation.annotation().userDefinedFunction) + if (_unaryOperation.annotation().userDefinedFunction.set()) { _unaryOperation.subExpression().accept(*this); setLocation(_unaryOperation); + FunctionDefinition const* function = *_unaryOperation.annotation().userDefinedFunction; + solAssert(function); solAssert( function->isFree() || function->libraryFunction(), "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); - if (FunctionDefinition const* function = _binOp.annotation().userDefinedFunction) + if (_binOp.annotation().userDefinedFunction.set()) { _binOp.leftExpression().accept(*this); _binOp.rightExpression().accept(*this); setLocation(_binOp); + FunctionDefinition const* function = *_binOp.annotation().userDefinedFunction; + solAssert(function); solAssert( function->isFree() || function->libraryFunction(), "Only file-level functions and library functions can be bound to a user type operator."