mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
commit
5ee2ce353e
17
Changelog.md
17
Changelog.md
@ -1,9 +1,26 @@
|
|||||||
### 0.5.0 (unreleased)
|
### 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)
|
### 0.4.24 (2018-05-16)
|
||||||
|
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
* Code Generator: Use native shift instructions on target Constantinople.
|
* 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) = ...``.
|
* General: Allow multiple variables to be declared as part of a tuple assignment, e.g. ``(uint a, uint b) = ...``.
|
||||||
|
@ -802,7 +802,7 @@ as topics. The event call above can be performed in the same way as
|
|||||||
log3(
|
log3(
|
||||||
bytes32(msg.value),
|
bytes32(msg.value),
|
||||||
bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
|
bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
|
||||||
bytes32(msg.sender),
|
bytes32(uint256(msg.sender)),
|
||||||
_id
|
_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -762,7 +762,7 @@ Members
|
|||||||
// Create a dynamic byte array:
|
// Create a dynamic byte array:
|
||||||
bytes memory b = new bytes(200);
|
bytes memory b = new bytes(200);
|
||||||
for (uint i = 0; i < b.length; i++)
|
for (uint i = 0; i < b.length; i++)
|
||||||
b[i] = byte(i);
|
b[i] = byte(uint8(i));
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -975,6 +975,15 @@ cut off::
|
|||||||
uint32 a = 0x12345678;
|
uint32 a = 0x12345678;
|
||||||
uint16 b = uint16(a); // b will be 0x5678 now
|
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
|
.. index:: ! type;deduction, ! var
|
||||||
|
|
||||||
.. _type-deduction:
|
.. _type-deduction:
|
||||||
|
@ -159,15 +159,14 @@ bool ControlFlowBuilder::visit(WhileStatement const& _whileStatement)
|
|||||||
{
|
{
|
||||||
auto afterWhile = newLabel();
|
auto afterWhile = newLabel();
|
||||||
auto whileBody = createLabelHere();
|
auto whileBody = createLabelHere();
|
||||||
|
auto condition = newLabel();
|
||||||
|
|
||||||
{
|
{
|
||||||
// Note that "continue" in this case currently indeed jumps to whileBody
|
BreakContinueScope scope(*this, afterWhile, condition);
|
||||||
// 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);
|
|
||||||
appendControlFlow(_whileStatement.body());
|
appendControlFlow(_whileStatement.body());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
placeAndConnectLabel(condition);
|
||||||
appendControlFlow(_whileStatement.condition());
|
appendControlFlow(_whileStatement.condition());
|
||||||
|
|
||||||
connect(m_currentNode, whileBody);
|
connect(m_currentNode, whileBody);
|
||||||
|
@ -476,7 +476,7 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
|||||||
return _convertTo.category() == category() ||
|
return _convertTo.category() == category() ||
|
||||||
_convertTo.category() == Category::Contract ||
|
_convertTo.category() == Category::Contract ||
|
||||||
_convertTo.category() == Category::Enum ||
|
_convertTo.category() == Category::Enum ||
|
||||||
_convertTo.category() == Category::FixedBytes ||
|
(_convertTo.category() == Category::FixedBytes && numBits() == dynamic_cast<FixedBytesType const&>(_convertTo).numBytes() * 8) ||
|
||||||
_convertTo.category() == Category::FixedPoint;
|
_convertTo.category() == Category::FixedPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -884,7 +884,10 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
|||||||
bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||||
{
|
{
|
||||||
TypePointer mobType = mobileType();
|
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
|
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
|
bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||||
{
|
{
|
||||||
return _convertTo.category() == Category::Integer ||
|
return (_convertTo.category() == Category::Integer && numBytes() * 8 == dynamic_cast<IntegerType const&>(_convertTo).numBits()) ||
|
||||||
_convertTo.category() == Category::FixedPoint ||
|
_convertTo.category() == Category::FixedPoint ||
|
||||||
_convertTo.category() == category();
|
_convertTo.category() == category();
|
||||||
}
|
}
|
||||||
@ -1358,7 +1361,7 @@ TypePointer BoolType::binaryOperatorResult(Token::Value _operator, TypePointer c
|
|||||||
{
|
{
|
||||||
if (category() != _other->category())
|
if (category() != _other->category())
|
||||||
return TypePointer();
|
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;
|
return _other;
|
||||||
else
|
else
|
||||||
return TypePointer();
|
return TypePointer();
|
||||||
|
@ -666,32 +666,36 @@ bool ContractCompiler::visit(WhileStatement const& _whileStatement)
|
|||||||
{
|
{
|
||||||
StackHeightChecker checker(m_context);
|
StackHeightChecker checker(m_context);
|
||||||
CompilerContext::LocationSetter locationSetter(m_context, _whileStatement);
|
CompilerContext::LocationSetter locationSetter(m_context, _whileStatement);
|
||||||
|
|
||||||
eth::AssemblyItem loopStart = m_context.newTag();
|
eth::AssemblyItem loopStart = m_context.newTag();
|
||||||
eth::AssemblyItem loopEnd = m_context.newTag();
|
eth::AssemblyItem loopEnd = m_context.newTag();
|
||||||
m_continueTags.push_back(loopStart);
|
|
||||||
m_breakTags.push_back(loopEnd);
|
m_breakTags.push_back(loopEnd);
|
||||||
|
|
||||||
m_context << loopStart;
|
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())
|
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());
|
compileExpression(_whileStatement.condition());
|
||||||
m_context << Instruction::ISZERO;
|
m_context << Instruction::ISZERO;
|
||||||
m_context.appendConditionalJumpTo(loopEnd);
|
m_context.appendConditionalJumpTo(loopEnd);
|
||||||
}
|
|
||||||
|
|
||||||
m_context.appendJumpTo(loopStart);
|
_whileStatement.body().accept(*this);
|
||||||
|
|
||||||
|
m_context.appendJumpTo(loopStart);
|
||||||
|
}
|
||||||
m_context << loopEnd;
|
m_context << loopEnd;
|
||||||
|
|
||||||
m_continueTags.pop_back();
|
m_continueTags.pop_back();
|
||||||
|
@ -485,11 +485,7 @@ void SMTChecker::compareOperation(BinaryOperation const& _op)
|
|||||||
solUnimplementedAssert(SSAVariable::isBool(_op.annotation().commonType->category()), "Operation not yet supported");
|
solUnimplementedAssert(SSAVariable::isBool(_op.annotation().commonType->category()), "Operation not yet supported");
|
||||||
value = make_shared<smt::Expression>(
|
value = make_shared<smt::Expression>(
|
||||||
op == Token::Equal ? (left == right) :
|
op == Token::Equal ? (left == right) :
|
||||||
op == Token::NotEqual ? (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)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// TODO: check that other values for op are not possible.
|
// TODO: check that other values for op are not possible.
|
||||||
|
@ -404,9 +404,7 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings()
|
|||||||
{
|
{
|
||||||
bool ignoreMissing = m_args.count(g_argIgnoreMissingFiles);
|
bool ignoreMissing = m_args.count(g_argIgnoreMissingFiles);
|
||||||
bool addStdin = false;
|
bool addStdin = false;
|
||||||
if (!m_args.count(g_argInputFile))
|
if (m_args.count(g_argInputFile))
|
||||||
addStdin = true;
|
|
||||||
else
|
|
||||||
for (string path: m_args[g_argInputFile].as<vector<string>>())
|
for (string path: m_args[g_argInputFile].as<vector<string>>())
|
||||||
{
|
{
|
||||||
auto eq = find(path.begin(), path.end(), '=');
|
auto eq = find(path.begin(), path.end(), '=');
|
||||||
@ -450,6 +448,11 @@ bool CommandLineInterface::readInputFilesAndConfigureRemappings()
|
|||||||
}
|
}
|
||||||
if (addStdin)
|
if (addStdin)
|
||||||
m_sourceCodes[g_stdinFileName] = dev::readStandardInput();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -139,25 +139,55 @@ rm -rf "$TMPDIR"
|
|||||||
echo "Done."
|
echo "Done."
|
||||||
|
|
||||||
printTask "Testing library checksum..."
|
printTask "Testing library checksum..."
|
||||||
echo '' | "$SOLC" --link --libraries a:0x90f20564390eAe531E810af625A22f51385Cd222
|
echo '' | "$SOLC" - --link --libraries a:0x90f20564390eAe531E810af625A22f51385Cd222 >/dev/null
|
||||||
! echo '' | "$SOLC" --link --libraries a:0x80f20564390eAe531E810af625A22f51385Cd222 2>/dev/null
|
! echo '' | "$SOLC" - --link --libraries a:0x80f20564390eAe531E810af625A22f51385Cd222 &>/dev/null
|
||||||
|
|
||||||
printTask "Testing long library names..."
|
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)
|
TMPDIR=$(mktemp -d)
|
||||||
(
|
(
|
||||||
set -e
|
set -e
|
||||||
# First time it works
|
# 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
|
# 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
|
# 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"
|
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 "<stdin>:C")
|
||||||
|
result=$?
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# The contract should be compiled
|
||||||
|
if [[ "$result" != 0 ]] ; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
printTask "Testing soljson via the fuzzer..."
|
printTask "Testing soljson via the fuzzer..."
|
||||||
TMPDIR=$(mktemp -d)
|
TMPDIR=$(mktemp -d)
|
||||||
(
|
(
|
||||||
|
@ -263,7 +263,7 @@ library RLP {
|
|||||||
var (rStartPos, len) = _decode(self);
|
var (rStartPos, len) = _decode(self);
|
||||||
if (len != 1)
|
if (len != 1)
|
||||||
throw;
|
throw;
|
||||||
uint temp;
|
uint8 temp;
|
||||||
assembly {
|
assembly {
|
||||||
temp := byte(0, mload(rStartPos))
|
temp := byte(0, mload(rStartPos))
|
||||||
}
|
}
|
||||||
|
@ -579,7 +579,7 @@ BOOST_AUTO_TEST_CASE(struct_simple)
|
|||||||
a = s.a;
|
a = s.a;
|
||||||
b = s.b;
|
b = s.b;
|
||||||
c = s.c;
|
c = s.c;
|
||||||
d = uint(s.d);
|
d = uint16(s.d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -388,35 +388,6 @@ BOOST_AUTO_TEST_CASE(bool_simple)
|
|||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
CHECK_SUCCESS_NO_WARNINGS(text);
|
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)
|
BOOST_AUTO_TEST_CASE(bool_int_mixed)
|
||||||
|
@ -483,6 +483,27 @@ BOOST_AUTO_TEST_CASE(do_while_loop)
|
|||||||
testContractAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5);
|
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)
|
BOOST_AUTO_TEST_CASE(nested_loops)
|
||||||
{
|
{
|
||||||
// tests that break and continue statements in nested loops jump to the correct place
|
// 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"(
|
char const* sourceCode = R"(
|
||||||
contract Test {
|
contract Test {
|
||||||
function bytesToUint(bytes4 s) returns (uint16 h) {
|
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"(
|
char const* sourceCode = R"(
|
||||||
contract Test {
|
contract Test {
|
||||||
function bytesToUint(bytes4 s) returns (uint64 h) {
|
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"(
|
char const* sourceCode = R"(
|
||||||
contract Test {
|
contract Test {
|
||||||
function uintToBytes(uint32 h) returns (bytes2 s) {
|
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"(
|
char const* sourceCode = R"(
|
||||||
contract Test {
|
contract Test {
|
||||||
function UintToBytes(uint16 h) returns (bytes8 s) {
|
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 {
|
function deposit(bytes32 _id, bool _manually) payable {
|
||||||
if (_manually) {
|
if (_manually) {
|
||||||
bytes32 s = 0x19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f;
|
bytes32 s = 0x19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f;
|
||||||
log3(bytes32(msg.value), s, bytes32(msg.sender), _id);
|
log3(bytes32(msg.value), s, bytes32(uint256(msg.sender)), _id);
|
||||||
} else {
|
} else {
|
||||||
Deposit(msg.sender, _id, msg.value);
|
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);
|
event E(string indexed r, uint[4] indexed t);
|
||||||
function deposit() {
|
function deposit() {
|
||||||
bytes(x).length = 90;
|
bytes(x).length = 90;
|
||||||
for (uint i = 0; i < 90; i++)
|
for (uint8 i = 0; i < 90; i++)
|
||||||
bytes(x)[i] = byte(i);
|
bytes(x)[i] = byte(i);
|
||||||
y[0] = 4;
|
y[0] = 4;
|
||||||
y[1] = 5;
|
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) {
|
function test() returns (bytes10 a, bytes10 b, bytes10 c, bytes10 d, bytes10 e) {
|
||||||
data1.length = 9;
|
data1.length = 9;
|
||||||
for (uint i = 0; i < data1.length; ++i)
|
for (uint i = 0; i < data1.length; ++i)
|
||||||
data1[i] = bytes8(i);
|
data1[i] = bytes8(uint64(i));
|
||||||
data2 = data1;
|
data2 = data1;
|
||||||
a = data2[1];
|
a = data2[1];
|
||||||
b = data2[2];
|
b = data2[2];
|
||||||
@ -4795,7 +4816,7 @@ BOOST_AUTO_TEST_CASE(array_copy_target_simple)
|
|||||||
bytes17[10] data2; // 1 per slot, no offset counter
|
bytes17[10] data2; // 1 per slot, no offset counter
|
||||||
function test() returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e) {
|
function test() returns (bytes17 a, bytes17 b, bytes17 c, bytes17 d, bytes17 e) {
|
||||||
for (uint i = 0; i < data1.length; ++i)
|
for (uint i = 0; i < data1.length; ++i)
|
||||||
data1[i] = bytes8(i);
|
data1[i] = bytes8(uint64(i));
|
||||||
data2[8] = data2[9] = 2;
|
data2[8] = data2[9] = 2;
|
||||||
data2 = data1;
|
data2 = data1;
|
||||||
a = data2[1];
|
a = data2[1];
|
||||||
@ -4827,14 +4848,14 @@ BOOST_AUTO_TEST_CASE(array_copy_target_leftover)
|
|||||||
uint i;
|
uint i;
|
||||||
for (i = 0; i < data2.length; ++i)
|
for (i = 0; i < data2.length; ++i)
|
||||||
data2[i] = 0xffff;
|
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)
|
for (i = 0; i < data1.length; ++i)
|
||||||
data1[i] = byte(uint8(1 + i));
|
data1[i] = byte(uint8(1 + i));
|
||||||
data2 = data1;
|
data2 = data1;
|
||||||
for (i = 0; i < 16; ++i)
|
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)
|
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[2] = 3;
|
||||||
data1[3] = 4;
|
data1[3] = 4;
|
||||||
for (uint i = 0; i < data2.length; ++i)
|
for (uint i = 0; i < data2.length; ++i)
|
||||||
data2[i] = bytes10(0xffff00 | (1 + i));
|
data2[i] = bytes10(uint80(0xffff00 | (1 + i)));
|
||||||
data2 = data1;
|
data2 = data1;
|
||||||
r1 = data2[3];
|
r1 = data2[3];
|
||||||
r2 = data2[4];
|
r2 = data2[4];
|
||||||
@ -5074,7 +5095,7 @@ BOOST_AUTO_TEST_CASE(byte_array_push_transition)
|
|||||||
contract c {
|
contract c {
|
||||||
bytes data;
|
bytes data;
|
||||||
function test() returns (uint) {
|
function test() returns (uint) {
|
||||||
for (uint i = 1; i < 40; i++)
|
for (uint8 i = 1; i < 40; i++)
|
||||||
{
|
{
|
||||||
data.push(byte(i));
|
data.push(byte(i));
|
||||||
if (data.length != i) return 0x1000 + i;
|
if (data.length != i) return 0x1000 + i;
|
||||||
@ -5120,11 +5141,11 @@ BOOST_AUTO_TEST_CASE(bytes_index_access)
|
|||||||
contract c {
|
contract c {
|
||||||
bytes data;
|
bytes data;
|
||||||
function direct(bytes arg, uint index) external returns (uint) {
|
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) {
|
function storageCopyRead(bytes arg, uint index) external returns (uint) {
|
||||||
data = arg;
|
data = arg;
|
||||||
return uint(data[index]);
|
return uint(uint8(data[index]));
|
||||||
}
|
}
|
||||||
function storageWrite() external returns (uint) {
|
function storageWrite() external returns (uint) {
|
||||||
data.length = 35;
|
data.length = 35;
|
||||||
@ -5135,7 +5156,7 @@ BOOST_AUTO_TEST_CASE(bytes_index_access)
|
|||||||
data[31] |= 8;
|
data[31] |= 8;
|
||||||
data[30] = 1;
|
data[30] = 1;
|
||||||
data[32] = 3;
|
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) {
|
function test1() external returns (bool) {
|
||||||
data.length = 100;
|
data.length = 100;
|
||||||
for (uint i = 0; i < data.length; i++)
|
for (uint i = 0; i < data.length; i++)
|
||||||
data[i] = byte(i);
|
data[i] = byte(uint8(i));
|
||||||
delete data[94];
|
delete data[94];
|
||||||
delete data[96];
|
delete data[96];
|
||||||
delete data[98];
|
delete data[98];
|
||||||
@ -7517,7 +7538,7 @@ BOOST_AUTO_TEST_CASE(short_strings)
|
|||||||
if (data1[0] != "1") return 10;
|
if (data1[0] != "1") return 10;
|
||||||
if (data1[4] != "4") return 11;
|
if (data1[4] != "4") return 11;
|
||||||
for (uint i = 0; i < data1.length; i ++)
|
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[4] != 4 * 3) return 12;
|
||||||
if (data1[67] != 67 * 3) return 13;
|
if (data1[67] != 67 * 3) return 13;
|
||||||
// change length: long -> short
|
// change length: long -> short
|
||||||
@ -8333,7 +8354,7 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_index_access)
|
|||||||
function g(bytes32 x) returns (uint) {
|
function g(bytes32 x) returns (uint) {
|
||||||
data = [x[0], x[1], x[2]];
|
data = [x[0], x[1], x[2]];
|
||||||
data[0] = "12345";
|
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) {
|
function test() returns (bytes) {
|
||||||
bytes memory x = new bytes(5);
|
bytes memory x = new bytes(5);
|
||||||
for (uint i = 0; i < x.length; ++i)
|
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") }
|
assembly { mstore(add(x, 32), "12345678901234567890123456789012") }
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
@ -8911,7 +8932,7 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types)
|
|||||||
function f(bytes2 a, uint16 x) returns (uint) {
|
function f(bytes2 a, uint16 x) returns (uint) {
|
||||||
if (a != "ab") return 1;
|
if (a != "ab") return 1;
|
||||||
if (x != 0x0102) return 2;
|
if (x != 0x0102) return 2;
|
||||||
if (bytes3(x) != 0x0102) return 3;
|
if (bytes3(uint24(x)) != 0x0102) return 3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3858,19 +3858,6 @@ BOOST_AUTO_TEST_CASE(conditional_with_all_types)
|
|||||||
CHECK_SUCCESS(text);
|
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)
|
BOOST_AUTO_TEST_CASE(uint7_and_uintM_as_identifier)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
|
@ -216,7 +216,7 @@ BOOST_AUTO_TEST_CASE(array_copy)
|
|||||||
data1[i] = msg.data[i];
|
data1[i] = msg.data[i];
|
||||||
data2 = data1;
|
data2 = data1;
|
||||||
l = data2.length;
|
l = data2.length;
|
||||||
y = uint(data2[x]);
|
y = uint(uint40(data2[x]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -23,13 +23,8 @@ contract C {
|
|||||||
}
|
}
|
||||||
function k() internal view returns (S storage c) {
|
function k() internal view returns (S storage c) {
|
||||||
do {
|
do {
|
||||||
if (s.f) {
|
c = s;
|
||||||
continue;
|
continue;
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
c = s;
|
|
||||||
}
|
|
||||||
} while(false);
|
} while(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,15 @@ contract C {
|
|||||||
do {
|
do {
|
||||||
if (s.f) {
|
if (s.f) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
c = s;
|
||||||
|
}
|
||||||
|
} while(false);
|
||||||
|
}
|
||||||
|
function i() internal view returns (S storage c) {
|
||||||
|
do {
|
||||||
|
if (s.f) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -28,8 +37,16 @@ contract C {
|
|||||||
}
|
}
|
||||||
} while(false);
|
} 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: (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: (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: (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.
|
||||||
|
53
test/libsolidity/syntaxTests/types/bool_ops.sol
Normal file
53
test/libsolidity/syntaxTests/types/bool_ops.sol
Normal file
@ -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
|
7
test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol
Normal file
7
test/libsolidity/syntaxTests/types/bytes1_to_uint256.sol
Normal file
@ -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".
|
7
test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol
Normal file
7
test/libsolidity/syntaxTests/types/bytes32_to_uint32.sol
Normal file
@ -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".
|
@ -1,7 +1,7 @@
|
|||||||
contract C {
|
contract C {
|
||||||
function f() public pure {
|
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".
|
||||||
|
@ -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)));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
contract C {
|
||||||
|
bytes20 x;
|
||||||
|
function f(bytes16 b) public view {
|
||||||
|
b[uint8(x[2])];
|
||||||
|
}
|
||||||
|
}
|
7
test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol
Normal file
7
test/libsolidity/syntaxTests/types/uint256_to_bytes1.sol
Normal file
@ -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".
|
7
test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol
Normal file
7
test/libsolidity/syntaxTests/types/uint32_to_bytes32.sol
Normal file
@ -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".
|
Loading…
Reference in New Issue
Block a user