diff options
author | VoR0220 <catalanor0220@gmail.com> | 2016-05-06 06:47:08 +0800 |
---|---|---|
committer | VoR0220 <catalanor0220@gmail.com> | 2016-05-10 00:41:03 +0800 |
commit | a6fc3c8f30d987f90d791c6cc5ec9d0a6a132109 (patch) | |
tree | efeb403b50f1569429dbc342415a71ccb78863d2 | |
parent | bfc238c8d11e118443d373d819deeada9fe1ea3b (diff) | |
download | dexon-solidity-a6fc3c8f30d987f90d791c6cc5ec9d0a6a132109.tar.gz dexon-solidity-a6fc3c8f30d987f90d791c6cc5ec9d0a6a132109.tar.zst dexon-solidity-a6fc3c8f30d987f90d791c6cc5ec9d0a6a132109.zip |
reorganized tests and fixed mobile types and implicit conversions of rationals and fixed point types
one final tweak
check for null types
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 72 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 165 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 207 |
3 files changed, 263 insertions, 181 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 1b37d42e..264fee6b 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -774,8 +774,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) solAssert(!var.typeName(), ""); if ( valueComponentType->category() == Type::Category::RationalNumber && - !dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->integerType() && - !dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->fixedPointType() + !dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->mobileType() ) fatalTypeError(_statement.initialValue()->location(), "Invalid rational " + valueComponentType->toString() + "."); var.annotation().type = valueComponentType->mobileType(); @@ -785,14 +784,32 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) { var.accept(*this); if (!valueComponentType->isImplicitlyConvertibleTo(*var.annotation().type)) - typeError( - _statement.location(), - "Type " + - valueComponentType->toString() + - " is not implicitly convertible to expected type " + - var.annotation().type->toString() + - "." - ); + { + if ( + valueComponentType->category() == Type::Category::RationalNumber && + dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->denominator() != 1 && + !!valueComponentType->mobileType() + ) + typeError( + _statement.location(), + "Type " + + valueComponentType->toString() + + " is not implicitly convertible to expected type " + + var.annotation().type->toString() + + ". Try converting to type " + + valueComponentType->mobileType()->toString() + + " or use an explicit conversion." + ); + else + typeError( + _statement.location(), + "Type " + + valueComponentType->toString() + + " is not implicitly convertible to expected type " + + var.annotation().type->toString() + + "." + ); + } } } return false; @@ -1499,16 +1516,33 @@ Declaration const& TypeChecker::dereference(UserDefinedTypeName const& _typeName void TypeChecker::expectType(Expression const& _expression, Type const& _expectedType) { _expression.accept(*this); - if (!type(_expression)->isImplicitlyConvertibleTo(_expectedType)) - typeError( - _expression.location(), - "Type " + - type(_expression)->toString() + - " is not implicitly convertible to expected type " + - _expectedType.toString() + - "." - ); + { + if ( + type(_expression)->category() == Type::Category::RationalNumber && + dynamic_pointer_cast<RationalNumberType const>(type(_expression))->denominator() != 1 && + !!type(_expression)->mobileType() + ) + typeError( + _expression.location(), + "Type " + + type(_expression)->toString() + + " is not implicitly convertible to expected type " + + _expectedType.toString() + + ". Try converting to type " + + type(_expression)->mobileType()->toString() + + " or using an explicit conversion." + ); + else + typeError( + _expression.location(), + "Type " + + type(_expression)->toString() + + " is not implicitly convertible to expected type " + + _expectedType.toString() + + "." + ); + } } void TypeChecker::requireLValue(Expression const& _expression) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 865e5969..1dbb70e2 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -387,18 +387,8 @@ bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const else return !convertTo.isSigned() || (convertTo.m_integerBits > m_integerBits); } - else if (_convertTo.category() == Category::Integer) - { - IntegerType const& convertTo = dynamic_cast<IntegerType const&>(_convertTo); - if (convertTo.numBits() < m_integerBits) - return false; - else if (isSigned()) - return convertTo.isSigned(); - else - return !convertTo.isSigned() || convertTo.numBits() > m_integerBits; - } - else - return false; + + return false; } bool FixedPointType::isExplicitlyConvertibleTo(Type const& _convertTo) const @@ -459,6 +449,8 @@ TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePoi return commonType; if (Token::isBitOp(_operator) || Token::isBooleanOp(_operator)) return TypePointer(); + if (Token::Exp == _operator) + return TypePointer(); return commonType; } @@ -470,13 +462,12 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal rational numerator; rational denominator(1); - auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.'); - + auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.'); if (radixPoint != _literal.value().end()) { if ( !all_of(radixPoint + 1, _literal.value().end(), ::isdigit) || - !all_of(_literal.value().begin(), radixPoint, ::isdigit) + !all_of(_literal.value().begin(), radixPoint, ::isdigit) ) throw; //Only decimal notation allowed here, leading zeros would switch to octal. @@ -485,8 +476,7 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal _literal.value().end(), [](char const& a) { return a == '0'; } ); - auto fractionalBegin = leadingZeroes != _literal.value().end() ? - leadingZeroes : radixPoint + 1; + auto fractionalBegin = leadingZeroes; denominator = bigint(string(fractionalBegin, _literal.value().end())); denominator /= boost::multiprecision::pow( @@ -498,43 +488,44 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal } else x = bigint(_literal.value()); - switch (_literal.subDenomination()) - { - case Literal::SubDenomination::None: - case Literal::SubDenomination::Wei: - case Literal::SubDenomination::Second: - break; - case Literal::SubDenomination::Szabo: - x *= bigint("1000000000000"); - break; - case Literal::SubDenomination::Finney: - x *= bigint("1000000000000000"); - break; - case Literal::SubDenomination::Ether: - x *= bigint("1000000000000000000"); - break; - case Literal::SubDenomination::Minute: - x *= bigint("60"); - break; - case Literal::SubDenomination::Hour: - x *= bigint("3600"); - break; - case Literal::SubDenomination::Day: - x *= bigint("86400"); - break; - case Literal::SubDenomination::Week: - x *= bigint("604800"); - break; - case Literal::SubDenomination::Year: - x *= bigint("31536000"); - break; - } - } catch (...) { return make_tuple(false, rational(0)); } + switch (_literal.subDenomination()) + { + case Literal::SubDenomination::None: + case Literal::SubDenomination::Wei: + case Literal::SubDenomination::Second: + break; + case Literal::SubDenomination::Szabo: + x *= bigint("1000000000000"); + break; + case Literal::SubDenomination::Finney: + x *= bigint("1000000000000000"); + break; + case Literal::SubDenomination::Ether: + x *= bigint("1000000000000000000"); + break; + case Literal::SubDenomination::Minute: + x *= bigint("60"); + break; + case Literal::SubDenomination::Hour: + x *= bigint("3600"); + break; + case Literal::SubDenomination::Day: + x *= bigint("86400"); + break; + case Literal::SubDenomination::Week: + x *= bigint("604800"); + break; + case Literal::SubDenomination::Year: + x *= bigint("31536000"); + break; + } + + return make_tuple(true, x); } @@ -559,8 +550,14 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const } else if (_convertTo.category() == Category::FixedPoint) { - if (fixedPointType() && fixedPointType()->isImplicitlyConvertibleTo(_convertTo)) - return true; + //call fixed point type...call fractional bits...shift our number by the number of fractional bits... + //...see if it's a whole number. Make helper function for whether or not finitely representable. + if (auto fixed = fixedPointType()) + { + rational value = m_value * boost::multiprecision::pow(bigint(2), fixed->fractionalBits()); + if (value.denominator() == 1 && fixed->isImplicitlyConvertibleTo(_convertTo)) + return true; + } return false; } else if (_convertTo.category() == Category::FixedBytes) @@ -744,7 +741,17 @@ string RationalNumberType::toString(bool) const u256 RationalNumberType::literalValue(Literal const*) const { u256 value; - bigint shiftedValue = integerPart(); + bigint shiftedValue; + + if (m_value.denominator() != 1) + { + rational temporaryValue = m_value; + auto fixed = fixedPointType(); + temporaryValue *= boost::multiprecision::pow(bigint(2), fixed->fractionalBits()); + shiftedValue = temporaryValue.numerator() / temporaryValue.denominator(); + } + else + shiftedValue = integerPart(); // we ignore the literal and hope that the type was correctly determined solAssert(shiftedValue <= u256(-1), "Integer constant too large."); solAssert(shiftedValue >= -(bigint(1) << 255), "Number constant too small."); @@ -772,6 +779,7 @@ TypePointer RationalNumberType::mobileType() const //TODO: combine integerType() and fixedPointType() into one function shared_ptr<IntegerType const> RationalNumberType::integerType() const { + solAssert(m_value.denominator() == 1, "Non integer type found."); bigint value = integerPart(); bool negative = (value < 0); if (negative) // convert to positive number of same bit requirements @@ -788,46 +796,43 @@ shared_ptr<IntegerType const> RationalNumberType::integerType() const shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const { bool negative = (m_value < 0); + bigint fillRationalBits = bigint(1) << 256; //use this because rationals don't have bit ops unsigned fractionalBits = 0; unsigned integerBits = 0; - rational value = m_value; - bigint transitionValue = bigint(1) << 256; - rational maxValue = rational(transitionValue); + rational value = abs(m_value); //convert to absolute value of same type for byte requirements + rational maxValue = negative ? + rational(fillRationalBits) / 2: + rational(fillRationalBits) - 1; - if (!negative) - { - maxValue -= 1; - integerBits = bytesRequired(integerPart()) * 8; - } - else + while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256) { - value = abs(value); - if (integerPart() > 0) - transitionValue = ((0 - integerPart()) - 1) << 1; - else - transitionValue = 0; - integerBits = bytesRequired(transitionValue) * 8; - } - - while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256 - integerBits) - { value *= 0x100; fractionalBits += 8; } - + if (value > maxValue) return shared_ptr<FixedPointType const>(); - bigint v = value.denominator() / value.numerator(); - if (negative) - v = -v; // u256(v) is the actual value that will be put on the stack // From here on, very similar to integerType() - //if (negative) // convert to positive number of same bit requirements - // value = ((0 - value) - 1) << 1; - if (value > u256(-1)) + bigint v = value.numerator() / value.denominator(); + if (negative) //convert back to negative number and then shift into a positive number of equal size + v = (v - 1) << 1; + + if (v > u256(-1)) + return shared_ptr<FixedPointType const>(); + if (0 == integerPart()) + integerBits = 0; + else + integerBits = (bytesRequired(v) * 8) - fractionalBits; + + if (integerBits > 256 || fractionalBits > 256 || fractionalBits + integerBits > 256) return shared_ptr<FixedPointType const>(); - //solAssert(integerBits >= fractionalBits, "Invalid bit requirement calculation."); - //@todo special handling for integerBits == 0 && fractionalBits == 0? + if (integerBits + fractionalBits == 0) + { + integerBits = 0; + fractionalBits = 8; + } + return make_shared<FixedPointType>( integerBits, fractionalBits, negative ? FixedPointType::Modifier::Signed : FixedPointType::Modifier::Unsigned diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index aea2c688..48b58b71 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -3278,286 +3278,316 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_type_long) BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(valid_fixed_types_casting) +BOOST_AUTO_TEST_CASE(fixed_type_int_conversion) { char const* text = R"( contract test { - function f(){ - ufixed8x8 a = ufixed8x8(8765.1234); - ufixed16x16 b = a**2; - ufixed24x24 c = b**3; - ufixed32x32 d = b**2; - ufixed40x40 e = a**5; + function f() { + uint128 a = 3; + int128 b = 4; + fixed c = b; + ufixed d = a; } } )"; - BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(fixed_type_int_conversion) +BOOST_AUTO_TEST_CASE(fixed_type_rational_int_conversion) { char const* text = R"( contract test { function f() { - uint128 a = 3; - int128 b = 4; - fixed c = b; - ufixed d = a; + fixed c = 3; + ufixed d = 4; } } )"; BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(fixed_type_rational_conversion) +BOOST_AUTO_TEST_CASE(fixed_type_rational_fraction_conversion) { char const* text = R"( contract test { function f() { - fixed c = 3; - ufixed d = 4; + fixed a = 4.5; + ufixed d = 2.5; } } )"; BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(fixed_type_literal) +BOOST_AUTO_TEST_CASE(invalid_int_implicit_conversion_from_fixed) { char const* text = R"( contract test { function f() { fixed a = 4.5; - ufixed d = 2.5; + int b = a; + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(rational_unary_operation) +{ + char const* text = R"( + contract test { + function f() { + ufixed8x16 a = +3.25; + fixed8x16 b = -3.25; } } )"; BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(fixed_type_literal_expression) +BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert) +{ + char const* text = R"( + contract A { + function f() { + ufixed0x8 a = 0.5; + ufixed0x56 b = 0.0000000000000006661338147750939242541790008544921875; + fixed0x8 c = -0.5; + fixed0x56 d = -0.0000000000000006661338147750939242541790008544921875; + } + } + )"; + BOOST_CHECK(success(text)); +} + +BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types) { char const* text = R"( contract test { function f() { - ufixed8x248 a = 3.14 * 3; - ufixed8x248 b = 4 - 2.555555; - ufixed0x256 c = 1.0 / 3.0; - ufixed16x240 d = 599 + .5367; - ufixed8x248 e = 35.245 % 12.9; - ufixed8x248 f = 1.2 % 2; - fixed g = 2 ** -2; + ufixed248x8 a = 123456781234567979695948382928485849359686494864095409282048094275023098123.5; + ufixed0x256 b = 0.920890746623327805482905058466021565416131529487595827354393978494366605267637829135688384325135165352082715782143655824815685807141335814463015972119819459298455224338812271036061391763384038070334798471324635050876128428143374549108557403087615966796875; + ufixed0x256 c = 0.0000000000015198847363997979984922685411315294875958273543939784943666052676464653042434787697605517039455161817147718251801220885263595179331845639229818863564267318422845592626219390573301877339317935702714669975697814319204326238832436501979827880859375; + fixed248x8 d = -123456781234567979695948382928485849359686494864095409282048094275023098123.5; + fixed0x256 e = -0.93322335481643744342575580035176794825198893968114429702091846411734101080123092162893656820177312738451291806995868682861328125; + fixed0x256 g = -0.00011788606643744342575580035176794825198893968114429702091846411734101080123092162893656820177312738451291806995868682861328125; } } )"; BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(rational_as_exponent_value) +BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_size) { char const* text = R"( contract test { function f() { - fixed g = 2 ** -2.2; - fixed b = 3 ** 2.56; + ufixed a = 11/4; + ufixed248x8 b = a; } } )"; BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(fixed_type_invalid_size_conversion) +BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_lost_data) { char const* text = R"( contract test { function f() { - fixed a = 1/3; - ufixed248x8 b = a + 2.5; + ufixed0x256 a = 1/3; } } )"; BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(fixed_type_valid_size_conversion) +BOOST_AUTO_TEST_CASE(fixed_type_valid_explicit_conversions) { char const* text = R"( contract test { function f() { - fixed a = 1/3; - ufixed248x8 b = ufixed248x8(a) + 2.5; + ufixed0x256 a = ufixed0x256(1/3); + ufixed0x248 b = ufixed0x248(1/3); + ufixed0x8 c = ufixed0x8(1/3); } } )"; - BOOST_CHECK(!success(text)); + BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(uint_array_declaration_with_fixed_type) +BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational) { char const* text = R"( contract test { function f() { - uint[fixed(3.56)] a; + uint[3.5] a; } } )"; BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(array_declaration_with_fixed_literal) +BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_fixed_type) { char const* text = R"( contract test { function f() { - uint[3.56] a; + uint[fixed(3.5)] a; } } )"; BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal) +BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion) { char const* text = R"( contract test { - mapping(ufixed8x248 => string) fixedString; function f() { - fixedString[3.14] = "Pi"; + bytes32 c = 3.2; } } )"; - BOOST_CHECK(success(text)); + BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(inline_array_fixed_type) +BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion) { char const* text = R"( contract test { function f() { - fixed[3] memory a = [fixed(3.5), fixed(4.1234), fixed(967.32)]; + fixed a = 3.2; + bytes32 c = a; } } )"; - BOOST_CHECK(success(text)); + BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(inline_array_fixed_rationals) +BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal) { char const* text = R"( contract test { + mapping(ufixed8x248 => string) fixedString; function f() { - ufixed8x248[4] memory a = [3.5, 4.1234, 2.5, 4.0]; + fixedString[0.5] = "Half"; } } )"; BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(zero_and_eight_variant_fixed) +BOOST_AUTO_TEST_CASE(fixed_points_inside_structs) { char const* text = R"( - contract A { - ufixed0x8 half = 0.5; + contract test { + struct myStruct { + ufixed a; + int b; + } + myStruct a = myStruct(3.125, 3); } )"; BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types) +BOOST_AUTO_TEST_CASE(inline_array_fixed_types) { char const* text = R"( contract test { function f() { - ufixed0x256 a = 0.12345678; - ufixed24x8 b = 12345678.5; - ufixed0x256 c = 0.00000009; + fixed[3] memory a = [fixed(3.5), fixed(-4.25), fixed(967.125)]; } } )"; BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals) +BOOST_AUTO_TEST_CASE(inline_array_rationals) { char const* text = R"( contract test { function f() { - var a = 0.12345678; - var b = 12345678.0; - var c = 0.00000009; + ufixed8x8[4] memory a = [3.5, 4.125, 2.5, 4.0]; } } )"; BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(invalid_rational_exponent_usage) +BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression) { char const* text = R"( contract test { function f() { - fixed8x8 a = 3 ** 1.5; - fixed24x24 b = 2 ** (1/2); - fixed40x40 c = 42 ** (-1/4); - fixed48x48 d = 16 ** -0.33; + ufixed8x8 a = 3.5 * 3; + ufixed8x8 b = 4 - 2.5; + ufixed8x8 c = 11 / 4; + ufixed16x240 d = 599 + 0.21875; + ufixed8x248 e = ufixed8x248(35.245 % 12.9); + ufixed8x248 f = ufixed8x248(1.2 % 2); + fixed g = 2 ** -2; } } )"; - BOOST_CHECK(!success(text)); + BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents) +BOOST_AUTO_TEST_CASE(rational_as_exponent_value) { char const* text = R"( contract test { function f() { - fixed a = 3 ** fixed(1.5); - fixed b = 2 ** fixed(1/2); - fixed c = 42 ** fixed(-1/4); - fixed d = 16 ** fixed(-0.33); + fixed g = 2 ** -2.2; + ufixed b = 3 ** 2.5; + ufixed24x24 b = 2 ** (1/2); + fixed40x40 c = 42 ** (-1/4); } } )"; - BOOST_CHECK(success(text)); + BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion) +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents) { char const* text = R"( contract test { function f() { - bytes32 c = 3.183; + ufixed a = 3 ** ufixed(1.5); + ufixed b = 2 ** ufixed(1/2); + fixed c = 42 ** fixed(-1/4); + fixed d = 16 ** fixed(-0.33); } } )"; BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion) +BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals) { char const* text = R"( contract test { function f() { - fixed a = 3.183; - bytes32 c = a; + var a = 0.12345678; + var b = 12345678.352; + var c = 0.00000009; } } )"; - BOOST_CHECK(!success(text)); + BOOST_CHECK(success(text)); } -BOOST_AUTO_TEST_CASE(rational_unary_operation) +BOOST_AUTO_TEST_CASE(var_handle_divided_integers) { char const* text = R"( contract test { function f() { - ufixed8x248 a = +3.5134; - fixed8x248 b = -3.5134; + var x = 1/3; } } )"; - BOOST_CHECK(success(text)); + BOOST_CHECK(success(text)); } BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation) @@ -3608,6 +3638,19 @@ BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation) BOOST_CHECK(!success(text)); } +BOOST_AUTO_TEST_CASE(zero_handling) +{ + char const* text = R"( + contract test { + function f() { + fixed8x8 a = 0; + ufixed8x8 b = 0; + } + } + )"; + BOOST_CHECK(success(text)); +} + BOOST_AUTO_TEST_SUITE_END() } |