diff --git a/Changelog.md b/Changelog.md index 3ac18f47c..3da4aa96f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,7 +5,7 @@ Language Features: Compiler Features: * Yul Optimizer: Allow replacing the previously hard-coded cleanup sequence by specifying custom steps after a colon delimiter (``:``) in the sequence string. - * Allow user-defined operators via ``using {f as +} for Typename;``. + * Allow defining custom operators for user-defined value types and structs via ``using {f as +} for Typename;`` syntax. Bugfixes: diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index 7797df958..356e28f8d 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,14 +75,14 @@ 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); solAssert(!m_currentNode->resolveFunctionCall(nullptr)); - m_currentNode->functionCall = _operation.annotation().userDefinedFunction; + m_currentNode->functionCall = *_operation.annotation().userDefinedFunction; auto nextNode = newLabel(); connect(m_currentNode, nextNode); @@ -99,11 +99,11 @@ bool ControlFlowBuilder::visit(UnaryOperation const& _operation) { solAssert(!!m_currentNode, ""); - if (_operation.annotation().userDefinedFunction) + if (_operation.annotation().userDefinedFunction.set()) { visitNode(_operation); solAssert(!m_currentNode->resolveFunctionCall(nullptr)); - m_currentNode->functionCall = _operation.annotation().userDefinedFunction; + m_currentNode->functionCall = *_operation.annotation().userDefinedFunction; auto nextNode = newLabel(); diff --git a/libsolidity/analysis/FunctionCallGraph.cpp b/libsolidity/analysis/FunctionCallGraph.cpp index 8f7a816d3..8f0673311 100644 --- a/libsolidity/analysis/FunctionCallGraph.cpp +++ b/libsolidity/analysis/FunctionCallGraph.cpp @@ -206,14 +206,14 @@ bool FunctionCallGraphBuilder::visit(MemberAccess const& _memberAccess) bool FunctionCallGraphBuilder::visit(BinaryOperation const& _binaryOperation) { - if (FunctionDefinition const* function = _binaryOperation.annotation().userDefinedFunction) + if (FunctionDefinition const* function = *_binaryOperation.annotation().userDefinedFunction) functionReferenced(*function, true /* called directly */); return true; } bool FunctionCallGraphBuilder::visit(UnaryOperation const& _unaryOperation) { - if (FunctionDefinition const* function = _unaryOperation.annotation().userDefinedFunction) + if (FunctionDefinition const* function = *_unaryOperation.annotation().userDefinedFunction) functionReferenced(*function, true /* called directly */); return true; } diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index a7f18f298..2f70447e2 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -333,14 +333,14 @@ 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()) + 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()) + reportFunctionCallMutability((*_unaryOperation.annotation().userDefinedFunction)->stateMutability(), _unaryOperation.location()); } void ViewPureChecker::endVisit(FunctionCall const& _functionCall) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index c6d4de92a..f316ab6a0 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -688,14 +688,19 @@ public: /// @returns a list of functions or the single library. std::vector> const& functionsOrLibrary() const { return m_functions; } - auto functionsAndOperators() const { return ranges::zip_view(m_functions, m_operators); } + //auto functionsAndOperators() const { return ranges::zip_view(m_functions, m_operators); } + ranges::zip_view< + ranges::ref_view>>, + ranges::ref_view>> + > + functionsAndOperators() const { return ranges::zip_view(m_functions, m_operators); } bool usesBraces() const { return m_usesBraces; } bool global() const { return m_global; } private: /// Either the single library or a list of functions. std::vector> m_functions; - /// Operators, the functions are applied to. + /// Operators, the functions from @a m_functions implement. std::vector> m_operators; bool m_usesBraces; ASTPointer m_typeName; 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 f2ac33325..93bc52d14 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -828,7 +828,7 @@ bool ASTJsonExporter::visit(UnaryOperation const& _node) make_pair("operator", TokenTraits::toString(_node.getOperator())), make_pair("subExpression", toJson(_node.subExpression())) }; - if (FunctionDefinition const* function = _node.annotation().userDefinedFunction) + if (FunctionDefinition const* function = *_node.annotation().userDefinedFunction) attributes.emplace_back("function", nodeId(*function)); appendExpressionAttributes(attributes, _node.annotation()); setJsonNode(_node, "UnaryOperation", std::move(attributes)); @@ -843,7 +843,7 @@ 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) + if (FunctionDefinition const* function = *_node.annotation().userDefinedFunction) attributes.emplace_back("function", nodeId(*function)); appendExpressionAttributes(attributes, _node.annotation()); setJsonNode(_node, "BinaryOperation", std::move(attributes)); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 490ec3d1b..25e964dd5 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -411,7 +411,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) { CompilerContext::LocationSetter locationSetter(m_context, _unaryOperation); - if (FunctionDefinition const* function = _unaryOperation.annotation().userDefinedFunction) + if (FunctionDefinition const* function = *_unaryOperation.annotation().userDefinedFunction) { solAssert( function->isFree() || function->libraryFunction(), @@ -538,7 +538,7 @@ 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 (FunctionDefinition const* function = *_binaryOperation.annotation().userDefinedFunction) { solAssert( function->isFree() || function->libraryFunction(), diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 70b3aaf59..0dab4a7f6 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -673,7 +673,7 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation) { setLocation(_unaryOperation); - if (FunctionDefinition const* function = _unaryOperation.annotation().userDefinedFunction) + if (FunctionDefinition const* function = *_unaryOperation.annotation().userDefinedFunction) { _unaryOperation.subExpression().accept(*this); setLocation(_unaryOperation); @@ -817,7 +817,7 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) { setLocation(_binOp); - if (FunctionDefinition const* function = _binOp.annotation().userDefinedFunction) + if (FunctionDefinition const* function = *_binOp.annotation().userDefinedFunction) { _binOp.leftExpression().accept(*this); _binOp.rightExpression().accept(*this);