diff options
| -rw-r--r-- | Changelog.md | 1 | ||||
| -rw-r--r-- | docs/index.rst | 2 | ||||
| -rw-r--r-- | docs/types.rst | 13 | ||||
| -rw-r--r-- | docs/yul.rst (renamed from docs/julia.rst) | 45 | ||||
| -rw-r--r-- | libsolidity/ast/Types.cpp | 11 | ||||
| -rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 33 | ||||
| -rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 172 | ||||
| -rw-r--r-- | test/libsolidity/SyntaxTest.cpp | 13 | ||||
| -rw-r--r-- | test/tools/isoltest.cpp | 27 |
9 files changed, 199 insertions, 118 deletions
diff --git a/Changelog.md b/Changelog.md index 0050f9a6..d5b440b2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ Breaking Changes: * Commandline interface: Require ``-`` if standard input is used as source. * General: New keywords: ``calldata`` * General: ``continue`` in a ``do...while`` loop jumps to the condition (it used to jump to the loop body). Warning: this may silently change the semantics of existing code. + * General: Signed right shift uses proper arithmetic shift, i.e. rounding towards negative infinity. Warning: this may silently change the semantics of existing code! * Introduce ``emit`` as a keyword instead of parsing it as identifier. * Type Checker: Disallow arithmetic operations for Boolean variables. * Disallow trailing dots that are not followed by a number. diff --git a/docs/index.rst b/docs/index.rst index 80b0d6e7..a57b93e4 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -169,7 +169,7 @@ Contents using-the-compiler.rst metadata.rst abi-spec.rst - julia.rst + yul.rst style-guide.rst common-patterns.rst bugs.rst diff --git a/docs/types.rst b/docs/types.rst index 08b74241..009896d5 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -60,15 +60,14 @@ operators are :ref:`literals<rational_literals>` (or literal expressions). Division by zero and modulus with zero throws a runtime exception. The result of a shift operation is the type of the left operand. The -expression ``x << y`` is equivalent to ``x * 2**y``, and ``x >> y`` is -equivalent to ``x / 2**y``. This means that shifting negative numbers -sign extends. Shifting by a negative amount throws a runtime exception. +expression ``x << y`` is equivalent to ``x * 2**y``, and, for positive integers, +``x >> y`` is equivalent to ``x / 2**y``. For negative ``x``, ``x >> y`` +is equivalent to dividing by a power of ``2`` while rounding down (towards negative infinity). +Shifting by a negative amount throws a runtime exception. .. warning:: - The results produced by shift right of negative values of signed integer types is different from those produced - by other programming languages. In Solidity, shift right maps to division so the shifted negative values - are going to be rounded towards zero (truncated). In other programming languages the shift right of negative values - works like division with rounding down (towards negative infinity). + Before version ``0.5.0`` a right shift ``x >> y`` for negative ``x`` was equivalent to ``x / 2**y``, + i.e. right shifts used rounding towards zero instead of rounding towards negative infinity. .. index:: ! ufixed, ! fixed, ! fixed point number diff --git a/docs/julia.rst b/docs/yul.rst index 91b91df2..4f5ef98f 100644 --- a/docs/julia.rst +++ b/docs/yul.rst @@ -1,18 +1,19 @@ -################################################# -Joyfully Universal Language for (Inline) Assembly -################################################# +### +Yul +### -.. _julia: +.. _yul: -.. index:: ! assembly, ! asm, ! evmasm, ! julia +.. index:: ! assembly, ! asm, ! evmasm, ! yul, julia, iulia -JULIA is an intermediate language that can compile to various different backends +Yul (previously also called JULIA or IULIA) is an intermediate language that can +compile to various different backends (EVM 1.0, EVM 1.5 and eWASM are planned). Because of that, it is designed to be a usable common denominator of all three platforms. It can already be used for "inline assembly" inside Solidity and -future versions of the Solidity compiler will even use JULIA as intermediate -language. It should also be easy to build high-level optimizer stages for JULIA. +future versions of the Solidity compiler will even use Yul as intermediate +language. It should also be easy to build high-level optimizer stages for Yul. .. note:: @@ -21,14 +22,14 @@ language. It should also be easy to build high-level optimizer stages for JULIA. to the EVM opcodes. Please resort to the inline assembly documentation for details. -The core components of JULIA are functions, blocks, variables, literals, +The core components of Yul are functions, blocks, variables, literals, for-loops, if-statements, switch-statements, expressions and assignments to variables. -JULIA is typed, both variables and literals must specify the type with postfix +Yul is typed, both variables and literals must specify the type with postfix notation. The supported types are ``bool``, ``u8``, ``s8``, ``u32``, ``s32``, ``u64``, ``s64``, ``u128``, ``s128``, ``u256`` and ``s256``. -JULIA in itself does not even provide operators. If the EVM is targeted, +Yul in itself does not even provide operators. If the EVM is targeted, opcodes will be available as built-in functions, but they can be reimplemented if the backend changes. For a list of mandatory built-in functions, see the section below. @@ -69,10 +70,10 @@ and ``add`` to be available. } } -Specification of JULIA -====================== +Specification of Yul +==================== -JULIA code is described in this chapter. JULIA code is usually placed into a JULIA object, which is described in the following chapter. +This chapter describes Yul code. It is usually placed inside a Yul object, which is described in the following chapter. Grammar:: @@ -156,7 +157,7 @@ Literals cannot be larger than the their type. The largest type defined is 256-b Scoping Rules ------------- -Scopes in JULIA are tied to Blocks (exceptions are functions and the for loop +Scopes in Yul are tied to Blocks (exceptions are functions and the for loop as explained below) and all declarations (``FunctionDefinition``, ``VariableDeclaration``) introduce new identifiers into these scopes. @@ -186,7 +187,7 @@ outside of that function. Formal Specification -------------------- -We formally specify JULIA by providing an evaluation function E overloaded +We formally specify Yul by providing an evaluation function E overloaded on the various nodes of the AST. Any functions can have side effects, so E takes two state objects and the AST node and returns two new state objects and a variable number of other values. @@ -303,7 +304,7 @@ We will use a destructuring notation for the AST nodes. Type Conversion Functions ------------------------- -JULIA has no support for implicit type conversion and therefore functions exist to provide explicit conversion. +Yul has no support for implicit type conversion and therefore functions exist to provide explicit conversion. When converting a larger type to a shorter type a runtime exception can occur in case of an overflow. Truncating conversions are supported between the following types: @@ -507,7 +508,7 @@ The following functions must be available: Backends -------- -Backends or targets are the translators from JULIA to a specific bytecode. Each of the backends can expose functions +Backends or targets are the translators from Yul to a specific bytecode. Each of the backends can expose functions prefixed with the name of the backend. We reserve ``evm_`` and ``ewasm_`` prefixes for the two proposed backends. Backend: EVM @@ -525,8 +526,8 @@ Backend: eWASM TBD -Specification of JULIA Object -============================= +Specification of Yul Object +=========================== Grammar:: @@ -537,9 +538,9 @@ Grammar:: HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'') StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"' -Above, ``Block`` refers to ``Block`` in the JULIA code grammar explained in the previous chapter. +Above, ``Block`` refers to ``Block`` in the Yul code grammar explained in the previous chapter. -An example JULIA Object is shown below: +An example Yul Object is shown below: .. code:: diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 1e0565c0..94e04b6a 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1084,9 +1084,16 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ { uint32_t exponent = other.m_value.numerator().convert_to<uint32_t>(); if (exponent > mostSignificantBit(boost::multiprecision::abs(m_value.numerator()))) - value = 0; + value = m_value.numerator() < 0 ? -1 : 0; else - value = rational(m_value.numerator() / boost::multiprecision::pow(bigint(2), exponent), 1); + { + if (m_value.numerator() < 0) + // add 1 to the negative value before dividing to get a result that is strictly too large + // subtract 1 afterwards to round towards negative infinity + value = rational((m_value.numerator() + 1) / boost::multiprecision::pow(bigint(2), exponent) - bigint(1), 1); + else + value = rational(m_value.numerator() / boost::multiprecision::pow(bigint(2), exponent), 1); + } } break; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 93d440c8..0470c3ec 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1737,11 +1737,36 @@ void ExpressionCompiler::appendShiftOperatorCode(Token::Value _operator, Type co m_context << u256(2) << Instruction::EXP << Instruction::MUL; break; case Token::SAR: - // NOTE: SAR rounds differently than SDIV - if (m_context.evmVersion().hasBitwiseShifting() && !c_valueSigned) - m_context << Instruction::SHR; + if (m_context.evmVersion().hasBitwiseShifting()) + m_context << (c_valueSigned ? Instruction::SAR : Instruction::SHR); else - m_context << u256(2) << Instruction::EXP << Instruction::SWAP1 << (c_valueSigned ? Instruction::SDIV : Instruction::DIV); + { + if (c_valueSigned) + // In the following assembly snippet, xor_mask will be zero, if value_to_shift is positive. + // Therefor xor'ing with xor_mask is the identity and the computation reduces to + // div(value_to_shift, exp(2, shift_amount)), which is correct, since for positive values + // arithmetic right shift is dividing by a power of two (which, as a bitwise operation, results + // in discarding bits on the right and filling with zeros from the left). + // For negative values arithmetic right shift, viewed as a bitwise operation, discards bits to the + // right and fills in ones from the left. This is achieved as follows: + // If value_to_shift is negative, then xor_mask will have all bits set, so xor'ing with xor_mask + // will flip all bits. First all bits in value_to_shift are flipped. As for the positive case, + // dividing by a power of two using integer arithmetic results in discarding bits to the right + // and filling with zeros from the left. Flipping all bits in the result again, turns all zeros + // on the left to ones and restores the non-discarded, shifted bits to their original value (they + // have now been flipped twice). In summary we now have discarded bits to the right and filled with + // ones from the left, i.e. we have performed an arithmetic right shift. + m_context.appendInlineAssembly(R"({ + let xor_mask := sub(0, slt(value_to_shift, 0)) + value_to_shift := xor(div(xor(value_to_shift, xor_mask), exp(2, shift_amount)), xor_mask) + })", {"value_to_shift", "shift_amount"}); + else + m_context.appendInlineAssembly(R"({ + value_to_shift := div(value_to_shift, exp(2, shift_amount)) + })", {"value_to_shift", "shift_amount"}); + m_context << Instruction::POP; + + } break; case Token::SHR: default: diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index b53a9294..3b3cc4f7 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -10487,6 +10487,7 @@ BOOST_AUTO_TEST_CASE(shift_right) ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)), encodeArgs(u256(0x42))); ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)), encodeArgs(u256(0))); ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(uint256,uint256)", u256(1)<<255, u256(5)), encodeArgs(u256(1)<<250)); } BOOST_AUTO_TEST_CASE(shift_right_garbled) @@ -10583,16 +10584,73 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(-1))); +} + +BOOST_AUTO_TEST_CASE(shift_right_negative_literal) +{ + char const* sourceCode = R"( + contract C { + function f1() pure returns (bool) { + return (-4266 >> 0) == -4266; + } + function f2() pure returns (bool) { + return (-4266 >> 1) == -2133; + } + function f3() pure returns (bool) { + return (-4266 >> 4) == -267; + } + function f4() pure returns (bool) { + return (-4266 >> 8) == -17; + } + function f5() pure returns (bool) { + return (-4266 >> 16) == -1; + } + function f6() pure returns (bool) { + return (-4266 >> 17) == -1; + } + function g1() pure returns (bool) { + return (-4267 >> 0) == -4267; + } + function g2() pure returns (bool) { + return (-4267 >> 1) == -2134; + } + function g3() pure returns (bool) { + return (-4267 >> 4) == -267; + } + function g4() pure returns (bool) { + return (-4267 >> 8) == -17; + } + function g5() pure returns (bool) { + return (-4267 >> 16) == -1; + } + function g6() pure returns (bool) { + return (-4267 >> 17) == -1; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("f1()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f2()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f3()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f4()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f5()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("f6()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g1()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g2()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g3()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g4()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g5()"), encodeArgs(true)); + ABI_CHECK(callContractFunction("g6()"), encodeArgs(true)); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int8) @@ -10607,16 +10665,16 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int8) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(0)), encodeArgs(u256(-66))); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(1)), encodeArgs(u256(-33))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(4)), encodeArgs(u256(-4))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(8)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(4)), encodeArgs(u256(-5))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(8)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-66), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(0)), encodeArgs(u256(-67))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(1)), encodeArgs(u256(-33))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(4)), encodeArgs(u256(-4))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(8)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(1)), encodeArgs(u256(-34))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(4)), encodeArgs(u256(-5))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(8)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(-67), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int8) @@ -10630,10 +10688,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int8) )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int8,int8)", u256(0x99u), u256(8)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int16) @@ -10647,10 +10705,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int16) )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(0xFF99u), u256(8)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int32) @@ -10664,10 +10722,10 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_signextend_int32) )"; compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(0)), encodeArgs(u256(-103))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(1)), encodeArgs(u256(-51))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(2)), encodeArgs(u256(-25))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(4)), encodeArgs(u256(-6))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(8)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(1)), encodeArgs(u256(-52))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(2)), encodeArgs(u256(-26))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(4)), encodeArgs(u256(-7))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(0xFFFFFF99u), u256(8)), encodeArgs(u256(-1))); } @@ -10683,16 +10741,16 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int16) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int16,int16)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int32) @@ -10707,16 +10765,16 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_int32) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int32,int32)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) @@ -10732,16 +10790,16 @@ BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)), encodeArgs(u256(-4266))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)), encodeArgs(u256(-1))); ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(0)), encodeArgs(u256(-4267))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2133))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-266))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-16))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(0))); - ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(1)), encodeArgs(u256(-2134))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(4)), encodeArgs(u256(-267))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(8)), encodeArgs(u256(-17))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(16)), encodeArgs(u256(-1))); + ABI_CHECK(callContractFunction("f(int256,int256)", u256(-4267), u256(17)), encodeArgs(u256(-1))); } BOOST_AUTO_TEST_CASE(shift_negative_rvalue) diff --git a/test/libsolidity/SyntaxTest.cpp b/test/libsolidity/SyntaxTest.cpp index 1c2355d5..430073a0 100644 --- a/test/libsolidity/SyntaxTest.cpp +++ b/test/libsolidity/SyntaxTest.cpp @@ -268,9 +268,16 @@ int SyntaxTest::registerTests( [fullpath] { BOOST_REQUIRE_NO_THROW({ - stringstream errorStream; - if (!SyntaxTest(fullpath.string()).run(errorStream)) - BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str()); + try + { + stringstream errorStream; + if (!SyntaxTest(fullpath.string()).run(errorStream)) + BOOST_ERROR("Test expectation mismatch.\n" + errorStream.str()); + } + catch (boost::exception const& _e) + { + BOOST_ERROR("Exception during syntax test: " << boost::diagnostic_information(_e)); + } }); }, _path.stem().string(), diff --git a/test/tools/isoltest.cpp b/test/tools/isoltest.cpp index 100fcbf0..d4b99e9d 100644 --- a/test/tools/isoltest.cpp +++ b/test/tools/isoltest.cpp @@ -150,39 +150,22 @@ SyntaxTestTool::Result SyntaxTestTool::process() m_test = unique_ptr<SyntaxTest>(new SyntaxTest(m_path.string())); success = m_test->run(outputMessages, " ", m_formatted); } - catch(CompilerError const& _e) + catch(boost::exception const& _e) { FormattedScope(cout, m_formatted, {BOLD, RED}) << - "Exception: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(InternalCompilerError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "InternalCompilerError: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(FatalError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "FatalError: " << SyntaxTest::errorMessage(_e) << endl; - return Result::Exception; - } - catch(UnimplementedFeatureError const& _e) - { - FormattedScope(cout, m_formatted, {BOLD, RED}) << - "UnimplementedFeatureError: " << SyntaxTest::errorMessage(_e) << endl; + "Exception during syntax test: " << boost::diagnostic_information(_e) << endl; return Result::Exception; } catch (std::exception const& _e) { - FormattedScope(cout, m_formatted, {BOLD, RED}) << "Exception: " << _e.what() << endl; + FormattedScope(cout, m_formatted, {BOLD, RED}) << + "Exception during syntax test: " << _e.what() << endl; return Result::Exception; } catch(...) { FormattedScope(cout, m_formatted, {BOLD, RED}) << - "Unknown Exception" << endl; + "Unknown exception during syntax test." << endl; return Result::Exception; } |
