diff options
author | Yi Huang <yi@skymizer.com> | 2018-11-30 17:39:21 +0800 |
---|---|---|
committer | chriseth <chris@ethereum.org> | 2018-12-11 00:31:20 +0800 |
commit | 81f703427e7b34b5488d452eee9e8246e30421bb (patch) | |
tree | e18d162e1b9de2cac75fbebe9658e4ba85e6a4ef /libsolidity/ast | |
parent | 687382ae09106236a97907f72473dc275891f2fc (diff) | |
download | dexon-solidity-81f703427e7b34b5488d452eee9e8246e30421bb.tar dexon-solidity-81f703427e7b34b5488d452eee9e8246e30421bb.tar.gz dexon-solidity-81f703427e7b34b5488d452eee9e8246e30421bb.tar.bz2 dexon-solidity-81f703427e7b34b5488d452eee9e8246e30421bb.tar.lz dexon-solidity-81f703427e7b34b5488d452eee9e8246e30421bb.tar.xz dexon-solidity-81f703427e7b34b5488d452eee9e8246e30421bb.tar.zst dexon-solidity-81f703427e7b34b5488d452eee9e8246e30421bb.zip |
Add tests for implcit conversions from literals to fixed-point numbers.
Diffstat (limited to 'libsolidity/ast')
-rw-r--r-- | libsolidity/ast/Types.cpp | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index f5a38747..621e6513 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -125,6 +125,22 @@ bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2) return fitsPrecisionBaseX(_mantissa, 1.0, _expBase2); } +/// Checks whether _value fits into IntegerType _type. +bool fitsIntegerType(bigint const& _value, IntegerType const& _type) +{ + return (_type.minValue() <= _value) && (_value <= _type.maxValue()); +} + +/// Checks whether _value fits into _bits bits when having 1 bit as the sign bit +/// if _signed is true. +bool fitsIntoBits(bigint const& _value, unsigned _bits, bool _signed) +{ + return fitsIntegerType(_value, IntegerType( + _bits, + _signed ? IntegerType::Modifier::Signed : IntegerType::Modifier::Unsigned + )); +} + } void StorageOffsets::computeOffsets(TypePointers const& _types) @@ -963,27 +979,21 @@ BoolResult RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) if (isFractional()) return false; IntegerType const& targetType = dynamic_cast<IntegerType const&>(_convertTo); - if (m_value == rational(0)) - return true; - unsigned forSignBit = (targetType.isSigned() ? 1 : 0); - if (m_value > rational(0)) - { - if (m_value.numerator() <= (u256(-1) >> (256 - targetType.numBits() + forSignBit))) - return true; - return false; - } - if (targetType.isSigned()) - { - if (-m_value.numerator() <= (u256(1) << (targetType.numBits() - forSignBit))) - return true; - } - return false; + return fitsIntegerType(m_value.numerator(), targetType); } case Category::FixedPoint: { - if (auto fixed = fixedPointType()) - return fixed->isImplicitlyConvertibleTo(_convertTo); - return false; + FixedPointType const& targetType = dynamic_cast<FixedPointType const&>(_convertTo); + // Store a negative number into an unsigned. + if (isNegative() && !targetType.isSigned()) + return false; + if (!isFractional()) + return (targetType.minIntegerValue() <= m_value) && (m_value <= targetType.maxIntegerValue()); + rational value = m_value * pow(bigint(10), targetType.fractionalDigits()); + // Need explicit conversion since truncation will occur. + if (value.denominator() != 1) + return false; + return fitsIntoBits(value.numerator(), targetType.numBits(), targetType.isSigned()); } case Category::FixedBytes: return (m_value == rational(0)) || (m_compatibleBytesType && *m_compatibleBytesType == _convertTo); |