diff options
author | chriseth <chris@ethereum.org> | 2018-08-13 23:25:30 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-13 23:25:30 +0800 |
commit | ae8218543b91a98663ab98de3200a0eec2bfebe3 (patch) | |
tree | 142f8a34907ad0ebd79abfb18dedaac1fa4aa58c /libsolidity | |
parent | 463f4b0f35a9eb930a4cce164135d726c091c50e (diff) | |
parent | 7d7abeb1496dddfab7eb8705dbfc3d06284cf25d (diff) | |
download | dexon-solidity-ae8218543b91a98663ab98de3200a0eec2bfebe3.tar dexon-solidity-ae8218543b91a98663ab98de3200a0eec2bfebe3.tar.gz dexon-solidity-ae8218543b91a98663ab98de3200a0eec2bfebe3.tar.bz2 dexon-solidity-ae8218543b91a98663ab98de3200a0eec2bfebe3.tar.lz dexon-solidity-ae8218543b91a98663ab98de3200a0eec2bfebe3.tar.xz dexon-solidity-ae8218543b91a98663ab98de3200a0eec2bfebe3.tar.zst dexon-solidity-ae8218543b91a98663ab98de3200a0eec2bfebe3.zip |
Merge pull request #4696 from ethereum/byteLiteralConversion
Disallow ambiguous implicit and explicit conversions from number literals to bytesXX
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 16 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 55 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 15 |
3 files changed, 46 insertions, 40 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index bcc3757a..660bb828 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2348,22 +2348,6 @@ void TypeChecker::expectType(Expression const& _expression, Type const& _expecte "." ); } - - if ( - type(_expression)->category() == Type::Category::RationalNumber && - _expectedType.category() == Type::Category::FixedBytes - ) - { - auto literal = dynamic_cast<Literal const*>(&_expression); - - if (literal && !literal->isHexNumber()) - m_errorReporter.warning( - _expression.location(), - "Decimal literal assigned to bytesXX variable will be left-aligned. " - "Use an explicit conversion to silence this warning." - ); - } - } void TypeChecker::requireLValue(Expression const& _expression) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 2dcfda42..349e4a02 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -355,13 +355,7 @@ TypePointer Type::forLiteral(Literal const& _literal) case Token::FalseLiteral: return make_shared<BoolType>(); case Token::Number: - { - tuple<bool, rational> validLiteral = RationalNumberType::isValidLiteral(_literal); - if (get<0>(validLiteral) == true) - return make_shared<RationalNumberType>(get<1>(validLiteral)); - else - return TypePointer(); - } + return RationalNumberType::forLiteral(_literal); case Token::StringLiteral: return make_shared<StringLiteralType>(_literal); default: @@ -779,6 +773,30 @@ tuple<bool, rational> RationalNumberType::parseRational(string const& _value) } } +TypePointer RationalNumberType::forLiteral(Literal const& _literal) +{ + solAssert(_literal.token() == Token::Number, ""); + tuple<bool, rational> validLiteral = isValidLiteral(_literal); + if (get<0>(validLiteral)) + { + TypePointer compatibleBytesType; + if (_literal.isHexNumber()) + { + size_t digitCount = count_if( + _literal.value().begin() + 2, // skip "0x" + _literal.value().end(), + [](unsigned char _c) -> bool { return isxdigit(_c); } + ); + // require even number of digits + if (!(digitCount & 1)) + compatibleBytesType = make_shared<FixedBytesType>(digitCount / 2); + } + + return make_shared<RationalNumberType>(get<1>(validLiteral), compatibleBytesType); + } + return TypePointer(); +} + tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal) { rational value; @@ -918,14 +936,7 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const return false; } case Category::FixedBytes: - { - FixedBytesType const& fixedBytes = dynamic_cast<FixedBytesType const&>(_convertTo); - if (isFractional()) - return false; - if (integerType()) - return fixedBytes.numBytes() * 8 >= integerType()->numBits(); - return false; - } + return (m_value == rational(0)) || (m_compatibleBytesType && *m_compatibleBytesType == _convertTo); default: return false; } @@ -933,11 +944,15 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - TypePointer mobType = mobileType(); - return - (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)) || - (!isFractional() && _convertTo.category() == Category::FixedBytes) - ; + if (isImplicitlyConvertibleTo(_convertTo)) + return true; + else if (_convertTo.category() != Category::FixedBytes) + { + TypePointer mobType = mobileType(); + return (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)); + } + else + return false; } TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) const diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 3b57109d..8bae3d41 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -423,12 +423,12 @@ public: virtual Category category() const override { return Category::RationalNumber; } - /// @returns true if the literal is a valid integer. - static std::tuple<bool, rational> isValidLiteral(Literal const& _literal); + static TypePointer forLiteral(Literal const& _literal); - explicit RationalNumberType(rational const& _value): - m_value(_value) + explicit RationalNumberType(rational const& _value, TypePointer const& _compatibleBytesType = TypePointer()): + m_value(_value), m_compatibleBytesType(_compatibleBytesType) {} + virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override; @@ -462,6 +462,13 @@ public: private: rational m_value; + /// Bytes type to which the rational can be explicitly converted. + /// Empty for all rationals that are not directly parsed from hex literals. + TypePointer m_compatibleBytesType; + + /// @returns true if the literal is a valid integer. + static std::tuple<bool, rational> isValidLiteral(Literal const& _literal); + /// @returns true if the literal is a valid rational number. static std::tuple<bool, rational> parseRational(std::string const& _value); |