From 5cf88593fd72cce672f212fb6065a4e7c94dd471 Mon Sep 17 00:00:00 2001 From: wechman Date: Mon, 26 Sep 2022 13:27:45 +0200 Subject: [PATCH] Add userDefinedFunctionType helper function --- libsolidity/analysis/TypeChecker.cpp | 29 +++++-------------- libsolidity/ast/AST.cpp | 28 ++++++++++++++++++ libsolidity/ast/AST.h | 4 +++ libsolidity/codegen/ExpressionCompiler.cpp | 8 ++--- .../codegen/ir/IRGeneratorForStatements.cpp | 8 ++--- 5 files changed, 44 insertions(+), 33 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index bd9c61a94..2e170e561 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -1740,14 +1740,7 @@ bool TypeChecker::visit(UnaryOperation const& _operation) if (userDefinedOperatorResult) _operation.annotation().userDefinedFunction = userDefinedOperatorResult; - FunctionType const* userDefinedFunctionType = nullptr; - if (userDefinedOperatorResult) - userDefinedFunctionType = &dynamic_cast( - userDefinedOperatorResult.get()->libraryFunction() ? - *userDefinedOperatorResult.get()->typeViaContractName() : - *userDefinedOperatorResult.get()->type() - ); - + FunctionType const* userDefinedFunctionType = _operation.userDefinedFunctionType(); TypeResult builtinResult = subExprType->unaryOperatorResult(op); solAssert(!builtinResult || !userDefinedOperatorResult); @@ -1790,20 +1783,14 @@ void TypeChecker::endVisit(BinaryOperation const& _operation) _operation.annotation().isConstant = false; // Check if the operator is built-in or user-defined. - Result userDefinedOperatorResult = leftType->operatorDefinition( + Result operatorDefinitionResult = leftType->operatorDefinition( _operation.getOperator(), *currentDefinitionScope(), false // _unaryOperation ); - if (userDefinedOperatorResult) - _operation.annotation().userDefinedFunction = userDefinedOperatorResult; - FunctionType const* userDefinedFunctionType = nullptr; - if (userDefinedOperatorResult) - userDefinedFunctionType = &dynamic_cast( - userDefinedOperatorResult.get()->libraryFunction() ? - *userDefinedOperatorResult.get()->typeViaContractName() : - *userDefinedOperatorResult.get()->type() - ); + if (operatorDefinitionResult) + _operation.annotation().userDefinedFunction = operatorDefinitionResult; + FunctionType const* userDefinedFunctionType = _operation.userDefinedFunctionType(); _operation.annotation().isPure = *_operation.leftExpression().annotation().isPure && *_operation.rightExpression().annotation().isPure && @@ -1812,12 +1799,12 @@ void TypeChecker::endVisit(BinaryOperation const& _operation) TypeResult builtinResult = leftType->binaryOperatorResult(_operation.getOperator(), rightType); // Either the operator is user-defined or built-in. - solAssert(!userDefinedOperatorResult || !builtinResult); + solAssert(!operatorDefinitionResult || !builtinResult); Type const* commonType = leftType; if (builtinResult) commonType = builtinResult.get(); - else if (userDefinedOperatorResult) + else if (operatorDefinitionResult) { Type const* normalizedParameterType = userDefinedFunctionType->parameterTypes().at(0); Type const* normalizedLeftType = leftType; @@ -1860,7 +1847,7 @@ void TypeChecker::endVisit(BinaryOperation const& _operation) " and " + rightType->humanReadableName() + "." + (!builtinResult.message().empty() ? " " + builtinResult.message() : "") + - (!userDefinedOperatorResult.message().empty() ? " " + userDefinedOperatorResult.message() : "") + (!operatorDefinitionResult.message().empty() ? " " + operatorDefinitionResult.message() : "") ); _operation.annotation().commonType = commonType; diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 657719340..1e7eae7bf 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -907,6 +907,34 @@ OperationAnnotation& UnaryOperation::annotation() const return initAnnotation(); } +FunctionType const* UnaryOperation::userDefinedFunctionType() const +{ + if (!annotation().userDefinedFunction.set()) + return nullptr; + + FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction; + solAssert(userDefinedFunction); + return dynamic_cast( + userDefinedFunction->libraryFunction() ? + userDefinedFunction->typeViaContractName() : + userDefinedFunction->type() + ); +} + +FunctionType const* BinaryOperation::userDefinedFunctionType() const +{ + if (!annotation().userDefinedFunction.set()) + return nullptr; + + FunctionDefinition const* userDefinedFunction = *annotation().userDefinedFunction; + solAssert(userDefinedFunction); + return dynamic_cast( + userDefinedFunction->libraryFunction() ? + userDefinedFunction->typeViaContractName() : + userDefinedFunction->type() + ); +} + BinaryOperationAnnotation& BinaryOperation::annotation() const { return initAnnotation(); diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 7c22f1811..bb3f9c690 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -2068,6 +2068,8 @@ public: bool isPrefixOperation() const { return m_isPrefix; } Expression const& subExpression() const { return *m_subExpression; } + FunctionType const* userDefinedFunctionType() const; + OperationAnnotation& annotation() const override; private: @@ -2101,6 +2103,8 @@ public: Expression const& rightExpression() const { return *m_right; } Token getOperator() const { return m_operator; } + FunctionType const* userDefinedFunctionType() const; + BinaryOperationAnnotation& annotation() const override; private: diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index e703f1cfc..7712ed2d3 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -420,9 +420,7 @@ bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) "Only file-level functions and library functions can be bound to a user type operator." ); - FunctionType const* functionType = dynamic_cast( - function->libraryFunction() ? function->typeViaContractName() : function->type() - ); + FunctionType const* functionType = _unaryOperation.userDefinedFunctionType(); solAssert(functionType); functionType = dynamic_cast(*functionType).asBoundFunction(); @@ -548,9 +546,7 @@ bool ExpressionCompiler::visit(BinaryOperation const& _binaryOperation) function->isFree() || function->libraryFunction(), "Only file-level functions and library functions can be bound to a user type operator." ); - FunctionType const* functionType = dynamic_cast( - function->libraryFunction() ? function->typeViaContractName() : function->type() - ); + FunctionType const* functionType = _binaryOperation.userDefinedFunctionType(); solAssert(functionType); functionType = dynamic_cast(*functionType).asBoundFunction(); solAssert(functionType); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 963b059d7..3615861c0 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -685,9 +685,7 @@ bool IRGeneratorForStatements::visit(UnaryOperation const& _unaryOperation) "Only file-level functions and library functions can be bound to a user type operator." ); - FunctionType const* functionType = dynamic_cast( - function->libraryFunction() ? function->typeViaContractName() : function->type() - ); + FunctionType const* functionType = _unaryOperation.userDefinedFunctionType(); solAssert(functionType); functionType = dynamic_cast(*functionType).asBoundFunction(); solAssert(functionType); @@ -832,9 +830,7 @@ bool IRGeneratorForStatements::visit(BinaryOperation const& _binOp) "Only file-level functions and library functions can be bound to a user type operator." ); - FunctionType const* functionType = dynamic_cast( - function->libraryFunction() ? function->typeViaContractName() : function->type() - ); + FunctionType const* functionType = _binOp.userDefinedFunctionType(); solAssert(functionType); functionType = dynamic_cast(*functionType).asBoundFunction(); solAssert(functionType);