mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Disallow bare fractional literals that incur precision loss.
This commit is contained in:
parent
5df275b846
commit
64408a9173
@ -1030,7 +1030,7 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const*
|
|||||||
{
|
{
|
||||||
if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint)
|
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.");
|
return TypeResult::err("Literal too large or cannot be represented without precision loss.");
|
||||||
else if (!isFractional() && !integerType())
|
else if (!isFractional() && !integerType())
|
||||||
return TypeResult::err("Literal too large.");
|
return TypeResult::err("Literal too large.");
|
||||||
@ -1143,7 +1143,7 @@ u256 RationalNumberType::literalValue(Literal const*) const
|
|||||||
shiftedValue = m_value.numerator();
|
shiftedValue = m_value.numerator();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto fixed = fixedPointType();
|
auto fixed = closestFixedPointType();
|
||||||
solAssert(fixed, "Rational number cannot be represented as fixed point type.");
|
solAssert(fixed, "Rational number cannot be represented as fixed point type.");
|
||||||
unsigned fractionalDigits = fixed->fractionalDigits();
|
unsigned fractionalDigits = fixed->fractionalDigits();
|
||||||
shiftedValue = m_value.numerator() * boost::multiprecision::pow(bigint(10), fractionalDigits) / m_value.denominator();
|
shiftedValue = m_value.numerator() * boost::multiprecision::pow(bigint(10), fractionalDigits) / m_value.denominator();
|
||||||
@ -1164,8 +1164,10 @@ Type const* RationalNumberType::mobileType() const
|
|||||||
{
|
{
|
||||||
if (!isFractional())
|
if (!isFractional())
|
||||||
return integerType();
|
return integerType();
|
||||||
else
|
else if (auto const* fixed = closestFixedPointType())
|
||||||
return fixedPointType();
|
if (isImplicitlyConvertibleTo(*fixed))
|
||||||
|
return fixed;
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
IntegerType const* RationalNumberType::integerType() const
|
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);
|
bool negative = (m_value < 0);
|
||||||
unsigned fractionalDigits = 0;
|
unsigned fractionalDigits = 0;
|
||||||
|
@ -580,7 +580,7 @@ public:
|
|||||||
/// If the integer part does not fit, returns an empty pointer.
|
/// If the integer part does not fit, returns an empty pointer.
|
||||||
/// The rational number is not always implicitly convertible to the resulting type
|
/// The rational number is not always implicitly convertible to the resulting type
|
||||||
/// (for example if precision loss is required).
|
/// (for example if precision loss is required).
|
||||||
FixedPointType const* fixedPointType() const;
|
FixedPointType const* closestFixedPointType() const;
|
||||||
|
|
||||||
/// @returns true if the value is not an integer.
|
/// @returns true if the value is not an integer.
|
||||||
bool isFractional() const { return m_value.denominator() != 1; }
|
bool isFractional() const { return m_value.denominator() != 1; }
|
||||||
|
Loading…
Reference in New Issue
Block a user