From dce846953424d29f7c07f4e25c77d1b841fbe62b Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Mon, 11 Mar 2019 13:28:46 +0100 Subject: [PATCH 1/2] Fix wrong error concatenation --- liblangutil/ErrorReporter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liblangutil/ErrorReporter.h b/liblangutil/ErrorReporter.h index 8b70aabbf..30b494a0f 100644 --- a/liblangutil/ErrorReporter.h +++ b/liblangutil/ErrorReporter.h @@ -98,7 +98,7 @@ public: auto filterEmpty = boost::adaptors::filtered([](std::string const& _s) { return !_s.empty(); }); - std::string errorStr = dev::joinHumanReadable(descs | filterEmpty); + std::string errorStr = dev::joinHumanReadable(descs | filterEmpty, " "); error(Error::Type::TypeError, _location, errorStr); } From d70cb375cfae54d18aea133208c3dbc9f87834b5 Mon Sep 17 00:00:00 2001 From: Mathias Baumann Date: Mon, 11 Mar 2019 13:36:30 +0100 Subject: [PATCH 2/2] isImplicitlyConvertibleTo(): Add better error messages --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 14 +++++++++++--- .../inheritance/wrong_type_base_arguments.sol | 2 +- ...fixed_type_invalid_implicit_conversion_size.sol | 2 +- .../types/rational_number_signed_to_unsigned.sol | 7 +++++++ .../types/rational_number_too_large.sol | 7 +++++++ 6 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 test/libsolidity/syntaxTests/types/rational_number_signed_to_unsigned.sol create mode 100644 test/libsolidity/syntaxTests/types/rational_number_too_large.sol diff --git a/Changelog.md b/Changelog.md index 883e555b7..6726ef123 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Language Features: Compiler Features: + * Type Checker: Give better error messages for some literal conversions * Peephole Optimizer: Remove double ``iszero`` before ``jumpi``. * SMTChecker: Support enums without typecast. * SMTChecker: Support one-dimensional arrays. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 4748b8217..dae0974cc 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -126,9 +126,15 @@ bool fitsPrecisionBase2(bigint const& _mantissa, uint32_t _expBase2) } /// Checks whether _value fits into IntegerType _type. -bool fitsIntegerType(bigint const& _value, IntegerType const& _type) +BoolResult fitsIntegerType(bigint const& _value, IntegerType const& _type) { - return (_type.minValue() <= _value) && (_value <= _type.maxValue()); + if (_value < 0 && !_type.isSigned()) + return BoolResult{std::string("Cannot implicitly convert signed literal to unsigned type.")}; + + if (_type.minValue() > _value || _value > _type.maxValue()) + return BoolResult{"Literal is too large to fit in " + _type.toString(false)}; + + return true; } /// Checks whether _value fits into _bits bits when having 1 bit as the sign bit @@ -722,7 +728,9 @@ BoolResult FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) con if (_convertTo.category() == category()) { FixedPointType const& convertTo = dynamic_cast(_convertTo); - if (convertTo.numBits() < m_totalBits || convertTo.fractionalDigits() < m_fractionalDigits) + if (convertTo.fractionalDigits() < m_fractionalDigits) + return BoolResult{std::string("Too many fractional digits.")}; + if (convertTo.numBits() < m_totalBits) return false; else return convertTo.maxIntegerValue() >= maxIntegerValue() && convertTo.minIntegerValue() <= minIntegerValue(); diff --git a/test/libsolidity/syntaxTests/inheritance/wrong_type_base_arguments.sol b/test/libsolidity/syntaxTests/inheritance/wrong_type_base_arguments.sol index aa29af52a..60df4fa05 100644 --- a/test/libsolidity/syntaxTests/inheritance/wrong_type_base_arguments.sol +++ b/test/libsolidity/syntaxTests/inheritance/wrong_type_base_arguments.sol @@ -6,4 +6,4 @@ contract Derived2 is Base { constructor() Base(2) public { } } // ---- -// TypeError: (74-77): Invalid type for argument in constructor call. Invalid implicit conversion from int_const 300 to uint8 requested. +// TypeError: (74-77): Invalid type for argument in constructor call. Invalid implicit conversion from int_const 300 to uint8 requested. Literal is too large to fit in uint8 diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/315_fixed_type_invalid_implicit_conversion_size.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/315_fixed_type_invalid_implicit_conversion_size.sol index 796982286..f045731ac 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/315_fixed_type_invalid_implicit_conversion_size.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/315_fixed_type_invalid_implicit_conversion_size.sol @@ -5,4 +5,4 @@ contract test { } } // ---- -// TypeError: (75-92): Type ufixed128x18 is not implicitly convertible to expected type ufixed248x8. +// TypeError: (75-92): Type ufixed128x18 is not implicitly convertible to expected type ufixed248x8. Too many fractional digits. diff --git a/test/libsolidity/syntaxTests/types/rational_number_signed_to_unsigned.sol b/test/libsolidity/syntaxTests/types/rational_number_signed_to_unsigned.sol new file mode 100644 index 000000000..735968952 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_signed_to_unsigned.sol @@ -0,0 +1,7 @@ +contract c { + function f() public pure { + uint a = -1; + } +} +// ---- +// TypeError: (52-63): Type int_const -1 is not implicitly convertible to expected type uint256. Cannot implicitly convert signed literal to unsigned type. diff --git a/test/libsolidity/syntaxTests/types/rational_number_too_large.sol b/test/libsolidity/syntaxTests/types/rational_number_too_large.sol new file mode 100644 index 000000000..1482ab604 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/rational_number_too_large.sol @@ -0,0 +1,7 @@ +contract c { + function f() public pure { + uint8 a = 256; + } +} +// ---- +// TypeError: (52-65): Type int_const 256 is not implicitly convertible to expected type uint8. Literal is too large to fit in uint8