mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #3036 from ethereum/constant-eval-refactor
Refactor error reporting in ConstantEvaluator
This commit is contained in:
commit
094012dbb0
@ -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.");
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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.");
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"(
|
||||
|
Loading…
Reference in New Issue
Block a user