Disallow bare fractional literals that incur precision loss.

This commit is contained in:
chriseth 2021-08-17 15:57:02 +02:00
parent 5df275b846
commit 64408a9173
2 changed files with 8 additions and 6 deletions

View File

@ -1030,7 +1030,7 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const*
{
if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint)
{
if (isFractional() && !fixedPointType())
if (isFractional() && !mobileType())
return TypeResult::err("Literal too large or cannot be represented without precision loss.");
else if (!isFractional() && !integerType())
return TypeResult::err("Literal too large.");
@ -1143,7 +1143,7 @@ u256 RationalNumberType::literalValue(Literal const*) const
shiftedValue = m_value.numerator();
else
{
auto fixed = fixedPointType();
auto fixed = closestFixedPointType();
solAssert(fixed, "Rational number cannot be represented as fixed point type.");
unsigned fractionalDigits = fixed->fractionalDigits();
shiftedValue = m_value.numerator() * boost::multiprecision::pow(bigint(10), fractionalDigits) / m_value.denominator();
@ -1164,8 +1164,10 @@ Type const* RationalNumberType::mobileType() const
{
if (!isFractional())
return integerType();
else
return fixedPointType();
else if (auto const* fixed = closestFixedPointType())
if (isImplicitlyConvertibleTo(*fixed))
return fixed;
return nullptr;
}
IntegerType const* RationalNumberType::integerType() const
@ -1184,7 +1186,7 @@ IntegerType const* RationalNumberType::integerType() const
);
}
FixedPointType const* RationalNumberType::fixedPointType() const
FixedPointType const* RationalNumberType::closestFixedPointType() const
{
bool negative = (m_value < 0);
unsigned fractionalDigits = 0;

View File

@ -580,7 +580,7 @@ public:
/// If the integer part does not fit, returns an empty pointer.
/// The rational number is not always implicitly convertible to the resulting type
/// (for example if precision loss is required).
FixedPointType const* fixedPointType() const;
FixedPointType const* closestFixedPointType() const;
/// @returns true if the value is not an integer.
bool isFractional() const { return m_value.denominator() != 1; }