Merge pull request #3036 from ethereum/constant-eval-refactor

Refactor error reporting in ConstantEvaluator
This commit is contained in:
chriseth 2017-10-06 13:50:15 +02:00 committed by GitHub
commit 094012dbb0
7 changed files with 53 additions and 20 deletions

View File

@ -22,17 +22,17 @@
#include <libsolidity/analysis/ConstantEvaluator.h>
#include <libsolidity/ast/AST.h>
#include <libsolidity/interface/ErrorReporter.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;
void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
{
TypePointer const& subType = _operation.subExpression().annotation().type;
if (!dynamic_cast<RationalNumberType const*>(subType.get()))
BOOST_THROW_EXCEPTION(_operation.subExpression().createTypeError("Invalid constant expression."));
m_errorReporter.fatalTypeError(_operation.subExpression().location(), "Invalid constant expression.");
TypePointer t = subType->unaryOperatorResult(_operation.getOperator());
_operation.annotation().type = t;
}
@ -42,9 +42,9 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
TypePointer const& leftType = _operation.leftExpression().annotation().type;
TypePointer const& rightType = _operation.rightExpression().annotation().type;
if (!dynamic_cast<RationalNumberType const*>(leftType.get()))
BOOST_THROW_EXCEPTION(_operation.leftExpression().createTypeError("Invalid constant expression."));
m_errorReporter.fatalTypeError(_operation.leftExpression().location(), "Invalid constant expression.");
if (!dynamic_cast<RationalNumberType const*>(rightType.get()))
BOOST_THROW_EXCEPTION(_operation.rightExpression().createTypeError("Invalid constant expression."));
m_errorReporter.fatalTypeError(_operation.rightExpression().location(), "Invalid constant expression.");
TypePointer commonType = leftType->binaryOperatorResult(_operation.getOperator(), rightType);
if (Token::isCompareOp(_operation.getOperator()))
commonType = make_shared<BoolType>();
@ -55,5 +55,5 @@ void ConstantEvaluator::endVisit(Literal const& _literal)
{
_literal.annotation().type = Type::forLiteral(_literal);
if (!_literal.annotation().type)
BOOST_THROW_EXCEPTION(_literal.createTypeError("Invalid literal value."));
m_errorReporter.fatalTypeError(_literal.location(), "Invalid literal value.");
}

View File

@ -29,6 +29,7 @@ namespace dev
namespace solidity
{
class ErrorReporter;
class TypeChecker;
/**
@ -37,13 +38,18 @@ class TypeChecker;
class ConstantEvaluator: private ASTConstVisitor
{
public:
ConstantEvaluator(Expression const& _expr) { _expr.accept(*this); }
ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter):
m_errorReporter(_errorReporter)
{
_expr.accept(*this);
}
private:
virtual void endVisit(BinaryOperation const& _operation);
virtual void endVisit(UnaryOperation const& _operation);
virtual void endVisit(Literal const& _literal);
ErrorReporter& m_errorReporter;
};
}

View File

@ -147,7 +147,7 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName)
if (Expression const* length = _typeName.length())
{
if (!length->annotation().type)
ConstantEvaluator e(*length);
ConstantEvaluator e(*length, m_errorReporter);
auto const* lengthType = dynamic_cast<RationalNumberType const*>(length->annotation().type.get());
if (!lengthType || !lengthType->mobileType())
fatalTypeError(length->location(), "Invalid array length, expected integer literal.");

View File

@ -22,7 +22,6 @@
#include <libsolidity/ast/AST.h>
#include <libsolidity/ast/ASTVisitor.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/ast/AST_accept.h>
#include <libdevcore/SHA3.h>
@ -73,11 +72,6 @@ ASTAnnotation& ASTNode::annotation() const
return *m_annotation;
}
Error ASTNode::createTypeError(string const& _description) const
{
return Error(Error::Type::TypeError) << errinfo_sourceLocation(location()) << errinfo_comment(_description);
}
SourceUnitAnnotation& SourceUnit::annotation() const
{
if (!m_annotation)

View File

@ -26,7 +26,6 @@
#include <libsolidity/ast/ASTForward.h>
#include <libsolidity/parsing/Token.h>
#include <libsolidity/ast/Types.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/ast/ASTAnnotations.h>
#include <libsolidity/ast/ASTEnums.h>
@ -89,10 +88,6 @@ public:
/// Returns the source code location of this node.
SourceLocation const& location() const { return m_location; }
/// Creates a @ref TypeError exception and decorates it with the location of the node and
/// the given description
Error createTypeError(std::string const& _description) const;
///@todo make this const-safe by providing a different way to access the annotation
virtual ASTAnnotation& annotation() const;

View File

@ -2025,7 +2025,7 @@ unsigned EnumType::memberValue(ASTString const& _member) const
return index;
++index;
}
BOOST_THROW_EXCEPTION(m_enum.createTypeError("Requested unknown enum value ." + _member));
solAssert(false, "Requested unknown enum value " + _member);
}
bool TupleType::isImplicitlyConvertibleTo(Type const& _other) const

View File

@ -7122,7 +7122,7 @@ BOOST_AUTO_TEST_CASE(address_overload_resolution)
CHECK_SUCCESS(text);
}
BOOST_AUTO_TEST_CASE(array_length_validation)
BOOST_AUTO_TEST_CASE(array_length_too_large)
{
char const* text = R"(
contract C {
@ -7132,6 +7132,44 @@ BOOST_AUTO_TEST_CASE(array_length_validation)
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal.");
}
BOOST_AUTO_TEST_CASE(array_length_not_convertible_to_integer)
{
char const* text = R"(
contract C {
uint[true] ids;
}
)";
CHECK_ERROR(text, TypeError, "Invalid array length, expected integer literal.");
}
BOOST_AUTO_TEST_CASE(array_length_invalid_expression)
{
char const* text = R"(
contract C {
uint[-true] ids;
}
)";
CHECK_ERROR(text, TypeError, "Invalid constant expression.");
text = R"(
contract C {
uint[true/1] ids;
}
)";
CHECK_ERROR(text, TypeError, "Invalid constant expression.");
text = R"(
contract C {
uint[1/true] ids;
}
)";
CHECK_ERROR(text, TypeError, "Invalid constant expression.");
text = R"(
contract C {
uint[1.111111E1111111111111] ids;
}
)";
CHECK_ERROR(text, TypeError, "Invalid literal value.");
}
BOOST_AUTO_TEST_CASE(no_address_members_on_contract)
{
char const* text = R"(