Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth
2020-06-10 11:30:50 +02:00
60 changed files with 889 additions and 391 deletions
@@ -31,14 +31,14 @@
{
"id": 4,
"nodeType": "Block",
"src": "42:48:1",
"src": "42:58:1",
"statements":
[
{
"AST":
{
"nodeType": "YulBlock",
"src": "61:23:1",
"src": "61:33:1",
"statements":
[
{
@@ -48,11 +48,29 @@
"body":
{
"nodeType": "YulBlock",
"src": "80:2:1",
"src": "79:2:1",
"statements": []
},
"nodeType": "YulCase",
"src": "72:10:1",
"src": "72:9:1",
"value":
{
"kind": "number",
"nodeType": "YulLiteral",
"src": "77:1:1",
"type": "",
"value": "0"
}
},
{
"body":
{
"nodeType": "YulBlock",
"src": "90:2:1",
"statements": []
},
"nodeType": "YulCase",
"src": "82:10:1",
"value": "default"
}
],
@@ -65,7 +83,7 @@
"value": "0"
},
"nodeType": "YulSwitch",
"src": "63:19:1"
"src": "63:29:1"
}
]
},
@@ -73,7 +91,7 @@
"externalReferences": [],
"id": 3,
"nodeType": "InlineAssembly",
"src": "52:32:1"
"src": "52:42:1"
}
]
},
@@ -99,15 +117,15 @@
"src": "42:0:1"
},
"scope": 6,
"src": "17:73:1",
"src": "17:83:1",
"stateMutability": "view",
"virtual": false,
"visibility": "public"
}
],
"scope": 7,
"src": "0:92:1"
"src": "0:102:1"
}
],
"src": "0:93:1"
"src": "0:103:1"
}
@@ -1,6 +1,6 @@
contract C {
function g() view public {
assembly { switch 0 default {} }
assembly { switch 0 case 0 {} default {} }
}
}
@@ -91,30 +91,30 @@
[
null
],
"operations": "{\n switch 0\n default { }\n}"
"operations": "{\n switch 0\n case 0 { }\n default { }\n}"
},
"children": [],
"id": 3,
"name": "InlineAssembly",
"src": "52:32:1"
"src": "52:42:1"
}
],
"id": 4,
"name": "Block",
"src": "42:48:1"
"src": "42:58:1"
}
],
"id": 5,
"name": "FunctionDefinition",
"src": "17:73:1"
"src": "17:83:1"
}
],
"id": 6,
"name": "ContractDefinition",
"src": "0:92:1"
"src": "0:102:1"
}
],
"id": 7,
"name": "SourceUnit",
"src": "0:93:1"
"src": "0:103:1"
}
+11 -3
View File
@@ -314,9 +314,17 @@ BOOST_AUTO_TEST_CASE(switch_duplicate_case)
BOOST_AUTO_TEST_CASE(switch_invalid_expression)
{
CHECK_PARSE_ERROR("{ switch {} default {} }", ParserError, "Literal or identifier expected.");
CHECK_PARSE_ERROR("{ switch mload default {} }", ParserError, "Expected '(' but got reserved keyword 'default'");
CHECK_PARSE_ERROR("{ switch mstore(1, 1) default {} }", TypeError, "Expected expression to evaluate to one value, but got 0 values instead.");
CHECK_PARSE_ERROR("{ switch {} case 1 {} default {} }", ParserError, "Literal or identifier expected.");
CHECK_PARSE_ERROR(
"{ switch mload case 1 {} default {} }",
ParserError,
"Expected '(' but got reserved keyword 'case'"
);
CHECK_PARSE_ERROR(
"{ switch mstore(1, 1) case 1 {} default {} }",
TypeError,
"Expected expression to evaluate to one value, but got 0 values instead."
);
}
BOOST_AUTO_TEST_CASE(switch_default_before_case)
@@ -0,0 +1,20 @@
contract C {
function to_little_endian_64(uint64 value) public pure returns (bytes memory ret) {
ret = new bytes(8);
bytes8 bytesValue = bytes8(value);
// Byteswapping during copying to bytes.
ret[0] = bytesValue[7];
ret[1] = bytesValue[6];
ret[2] = bytesValue[5];
ret[3] = bytesValue[4];
ret[4] = bytesValue[3];
ret[5] = bytesValue[2];
ret[6] = bytesValue[1];
ret[7] = bytesValue[0];
}
}
// ====
// compileViaYul: also
// ----
// to_little_endian_64(uint64): 0 -> 0x20, 8, 0x00
// to_little_endian_64(uint64): 0x0102030405060708 -> 0x20, 8, 0x0807060504030201000000000000000000000000000000000000000000000000
@@ -0,0 +1,29 @@
contract C {
struct Y {
uint a;
uint b;
}
mapping(uint256 => Y)[] public m;
mapping(uint256 => Y)[3] public n;
constructor() public {
m.push();
m.push();
m[1][0].a = 1;
m[1][0].b = 2;
m[1][1].a = 3;
m[1][1].b = 4;
n[1][0].a = 7;
n[1][0].b = 8;
n[1][1].a = 9;
n[1][1].b = 10;
}
}
// ----
// m(uint256,uint256): 0, 0 -> 0x00, 0x00
// m(uint256,uint256): 1, 0 -> 1, 2
// m(uint256,uint256): 1, 1 -> 3, 4
// m(uint256,uint256): 1, 2 -> 0x00, 0x00
// n(uint256,uint256): 0, 0 -> 0x00, 0x00
// n(uint256,uint256): 1, 0 -> 7, 8
// n(uint256,uint256): 1, 1 -> 9, 0x0a
// n(uint256,uint256): 1, 2 -> 0x00, 0x00
@@ -0,0 +1,27 @@
contract C {
struct Y {
uint a;
uint b;
}
mapping(uint256 => Y[]) public m;
mapping(uint256 => Y[3]) public n;
constructor() public {
m[1].push().a = 1;
m[1][0].b = 2;
m[1].push().a = 3;
m[1][1].b = 4;
n[1][0].a = 7;
n[1][0].b = 8;
n[1][1].a = 9;
n[1][1].b = 10;
}
}
// ----
// m(uint256,uint256): 0, 0 -> FAILURE
// m(uint256,uint256): 1, 0 -> 1, 2
// m(uint256,uint256): 1, 1 -> 3, 4
// m(uint256,uint256): 1, 2 -> FAILURE
// n(uint256,uint256): 0, 0 -> 0x00, 0x00
// n(uint256,uint256): 1, 0 -> 7, 8
// n(uint256,uint256): 1, 1 -> 9, 0x0a
// n(uint256,uint256): 1, 2 -> 0x00, 0x00
@@ -0,0 +1,18 @@
contract C {
mapping(string => uint8[3]) public x;
constructor() public {
x["abc"][0] = 1;
x["abc"][2] = 3;
x["abc"][1] = 2;
x["def"][1] = 9;
}
}
// ====
// compileViaYul: also
// ----
// x(string,uint256): 0x40, 0, 3, "abc" -> 1
// x(string,uint256): 0x40, 1, 3, "abc" -> 2
// x(string,uint256): 0x40, 2, 3, "abc" -> 3
// x(string,uint256): 0x40, 0, 3, "def" -> 0x00
// x(string,uint256): 0x40, 1, 3, "def" -> 9
// x(string,uint256): 0x40, 2, 3, "def" -> 0x00
@@ -0,0 +1,18 @@
contract C {
struct S {
uint a;
bytes b;
mapping(uint => uint) c;
uint[] d;
}
uint shifter;
S public s;
constructor() public {
s.a = 7;
s.b = "abc";
s.c[0] = 9;
s.d.push(10);
}
}
// ----
// s() -> 7, 0x40, 3, 0x6162630000000000000000000000000000000000000000000000000000000000
@@ -0,0 +1,23 @@
pragma experimental SMTChecker;
contract C {
uint[][] a;
uint[][][] c;
uint[] d;
function f() public {
a.push();
uint[] storage b = a[0];
c[0][0][0] = 12;
d[5] = 7;
b.push(8);
assert(a[0].length == 0);
// Safe but knowledge about `c` is erased because `b` could be pointing to `c[x][y]`.
assert(c[0][0][0] == 12);
// Safe but knowledge about `d` is erased because `b` could be pointing to `d`.
assert(d[5] == 7);
}
}
// ----
// Warning: (193-217): Assertion violation happens here
// Warning: (309-333): Assertion violation happens here
// Warning: (419-436): Assertion violation happens here
@@ -0,0 +1,12 @@
pragma experimental SMTChecker;
contract test {
function f() internal pure {
ufixed a = uint64(1) + ufixed(2);
}
}
// ----
// Warning: (80-88): Unused local variable.
// Warning: (91-100): Type conversion is not yet fully supported and might yield false positives.
// Warning: (103-112): Type conversion is not yet fully supported and might yield false positives.
// Warning: (91-112): Underflow (resulting value less than 0) happens here
// Warning: (91-112): Overflow (resulting value larger than 2**256 - 1) happens here
@@ -0,0 +1,8 @@
pragma experimental SMTChecker;
contract C {
fixed[] b;
function f() internal { b[0] += 1; }
}
// ----
// Warning: (84-93): Underflow (resulting value less than 0) happens here
// Warning: (84-93): Overflow (resulting value larger than 2**256 - 1) happens here
@@ -0,0 +1,6 @@
pragma experimental SMTChecker;
contract C {
function f3() public pure {
((, ), ) = ((7, 8), 9);
}
}
@@ -1,15 +1,7 @@
contract C {
struct S { bool f; }
S s;
function f(uint256 a) internal pure {
S storage c;
assembly {
switch a
default { c_slot := s_slot }
}
c;
}
function g(bool flag) internal pure {
function f(bool flag) internal pure {
S storage c;
assembly {
switch flag
@@ -18,7 +10,7 @@ contract C {
}
c;
}
function h(uint256 a) internal pure {
function g(uint256 a) internal pure {
S storage c;
assembly {
switch a
@@ -1,20 +1,14 @@
contract C {
struct S { bool f; }
S s;
function f(uint256 a) internal pure returns (S storage c) {
assembly {
switch a
default { c_slot := s_slot }
}
}
function g(bool flag) internal pure returns (S storage c) {
function f(bool flag) internal pure returns (S storage c) {
assembly {
switch flag
case 0 { c_slot := s_slot }
default { c_slot := s_slot }
}
}
function h(uint256 a) internal pure returns (S storage c) {
function g(uint256 a) internal pure returns (S storage c) {
assembly {
switch a
case 0 { revert(0, 0) }
@@ -0,0 +1,12 @@
contract C {
struct S { bool f; }
S s;
function f(uint256 a) internal pure returns (S storage c) {
assembly {
switch a
default { c_slot := s_slot }
}
}
}
// ----
// Warning: (142-195): "switch" statement with only a default case.