Prefer mobileType() to check rational range.

This commit is contained in:
chriseth 2016-05-10 10:26:53 +02:00
parent af354d7555
commit 80c368dac1
3 changed files with 23 additions and 26 deletions

View File

@ -772,12 +772,17 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
{ {
// Infer type from value. // Infer type from value.
solAssert(!var.typeName(), ""); solAssert(!var.typeName(), "");
if (
valueComponentType->category() == Type::Category::RationalNumber &&
!dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->mobileType()
)
fatalTypeError(_statement.initialValue()->location(), "Invalid rational " + valueComponentType->toString() + ".");
var.annotation().type = valueComponentType->mobileType(); var.annotation().type = valueComponentType->mobileType();
if (!var.annotation().type)
if (valueComponentType->category() == Type::Category::RationalNumber)
fatalTypeError(
_statement.initialValue()->location(),
"Invalid rational " +
valueComponentType->toString() +
" (absolute value too large or divison by zero)."
);
else
solAssert(false, "");
var.accept(*this); var.accept(*this);
} }
else else
@ -787,8 +792,8 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
{ {
if ( if (
valueComponentType->category() == Type::Category::RationalNumber && valueComponentType->category() == Type::Category::RationalNumber &&
dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->denominator() != 1 && dynamic_cast<RationalNumberType const&>(*valueComponentType).denominator() != 1 &&
!!valueComponentType->mobileType() valueComponentType->mobileType()
) )
typeError( typeError(
_statement.location(), _statement.location(),
@ -818,10 +823,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
void TypeChecker::endVisit(ExpressionStatement const& _statement) void TypeChecker::endVisit(ExpressionStatement const& _statement)
{ {
if (type(_statement.expression())->category() == Type::Category::RationalNumber) if (type(_statement.expression())->category() == Type::Category::RationalNumber)
if ( if (!dynamic_cast<RationalNumberType const&>(*type(_statement.expression())).mobileType())
!dynamic_pointer_cast<RationalNumberType const>(type(_statement.expression()))->integerType() &&
!dynamic_pointer_cast<RationalNumberType const>(type(_statement.expression()))->fixedPointType()
)
typeError(_statement.expression().location(), "Invalid rational number."); typeError(_statement.expression().location(), "Invalid rational number.");
} }
@ -1128,8 +1130,8 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
if (functionType->takesArbitraryParameters()) if (functionType->takesArbitraryParameters())
{ {
if (auto t = dynamic_cast<RationalNumberType const*>(argType.get())) if (auto t = dynamic_cast<RationalNumberType const*>(argType.get()))
if (!t->integerType() && !t->fixedPointType()) if (!t->mobileType())
typeError(arguments[i]->location(), "Rational number too large."); typeError(arguments[i]->location(), "Invalid rational number (too large or division by zero).");
} }
else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i])) else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
typeError( typeError(
@ -1367,7 +1369,7 @@ bool TypeChecker::visit(IndexAccess const& _access)
solAssert(!numberType->denominator() != 1 ,"Invalid type for array access."); solAssert(!numberType->denominator() != 1 ,"Invalid type for array access.");
if (!actualType.isDynamicallySized() && actualType.length() <= numberType->literalValue(nullptr)) if (!actualType.isDynamicallySized() && actualType.length() <= numberType->literalValue(nullptr))
typeError(_access.location(), "Out of bounds array access."); typeError(_access.location(), "Out of bounds array access.");
} }
} }
resultType = actualType.baseType(); resultType = actualType.baseType();
isLValue = actualType.location() != DataLocation::CallData; isLValue = actualType.location() != DataLocation::CallData;
@ -1521,7 +1523,7 @@ void TypeChecker::expectType(Expression const& _expression, Type const& _expecte
if ( if (
type(_expression)->category() == Type::Category::RationalNumber && type(_expression)->category() == Type::Category::RationalNumber &&
dynamic_pointer_cast<RationalNumberType const>(type(_expression))->denominator() != 1 && dynamic_pointer_cast<RationalNumberType const>(type(_expression))->denominator() != 1 &&
!!type(_expression)->mobileType() type(_expression)->mobileType()
) )
typeError( typeError(
_expression.location(), _expression.location(),
@ -1531,7 +1533,7 @@ void TypeChecker::expectType(Expression const& _expression, Type const& _expecte
_expectedType.toString() + _expectedType.toString() +
". Try converting to type " + ". Try converting to type " +
type(_expression)->mobileType()->toString() + type(_expression)->mobileType()->toString() +
" or using an explicit conversion." " or use an explicit conversion."
); );
else else
typeError( typeError(

View File

@ -766,20 +766,15 @@ u256 RationalNumberType::literalValue(Literal const*) const
TypePointer RationalNumberType::mobileType() const TypePointer RationalNumberType::mobileType() const
{ {
if (m_value.denominator() == 1) if (m_value.denominator() == 1)
{ return integerType();
auto intType = integerType(); else
solAssert(!!intType, "mobileType called with invalid integer constant " + toString(false)); return fixedPointType();
return intType;
}
auto fixType = fixedPointType();
solAssert(!!fixType, "mobileType called with invalid fixed constant " + toString(false));
return fixType;
} }
//TODO: combine integerType() and fixedPointType() into one function //TODO: combine integerType() and fixedPointType() into one function
shared_ptr<IntegerType const> RationalNumberType::integerType() const shared_ptr<IntegerType const> RationalNumberType::integerType() const
{ {
solAssert(m_value.denominator() == 1, "Non integer type found."); solAssert(m_value.denominator() == 1, "integerType() called for fractional number.");
bigint value = integerPart(); bigint value = integerPart();
bool negative = (value < 0); bool negative = (value < 0);
if (negative) // convert to positive number of same bit requirements if (negative) // convert to positive number of same bit requirements

View File

@ -205,7 +205,7 @@ public:
virtual unsigned sizeOnStack() const { return 1; } virtual unsigned sizeOnStack() const { return 1; }
/// @returns the mobile (in contrast to static) type corresponding to the given type. /// @returns the mobile (in contrast to static) type corresponding to the given type.
/// This returns the corresponding integer type for ConstantTypes and the pointer type /// This returns the corresponding integer type for ConstantTypes and the pointer type
/// for storage reference types. /// for storage reference types. Might return a null pointer if there is no fitting type.
virtual TypePointer mobileType() const { return shared_from_this(); } virtual TypePointer mobileType() const { return shared_from_this(); }
/// @returns true if this is a non-value type and the data of this type is stored at the /// @returns true if this is a non-value type and the data of this type is stored at the
/// given location. /// given location.