diff --git a/Changelog.md b/Changelog.md index 9bed7e9c1..c31aced2a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,9 +1,26 @@ ### 0.5.0 (unreleased) +Breaking Changes: + * Disallow conversions between bytesX and uintY of different size. + * Commandline interface: Require ``-`` if standard input is used as source. + * 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. + * Type Checker: Disallow arithmetic operations for Boolean variables. + +Features: + +Bugfixes: + + + +Features: + + +Bugfixes: ### 0.4.24 (2018-05-16) + Language Features: * Code Generator: Use native shift instructions on target Constantinople. * General: Allow multiple variables to be declared as part of a tuple assignment, e.g. ``(uint a, uint b) = ...``. diff --git a/docs/contracts.rst b/docs/contracts.rst index b73fe2caf..00ef3fc61 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -802,7 +802,7 @@ as topics. The event call above can be performed in the same way as log3( bytes32(msg.value), bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), - bytes32(msg.sender), + bytes32(uint256(msg.sender)), _id ); } diff --git a/docs/types.rst b/docs/types.rst index 5c20dc679..3f799c32e 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -762,7 +762,7 @@ Members // Create a dynamic byte array: bytes memory b = new bytes(200); for (uint i = 0; i < b.length; i++) - b[i] = byte(i); + b[i] = byte(uint8(i)); return b; } } @@ -975,6 +975,15 @@ cut off:: uint32 a = 0x12345678; uint16 b = uint16(a); // b will be 0x5678 now +Since 0.5.0 explicit conversions between integers and fixed-size byte arrays +are only allowed, if both have the same size. To convert between integers and +fixed-size byte arrays of different size, they first have to be explicitly +converted to a matching size. This makes alignment and padding explicit:: + + uint16 x = 0xffff; + bytes32(uint256(x)); // pad on the left + bytes32(bytes2(x)); // pad on the right + .. index:: ! type;deduction, ! var .. _type-deduction: diff --git a/libsolidity/analysis/ControlFlowBuilder.cpp b/libsolidity/analysis/ControlFlowBuilder.cpp index 35d7687c2..5bd39da39 100644 --- a/libsolidity/analysis/ControlFlowBuilder.cpp +++ b/libsolidity/analysis/ControlFlowBuilder.cpp @@ -159,15 +159,14 @@ bool ControlFlowBuilder::visit(WhileStatement const& _whileStatement) { auto afterWhile = newLabel(); auto whileBody = createLabelHere(); + auto condition = newLabel(); { - // Note that "continue" in this case currently indeed jumps to whileBody - // and not to the condition. This is inconsistent with JavaScript and C and - // therefore a bug. This will be fixed in the future (planned for 0.5.0) - // and the Control Flow Graph will have to be adjusted accordingly. - BreakContinueScope scope(*this, afterWhile, whileBody); + BreakContinueScope scope(*this, afterWhile, condition); appendControlFlow(_whileStatement.body()); } + + placeAndConnectLabel(condition); appendControlFlow(_whileStatement.condition()); connect(m_currentNode, whileBody); diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 60e3183c3..000b10630 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -476,7 +476,7 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const return _convertTo.category() == category() || _convertTo.category() == Category::Contract || _convertTo.category() == Category::Enum || - _convertTo.category() == Category::FixedBytes || + (_convertTo.category() == Category::FixedBytes && numBits() == dynamic_cast(_convertTo).numBytes() * 8) || _convertTo.category() == Category::FixedPoint; } @@ -884,7 +884,10 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const { TypePointer mobType = mobileType(); - return mobType && mobType->isExplicitlyConvertibleTo(_convertTo); + return + (mobType && mobType->isExplicitlyConvertibleTo(_convertTo)) || + (!isFractional() && _convertTo.category() == Category::FixedBytes) + ; } TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) const @@ -1281,7 +1284,7 @@ bool FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const { - return _convertTo.category() == Category::Integer || + return (_convertTo.category() == Category::Integer && numBytes() * 8 == dynamic_cast(_convertTo).numBits()) || _convertTo.category() == Category::FixedPoint || _convertTo.category() == category(); } @@ -1358,7 +1361,7 @@ TypePointer BoolType::binaryOperatorResult(Token::Value _operator, TypePointer c { if (category() != _other->category()) return TypePointer(); - if (Token::isCompareOp(_operator) || _operator == Token::And || _operator == Token::Or) + if (_operator == Token::Equal || _operator == Token::NotEqual || _operator == Token::And || _operator == Token::Or) return _other; else return TypePointer(); diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 0889ac7ce..f195b4165 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -666,32 +666,36 @@ bool ContractCompiler::visit(WhileStatement const& _whileStatement) { StackHeightChecker checker(m_context); CompilerContext::LocationSetter locationSetter(m_context, _whileStatement); + eth::AssemblyItem loopStart = m_context.newTag(); eth::AssemblyItem loopEnd = m_context.newTag(); - m_continueTags.push_back(loopStart); m_breakTags.push_back(loopEnd); m_context << loopStart; - // While loops have the condition prepended - if (!_whileStatement.isDoWhile()) - { - compileExpression(_whileStatement.condition()); - m_context << Instruction::ISZERO; - m_context.appendConditionalJumpTo(loopEnd); - } - - _whileStatement.body().accept(*this); - - // Do-while loops have the condition appended if (_whileStatement.isDoWhile()) { + eth::AssemblyItem condition = m_context.newTag(); + m_continueTags.push_back(condition); + + _whileStatement.body().accept(*this); + + m_context << condition; + compileExpression(_whileStatement.condition()); + m_context << Instruction::ISZERO << Instruction::ISZERO; + m_context.appendConditionalJumpTo(loopStart); + } + else + { + m_continueTags.push_back(loopStart); compileExpression(_whileStatement.condition()); m_context << Instruction::ISZERO; m_context.appendConditionalJumpTo(loopEnd); - } - m_context.appendJumpTo(loopStart); + _whileStatement.body().accept(*this); + + m_context.appendJumpTo(loopStart); + } m_context << loopEnd; m_continueTags.pop_back(); diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index 425c5c1e3..8639317ba 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -485,11 +485,7 @@ void SMTChecker::compareOperation(BinaryOperation const& _op) solUnimplementedAssert(SSAVariable::isBool(_op.annotation().commonType->category()), "Operation not yet supported"); value = make_shared( op == Token::Equal ? (left == right) : - op == Token::NotEqual ? (left != right) : - op == Token::LessThan ? (!left && right) : - op == Token::LessThanOrEqual ? (!left || right) : - op == Token::GreaterThan ? (left && !right) : - /*op == Token::GreaterThanOrEqual*/ (left || !right) + /*op == Token::NotEqual*/ (left != right) ); } // TODO: check that other values for op are not possible. diff --git a/solc/CommandLineInterface.cpp b/solc/CommandLineInterface.cpp index 1f04c68a1..89ac88063 100644 --- a/solc/CommandLineInterface.cpp +++ b/solc/CommandLineInterface.cpp @@ -404,9 +404,7 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings() { bool ignoreMissing = m_args.count(g_argIgnoreMissingFiles); bool addStdin = false; - if (!m_args.count(g_argInputFile)) - addStdin = true; - else + if (m_args.count(g_argInputFile)) for (string path: m_args[g_argInputFile].as>()) { auto eq = find(path.begin(), path.end(), '='); @@ -450,6 +448,11 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings() } if (addStdin) m_sourceCodes[g_stdinFileName] = dev::readStandardInput(); + if (m_sourceCodes.size() == 0) + { + cerr << "No input files given. If you wish to use the standard input please specify \"-\" explicity." << endl; + return false; + } return true; } diff --git a/test/cmdlineTests.sh b/test/cmdlineTests.sh index 1137c7b05..74b6a5a7c 100755 --- a/test/cmdlineTests.sh +++ b/test/cmdlineTests.sh @@ -139,25 +139,55 @@ rm -rf "$TMPDIR" echo "Done." printTask "Testing library checksum..." -echo '' | "$SOLC" --link --libraries a:0x90f20564390eAe531E810af625A22f51385Cd222 -! echo '' | "$SOLC" --link --libraries a:0x80f20564390eAe531E810af625A22f51385Cd222 2>/dev/null +echo '' | "$SOLC" - --link --libraries a:0x90f20564390eAe531E810af625A22f51385Cd222 >/dev/null +! echo '' | "$SOLC" - --link --libraries a:0x80f20564390eAe531E810af625A22f51385Cd222 &>/dev/null printTask "Testing long library names..." -echo '' | "$SOLC" --link --libraries aveeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerylonglibraryname:0x90f20564390eAe531E810af625A22f51385Cd222 +echo '' | "$SOLC" - --link --libraries aveeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerylonglibraryname:0x90f20564390eAe531E810af625A22f51385Cd222 >/dev/null -printTask "Testing overwriting files" +printTask "Testing overwriting files..." TMPDIR=$(mktemp -d) ( set -e # First time it works - echo 'contract C {} ' | "$SOLC" --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null + echo 'contract C {} ' | "$SOLC" - --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null # Second time it fails - ! echo 'contract C {} ' | "$SOLC" --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null + ! echo 'contract C {} ' | "$SOLC" - --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null # Unless we force - echo 'contract C {} ' | "$SOLC" --overwrite --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null + echo 'contract C {} ' | "$SOLC" - --overwrite --bin -o "$TMPDIR/non-existing-stuff-to-create" 2>/dev/null ) rm -rf "$TMPDIR" +printTask "Testing assemble, yul, strict-assembly..." +echo '{}' | "$SOLC" - --assemble &>/dev/null +echo '{}' | "$SOLC" - --julia &>/dev/null +echo '{}' | "$SOLC" - --strict-assembly &>/dev/null + +printTask "Testing standard input..." +TMPDIR=$(mktemp -d) +( + set +e + output=$("$SOLC" --bin 2>&1) + result=$? + set -e + + # This should fail + if [[ !("$output" =~ "No input files given") || ($result == 0) ]] ; then + printError "Incorrect response to empty input arg list: $STDERR" + exit 1 + fi + + set +e + output=$(echo 'contract C {} ' | "$SOLC" - --bin 2>/dev/null | grep -q ":C") + result=$? + set -e + + # The contract should be compiled + if [[ "$result" != 0 ]] ; then + exit 1 + fi +) + printTask "Testing soljson via the fuzzer..." TMPDIR=$(mktemp -d) ( diff --git a/test/compilationTests/milestonetracker/RLP.sol b/test/compilationTests/milestonetracker/RLP.sol index 5bb27bb2b..1b8cd1cb3 100644 --- a/test/compilationTests/milestonetracker/RLP.sol +++ b/test/compilationTests/milestonetracker/RLP.sol @@ -263,7 +263,7 @@ library RLP { var (rStartPos, len) = _decode(self); if (len != 1) throw; - uint temp; + uint8 temp; assembly { temp := byte(0, mload(rStartPos)) } diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index beb7b5af6..b3ebb7a5b 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -579,7 +579,7 @@ BOOST_AUTO_TEST_CASE(struct_simple) a = s.a; b = s.b; c = s.c; - d = uint(s.d); + d = uint16(s.d); } } )"; diff --git a/test/libsolidity/SMTChecker.cpp b/test/libsolidity/SMTChecker.cpp index 71fdb906f..ec23f4521 100644 --- a/test/libsolidity/SMTChecker.cpp +++ b/test/libsolidity/SMTChecker.cpp @@ -388,35 +388,6 @@ BOOST_AUTO_TEST_CASE(bool_simple) } )"; CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f(bool x) public pure { - bool y; - assert(x <= y); - } - } - )"; - CHECK_WARNING(text, "Assertion violation happens here"); - text = R"( - contract C { - function f(bool x) public pure { - bool y; - assert(x >= y); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); - text = R"( - contract C { - function f(bool x) public pure { - require(x); - bool y; - assert(x > y); - assert(y < x); - } - } - )"; - CHECK_SUCCESS_NO_WARNINGS(text); } BOOST_AUTO_TEST_CASE(bool_int_mixed) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index d00b174cb..40962294a 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -483,6 +483,27 @@ BOOST_AUTO_TEST_CASE(do_while_loop) testContractAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5); } +BOOST_AUTO_TEST_CASE(do_while_loop_continue) +{ + char const* sourceCode = R"( + contract test { + function f() public pure returns(uint r) { + uint i = 0; + do + { + if (i > 0) return 0; + i++; + continue; + } while (false); + return 42; + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f()"), encodeArgs(42)); +} + BOOST_AUTO_TEST_CASE(nested_loops) { // tests that break and continue statements in nested loops jump to the correct place @@ -1668,7 +1689,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size) char const* sourceCode = R"( contract Test { function bytesToUint(bytes4 s) returns (uint16 h) { - return uint16(s); + return uint16(uint32(s)); } } )"; @@ -1684,7 +1705,7 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size) char const* sourceCode = R"( contract Test { function bytesToUint(bytes4 s) returns (uint64 h) { - return uint64(s); + return uint64(uint32(s)); } } )"; @@ -1731,7 +1752,7 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size) char const* sourceCode = R"( contract Test { function uintToBytes(uint32 h) returns (bytes2 s) { - return bytes2(h); + return bytes2(uint16(h)); } } )"; @@ -1747,7 +1768,7 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) char const* sourceCode = R"( contract Test { function UintToBytes(uint16 h) returns (bytes8 s) { - return bytes8(h); + return bytes8(uint64(h)); } } )"; @@ -3138,7 +3159,7 @@ BOOST_AUTO_TEST_CASE(event) function deposit(bytes32 _id, bool _manually) payable { if (_manually) { bytes32 s = 0x19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f; - log3(bytes32(msg.value), s, bytes32(msg.sender), _id); + log3(bytes32(msg.value), s, bytes32(uint256(msg.sender)), _id); } else { Deposit(msg.sender, _id, msg.value); } @@ -3535,7 +3556,7 @@ BOOST_AUTO_TEST_CASE(event_indexed_string) event E(string indexed r, uint[4] indexed t); function deposit() { bytes(x).length = 90; - for (uint i = 0; i < 90; i++) + for (uint8 i = 0; i < 90; i++) bytes(x)[i] = byte(i); y[0] = 4; y[1] = 5; @@ -4767,7 +4788,7 @@ BOOST_AUTO_TEST_CASE(array_copy_different_packing) function test() returns (bytes10 a, bytes10 b, bytes10 c, bytes10 d, bytes10 e) { data1.length = 9; for (uint i = 0; i < data1.length; ++i) - data1[i] = bytes8(i); + data1[i] = bytes8(uint64(i)); data2 = data1; a = data2[1]; b = data2[2]; @@ -4795,7 +4816,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_simple) bytes17[10] data2; // 1 per slot, no offset counter function test() returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e) { for (uint i = 0; i < data1.length; ++i) - data1[i] = bytes8(i); + data1[i] = bytes8(uint64(i)); data2[8] = data2[9] = 2; data2 = data1; a = data2[1]; @@ -4827,14 +4848,14 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover) uint i; for (i = 0; i < data2.length; ++i) data2[i] = 0xffff; - check = uint(data2[31]) * 0x10000 | uint(data2[14]); + check = uint(uint16(data2[31])) * 0x10000 | uint(uint16(data2[14])); for (i = 0; i < data1.length; ++i) data1[i] = byte(uint8(1 + i)); data2 = data1; for (i = 0; i < 16; ++i) - res1 |= uint(data2[i]) * 0x10000**i; + res1 |= uint(uint16(data2[i])) * 0x10000**i; for (i = 0; i < 16; ++i) - res2 |= uint(data2[16 + i]) * 0x10000**i; + res2 |= uint(uint16(data2[16 + i])) * 0x10000**i; } } )"; @@ -4860,7 +4881,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover2) data1[2] = 3; data1[3] = 4; for (uint i = 0; i < data2.length; ++i) - data2[i] = bytes10(0xffff00 | (1 + i)); + data2[i] = bytes10(uint80(0xffff00 | (1 + i))); data2 = data1; r1 = data2[3]; r2 = data2[4]; @@ -5074,7 +5095,7 @@ BOOST_AUTO_TEST_CASE(byte_array_push_transition) contract c { bytes data; function test() returns (uint) { - for (uint i = 1; i < 40; i++) + for (uint8 i = 1; i < 40; i++) { data.push(byte(i)); if (data.length != i) return 0x1000 + i; @@ -5120,11 +5141,11 @@ BOOST_AUTO_TEST_CASE(bytes_index_access) contract c { bytes data; function direct(bytes arg, uint index) external returns (uint) { - return uint(arg[index]); + return uint(uint8(arg[index])); } function storageCopyRead(bytes arg, uint index) external returns (uint) { data = arg; - return uint(data[index]); + return uint(uint8(data[index])); } function storageWrite() external returns (uint) { data.length = 35; @@ -5135,7 +5156,7 @@ BOOST_AUTO_TEST_CASE(bytes_index_access) data[31] |= 8; data[30] = 1; data[32] = 3; - return uint(data[30]) * 0x100 | uint(data[31]) * 0x10 | uint(data[32]); + return uint(uint8(data[30])) * 0x100 | uint(uint8(data[31])) * 0x10 | uint(uint8(data[32])); } } )"; @@ -5158,7 +5179,7 @@ BOOST_AUTO_TEST_CASE(bytes_delete_element) function test1() external returns (bool) { data.length = 100; for (uint i = 0; i < data.length; i++) - data[i] = byte(i); + data[i] = byte(uint8(i)); delete data[94]; delete data[96]; delete data[98]; @@ -7517,7 +7538,7 @@ BOOST_AUTO_TEST_CASE(short_strings) if (data1[0] != "1") return 10; if (data1[4] != "4") return 11; for (uint i = 0; i < data1.length; i ++) - data1[i] = byte(i * 3); + data1[i] = byte(uint8(i * 3)); if (data1[4] != 4 * 3) return 12; if (data1[67] != 67 * 3) return 13; // change length: long -> short @@ -8333,7 +8354,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_index_access) function g(bytes32 x) returns (uint) { data = [x[0], x[1], x[2]]; data[0] = "12345"; - return uint(data[0][4]); + return uint(uint8(data[0][4])); } } )"; @@ -8391,7 +8412,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_memory_access) function test() returns (bytes) { bytes memory x = new bytes(5); for (uint i = 0; i < x.length; ++i) - x[i] = byte(i + 1); + x[i] = byte(uint8(i + 1)); assembly { mstore(add(x, 32), "12345678901234567890123456789012") } return x; } @@ -8911,7 +8932,7 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types) function f(bytes2 a, uint16 x) returns (uint) { if (a != "ab") return 1; if (x != 0x0102) return 2; - if (bytes3(x) != 0x0102) return 3; + if (bytes3(uint24(x)) != 0x0102) return 3; return 0; } } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 46250d136..d6ab8bef5 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -3858,19 +3858,6 @@ BOOST_AUTO_TEST_CASE(conditional_with_all_types) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(index_access_for_bytes) -{ - char const* text = R"( - contract C { - bytes20 x; - function f(bytes16 b) public { - b[uint(x[2])]; - } - } - )"; - CHECK_SUCCESS(text); -} - BOOST_AUTO_TEST_CASE(uint7_and_uintM_as_identifier) { char const* text = R"( diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index afce18239..3a8585f79 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(array_copy) data1[i] = msg.data[i]; data2 = data1; l = data2.length; - y = uint(data2[x]); + y = uint(uint40(data2[x])); } } )"; diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_fine.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_fine.sol index 6520672cf..55c5edd30 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_fine.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_fine.sol @@ -23,13 +23,8 @@ contract C { } function k() internal view returns (S storage c) { do { - if (s.f) { - continue; - break; - } - else { - c = s; - } + c = s; + continue; } while(false); } } diff --git a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol index f1a92e9c2..7d001c194 100644 --- a/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol +++ b/test/libsolidity/syntaxTests/controlFlow/storageReturn/dowhile_warn.sol @@ -21,6 +21,15 @@ contract C { do { if (s.f) { break; + } + else { + c = s; + } + } while(false); + } + function i() internal view returns (S storage c) { + do { + if (s.f) { continue; } else { @@ -28,8 +37,16 @@ contract C { } } while(false); } + function j() internal view returns (S storage c) { + do { + continue; + c = s; + } while(false); + } } // ---- // Warning: (87-98): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. // Warning: (223-234): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. // Warning: (440-451): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. +// Warning: (654-665): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. +// Warning: (871-882): This variable is of storage pointer type and might be returned without assignment. This can cause storage corruption. Assign the variable (potentially from itself) to remove this warning. diff --git a/test/libsolidity/syntaxTests/types/bool_ops.sol b/test/libsolidity/syntaxTests/types/bool_ops.sol new file mode 100644 index 000000000..910339064 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bool_ops.sol @@ -0,0 +1,53 @@ +contract C { + function f(bool a, bool b) public pure { + bool c; + // OK + c = !a; + c = !b; + c = a == b; + c = a != b; + c = a || b; + c = a && b; + + // Not OK + c = a > b; + c = a < b; + c = a >= b; + c = a <= b; + c = a & b; + c = a | b; + c = a ^ b; + c = ~a; + c = ~b; + c = a + b; + c = a - b; + c = -a; + c = -b; + c = a * b; + c = a / b; + c = a ** b; + c = a % b; + c = a << b; + c = a >> b; + } +} +// ---- +// TypeError: (231-236): Operator > not compatible with types bool and bool +// TypeError: (250-255): Operator < not compatible with types bool and bool +// TypeError: (269-275): Operator >= not compatible with types bool and bool +// TypeError: (289-295): Operator <= not compatible with types bool and bool +// TypeError: (309-314): Operator & not compatible with types bool and bool +// TypeError: (328-333): Operator | not compatible with types bool and bool +// TypeError: (347-352): Operator ^ not compatible with types bool and bool +// TypeError: (366-368): Unary operator ~ cannot be applied to type bool +// TypeError: (382-384): Unary operator ~ cannot be applied to type bool +// TypeError: (398-403): Operator + not compatible with types bool and bool +// TypeError: (417-422): Operator - not compatible with types bool and bool +// TypeError: (436-438): Unary operator - cannot be applied to type bool +// TypeError: (452-454): Unary operator - cannot be applied to type bool +// TypeError: (468-473): Operator * not compatible with types bool and bool +// TypeError: (487-492): Operator / not compatible with types bool and bool +// TypeError: (506-512): Operator ** not compatible with types bool and bool +// TypeError: (526-531): Operator % not compatible with types bool and bool +// TypeError: (545-551): Operator << not compatible with types bool and bool +// TypeError: (565-571): Operator >> not compatible with types bool and bool diff --git a/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol b/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol new file mode 100644 index 000000000..58828a627 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(uint256) { + return uint256(bytes1('')); + } +} +// ---- +// TypeError: (76-95): Explicit type conversion not allowed from "bytes1" to "uint256". diff --git a/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol b/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol new file mode 100644 index 000000000..77e813abb --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(uint32) { + return uint32(bytes32('')); + } +} +// ---- +// TypeError: (75-94): Explicit type conversion not allowed from "bytes32" to "uint32". diff --git a/test/libsolidity/syntaxTests/types/bytes_to_contract.sol b/test/libsolidity/syntaxTests/types/bytes_to_contract.sol index 2a3219ec5..820dbf9bd 100644 --- a/test/libsolidity/syntaxTests/types/bytes_to_contract.sol +++ b/test/libsolidity/syntaxTests/types/bytes_to_contract.sol @@ -1,7 +1,7 @@ contract C { function f() public pure { - C(bytes20(0x1234)); + C(bytes20(uint160(0x1234))); } } // ---- -// TypeError: (64-82): Explicit type conversion not allowed from "bytes20" to "contract C". +// TypeError: (64-91): Explicit type conversion not allowed from "bytes20" to "contract C". diff --git a/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol b/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol new file mode 100644 index 000000000..2963cfd27 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/bytes_to_uint_same_size.sol @@ -0,0 +1,20 @@ +contract C { + function f() public pure returns (uint256) { + return uint256(bytes32(uint256(0))); + } + function g() public pure returns (uint128) { + return uint128(bytes16(uint128(0))); + } + function h() public pure returns (uint64) { + return uint64(bytes8(uint64(0))); + } + function i() public pure returns (uint32) { + return uint32(bytes4(uint32(0))); + } + function j() public pure returns (uint16) { + return uint16(bytes2(uint16(0))); + } + function k() public pure returns (uint8) { + return uint8(bytes1(uint8(0))); + } +} diff --git a/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol b/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol new file mode 100644 index 000000000..f31b4cc0c --- /dev/null +++ b/test/libsolidity/syntaxTests/types/index_access_for_bytes.sol @@ -0,0 +1,6 @@ +contract C { + bytes20 x; + function f(bytes16 b) public view { + b[uint8(x[2])]; + } +} diff --git a/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol b/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol new file mode 100644 index 000000000..f70c89edc --- /dev/null +++ b/test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(bytes1) { + return bytes1(uint256(0)); + } +} +// ---- +// TypeError: (75-93): Explicit type conversion not allowed from "uint256" to "bytes1". diff --git a/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol b/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol new file mode 100644 index 000000000..4153c5c35 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol @@ -0,0 +1,7 @@ +contract C { + function f() public pure returns(bytes32) { + return bytes32(uint32(0)); + } +} +// ---- +// TypeError: (76-94): Explicit type conversion not allowed from "uint32" to "bytes32".