From 5226d54ed16bb7247c64ac67fec786301a3210ec Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 22 Nov 2017 12:33:11 +0000 Subject: Improve error message for constant evaluator --- libsolidity/analysis/ReferencesResolver.cpp | 2 +- libsolidity/ast/Types.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index f22c95cc..d8030b97 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -150,7 +150,7 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName) ConstantEvaluator e(*length, m_errorReporter); auto const* lengthType = dynamic_cast(length->annotation().type.get()); if (!lengthType || !lengthType->mobileType()) - fatalTypeError(length->location(), "Invalid array length, expected integer literal."); + fatalTypeError(length->location(), "Invalid array length, expected integer literal or constant expression."); else if (lengthType->isFractional()) fatalTypeError(length->location(), "Array with fractional length specified."); else if (lengthType->isNegative()) diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 635279ab..a54e4e09 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -257,7 +257,7 @@ public: } virtual u256 literalValue(Literal const*) const { - solAssert(false, "Literal value requested for type without literals."); + solAssert(false, "Literal value requested for type without literals: " + toString(false)); } /// @returns a (simpler) type that is encoded in the same way for external function calls. -- cgit v1.2.3 From 7ff9a85592cbb50b7a72654849582c780d7fc494 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 22 Nov 2017 12:41:33 +0000 Subject: Reduce the types of errors outputted by ConstantEvaluator --- libsolidity/analysis/ConstantEvaluator.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 4d546e68..7f5ffb51 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -33,7 +33,7 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation) { TypePointer const& subType = _operation.subExpression().annotation().type; if (!dynamic_cast(subType.get())) - m_errorReporter.fatalTypeError(_operation.subExpression().location(), "Invalid constant expression."); + return; TypePointer t = subType->unaryOperatorResult(_operation.getOperator()); _operation.annotation().type = t; } @@ -44,9 +44,9 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation) TypePointer const& leftType = _operation.leftExpression().annotation().type; TypePointer const& rightType = _operation.rightExpression().annotation().type; if (!dynamic_cast(leftType.get())) - m_errorReporter.fatalTypeError(_operation.leftExpression().location(), "Invalid constant expression."); + return; if (!dynamic_cast(rightType.get())) - m_errorReporter.fatalTypeError(_operation.rightExpression().location(), "Invalid constant expression."); + return; TypePointer commonType = leftType->binaryOperatorResult(_operation.getOperator(), rightType); if (!commonType) { @@ -71,8 +71,6 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation) void ConstantEvaluator::endVisit(Literal const& _literal) { _literal.annotation().type = Type::forLiteral(_literal); - if (!_literal.annotation().type) - m_errorReporter.fatalTypeError(_literal.location(), "Invalid literal value."); } void ConstantEvaluator::endVisit(Identifier const& _identifier) @@ -81,11 +79,11 @@ void ConstantEvaluator::endVisit(Identifier const& _identifier) if (!variableDeclaration) return; if (!variableDeclaration->isConstant()) - m_errorReporter.fatalTypeError(_identifier.location(), "Identifier must be declared constant."); + return; - ASTPointer value = variableDeclaration->value(); + ASTPointer const& value = variableDeclaration->value(); if (!value) - m_errorReporter.fatalTypeError(_identifier.location(), "Constant identifier declaration must have a constant value."); + return; if (!value->annotation().type) { -- cgit v1.2.3 From 48c7ba72f3616a037fe3fe8cf1a490b121c416e3 Mon Sep 17 00:00:00 2001 From: chriseth Date: Wed, 22 Nov 2017 12:54:23 +0100 Subject: Simplify ConstantEvaluator. --- libsolidity/analysis/ConstantEvaluator.cpp | 77 ++++++++++++++++------------- libsolidity/analysis/ConstantEvaluator.h | 18 +++++-- libsolidity/analysis/ReferencesResolver.cpp | 7 +-- 3 files changed, 61 insertions(+), 41 deletions(-) (limited to 'libsolidity') diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 7f5ffb51..14171b01 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -28,49 +28,42 @@ using namespace std; using namespace dev; using namespace dev::solidity; -/// FIXME: this is pretty much a copy of TypeChecker::endVisit(BinaryOperation) void ConstantEvaluator::endVisit(UnaryOperation const& _operation) { - TypePointer const& subType = _operation.subExpression().annotation().type; - if (!dynamic_cast(subType.get())) - return; - TypePointer t = subType->unaryOperatorResult(_operation.getOperator()); - _operation.annotation().type = t; + auto sub = type(_operation.subExpression()); + if (sub) + setType(_operation, sub->unaryOperatorResult(_operation.getOperator())); } -/// FIXME: this is pretty much a copy of TypeChecker::endVisit(BinaryOperation) void ConstantEvaluator::endVisit(BinaryOperation const& _operation) { - TypePointer const& leftType = _operation.leftExpression().annotation().type; - TypePointer const& rightType = _operation.rightExpression().annotation().type; - if (!dynamic_cast(leftType.get())) - return; - if (!dynamic_cast(rightType.get())) - return; - TypePointer commonType = leftType->binaryOperatorResult(_operation.getOperator(), rightType); - if (!commonType) + auto left = type(_operation.leftExpression()); + auto right = type(_operation.rightExpression()); + if (left && right) { - m_errorReporter.typeError( - _operation.location(), - "Operator " + - string(Token::toString(_operation.getOperator())) + - " not compatible with types " + - leftType->toString() + - " and " + - rightType->toString() + auto commonType = left->binaryOperatorResult(_operation.getOperator(), right); + if (!commonType) + m_errorReporter.fatalTypeError( + _operation.location(), + "Operator " + + string(Token::toString(_operation.getOperator())) + + " not compatible with types " + + left->toString() + + " and " + + right->toString() + ); + setType( + _operation, + Token::isCompareOp(_operation.getOperator()) ? + make_shared() : + left->binaryOperatorResult(_operation.getOperator(), right) ); - commonType = leftType; } - _operation.annotation().commonType = commonType; - _operation.annotation().type = - Token::isCompareOp(_operation.getOperator()) ? - make_shared() : - commonType; } void ConstantEvaluator::endVisit(Literal const& _literal) { - _literal.annotation().type = Type::forLiteral(_literal); + setType(_literal, Type::forLiteral(_literal)); } void ConstantEvaluator::endVisit(Identifier const& _identifier) @@ -84,13 +77,29 @@ void ConstantEvaluator::endVisit(Identifier const& _identifier) ASTPointer const& value = variableDeclaration->value(); if (!value) return; - - if (!value->annotation().type) + else if (!m_types->count(value.get())) { if (m_depth > 32) m_errorReporter.fatalTypeError(_identifier.location(), "Cyclic constant definition (or maximum recursion depth exhausted)."); - ConstantEvaluator e(*value, m_errorReporter, m_depth + 1); + ConstantEvaluator(m_errorReporter, m_depth + 1, m_types).evaluate(*value); } - _identifier.annotation().type = value->annotation().type; + setType(_identifier, type(*value)); +} + +void ConstantEvaluator::setType(ASTNode const& _node, TypePointer const& _type) +{ + if (_type && _type->category() == Type::Category::RationalNumber) + (*m_types)[&_node] = _type; +} + +TypePointer ConstantEvaluator::type(ASTNode const& _node) +{ + return (*m_types)[&_node]; +} + +TypePointer ConstantEvaluator::evaluate(Expression const& _expr) +{ + _expr.accept(*this); + return type(_expr); } diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h index 6725d610..77a357b6 100644 --- a/libsolidity/analysis/ConstantEvaluator.h +++ b/libsolidity/analysis/ConstantEvaluator.h @@ -38,22 +38,32 @@ class TypeChecker; class ConstantEvaluator: private ASTConstVisitor { public: - ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter, size_t _newDepth = 0): + ConstantEvaluator( + ErrorReporter& _errorReporter, + size_t _newDepth = 0, + std::shared_ptr> _types = std::make_shared>() + ): m_errorReporter(_errorReporter), - m_depth(_newDepth) + m_depth(_newDepth), + m_types(_types) { - _expr.accept(*this); } + TypePointer evaluate(Expression const& _expr); + private: virtual void endVisit(BinaryOperation const& _operation); virtual void endVisit(UnaryOperation const& _operation); virtual void endVisit(Literal const& _literal); virtual void endVisit(Identifier const& _identifier); + void setType(ASTNode const& _node, TypePointer const& _type); + TypePointer type(ASTNode const& _node); + ErrorReporter& m_errorReporter; /// Current recursion depth. - size_t m_depth; + size_t m_depth = 0; + std::shared_ptr> m_types; }; } diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index d8030b97..9eee16af 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -146,9 +146,10 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName) fatalTypeError(_typeName.baseType().location(), "Illegal base type of storage size zero for array."); if (Expression const* length = _typeName.length()) { - if (!length->annotation().type) - ConstantEvaluator e(*length, m_errorReporter); - auto const* lengthType = dynamic_cast(length->annotation().type.get()); + TypePointer lengthTypeGeneric = length->annotation().type; + if (!lengthTypeGeneric) + lengthTypeGeneric = ConstantEvaluator(m_errorReporter).evaluate(*length); + RationalNumberType const* lengthType = dynamic_cast(lengthTypeGeneric.get()); if (!lengthType || !lengthType->mobileType()) fatalTypeError(length->location(), "Invalid array length, expected integer literal or constant expression."); else if (lengthType->isFractional()) -- cgit v1.2.3 From e7ed9d878e80e53da9d4cc603e6527918c5a432a Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 12 Dec 2017 10:45:40 +0100 Subject: Re-use `commonType` --- libsolidity/analysis/ConstantEvaluator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libsolidity') diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 14171b01..83f37f47 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -56,7 +56,7 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation) _operation, Token::isCompareOp(_operation.getOperator()) ? make_shared() : - left->binaryOperatorResult(_operation.getOperator(), right) + commonType ); } } -- cgit v1.2.3