From 48f20289115183ce48bc2df8116069f7460fe9e8 Mon Sep 17 00:00:00 2001 From: RJ Date: Tue, 17 May 2016 10:04:10 -0500 Subject: Support shifting constants --- libsolidity/ast/Types.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 068cc138..a6c73953 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -705,6 +705,28 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ value = rational(denominator, numerator); break; } + case Token::SHL: + { + using boost::multiprecision::pow; + if (fractional) + return TypePointer(); + else if (abs(other.m_value) > numeric_limits::max()) + return TypePointer(); + uint32_t exponent = abs(other.m_value).numerator().convert_to(); + value = m_value.numerator() * pow(bigint(2), exponent); + break; + } + case Token::SHR: + { + using boost::multiprecision::pow; + if (fractional) + return TypePointer(); + else if (abs(other.m_value) > numeric_limits::max()) + return TypePointer(); + uint32_t exponent = abs(other.m_value).numerator().convert_to(); + value = rational(m_value.numerator() / pow(bigint(2), exponent), 1); + break; + } default: return TypePointer(); } -- cgit v1.2.3 From 33250eef9e3322a366a71fbd55df12e829d70726 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 7 Jun 2016 19:36:42 +0100 Subject: Reject negative shifts within constants --- libsolidity/ast/Types.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index a6c73953..3f13d62d 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -710,9 +710,11 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ using boost::multiprecision::pow; if (fractional) return TypePointer(); - else if (abs(other.m_value) > numeric_limits::max()) + else if (other.m_value < 0) return TypePointer(); - uint32_t exponent = abs(other.m_value).numerator().convert_to(); + else if (other.m_value > numeric_limits::max()) + return TypePointer(); + uint32_t exponent = other.m_value.numerator().convert_to(); value = m_value.numerator() * pow(bigint(2), exponent); break; } @@ -721,9 +723,11 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ using boost::multiprecision::pow; if (fractional) return TypePointer(); - else if (abs(other.m_value) > numeric_limits::max()) + else if (other.m_value < 0) return TypePointer(); - uint32_t exponent = abs(other.m_value).numerator().convert_to(); + else if (other.m_value > numeric_limits::max()) + return TypePointer(); + uint32_t exponent = other.m_value.numerator().convert_to(); value = rational(m_value.numerator() / pow(bigint(2), exponent), 1); break; } -- cgit v1.2.3 From 59603f7b8e0fe2847979fe066fb15ecdc911f3e3 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 7 Sep 2016 00:16:49 +0100 Subject: Add tests for constant shifts --- test/libsolidity/SolidityEndToEndTest.cpp | 44 ++++++++++++++++++++++ test/libsolidity/SolidityNameAndTypeResolution.cpp | 40 ++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 692abe57..088fe4d1 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -7260,6 +7260,50 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7))); } +BOOST_AUTO_TEST_CASE(shift_constant_left) +{ + char const* sourceCode = R"( + contract C { + uint public a = 0x42 << 8; + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0x4200))); +} + +BOOST_AUTO_TEST_CASE(shift_negative_constant_left) +{ + char const* sourceCode = R"( + contract C { + int public a = -0x42 << 8; + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x4200))); +} + +BOOST_AUTO_TEST_CASE(shift_constant_right) +{ + char const* sourceCode = R"( + contract C { + uint public a = 0x4200 >> 8; + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0x42))); +} + +BOOST_AUTO_TEST_CASE(shift_negative_constant_right) +{ + char const* sourceCode = R"( + contract C { + int public a = -0x4200 >> 8; + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x42))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 1691b1c5..7eedbefa 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -4039,6 +4039,46 @@ BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); } +BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) +{ + char const* text = R"( + contract C { + uint public a = 0x42 << -8; + } + )"; + BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) +{ + char const* text = R"( + contract C { + uint public a = 0x42 >> -8; + } + )"; + BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) +{ + char const* text = R"( + contract C { + uint public a = 0x42 << 0x100000000; + } + )"; + BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); +} + +BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) +{ + char const* text = R"( + contract C { + uint public a = 0x42 >> 0x100000000; + } + )"; + BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } -- cgit v1.2.3 From 7ac27c957ed061be4f9dafeff686c07cc693d65b Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Thu, 8 Sep 2016 00:26:14 +0100 Subject: Use >> (SAR) to denote constant shifts --- libsolidity/ast/Types.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 3f13d62d..eb98047c 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -718,7 +718,9 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ value = m_value.numerator() * pow(bigint(2), exponent); break; } - case Token::SHR: + // NOTE: we're using >> (SAR) to denote right shifting. The type of the LValue + // determines the resulting type and the type of shift (SAR or SHR). + case Token::SAR: { using boost::multiprecision::pow; if (fractional) -- cgit v1.2.3 From d5c94cb4121f2ab97ea52a5471e18c26434dd6e3 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 19 Oct 2016 20:28:14 +0100 Subject: Add constant shift to the changelog --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index ddfd01c3..343d8aa7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Features: * Inline assembly: support both ``suicide`` and ``selfdestruct`` opcodes (note: ``suicide`` is deprecated). * Include ``keccak256()`` as an alias to ``sha3()``. + * Support shifting constant numbers. Bugfixes: * Disallow unknown options in ``solc``. -- cgit v1.2.3