Merge pull request #11567 from ethereum/convert-type-ice-on-bound-calldata-struct

Fix ICE when calling functions bound to calldata structs and arrays
This commit is contained in:
chriseth 2021-06-22 16:51:25 +02:00 committed by GitHub
commit 9cf6021d8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 130 additions and 6 deletions

View File

@ -7,6 +7,7 @@ Compiler Features:
Bugfixes:
* Code Generator: Fix internal compiler error when calling functions bound to calldata structs and arrays.
### 0.8.6 (2021-06-22)

View File

@ -1078,8 +1078,7 @@ void CompilerUtils::convertType(
}
case DataLocation::CallData:
solAssert(
targetType.isByteArray() &&
typeOnStack.isByteArray() &&
((targetType.isByteArray() && typeOnStack.isByteArray()) || _typeOnStack == _targetType) &&
typeOnStack.location() == DataLocation::CallData,
"Invalid conversion to calldata type."
);
@ -1130,9 +1129,6 @@ void CompilerUtils::convertType(
solAssert(targetTypeCategory == stackTypeCategory, "");
auto& targetType = dynamic_cast<StructType const&>(_targetType);
auto& typeOnStack = dynamic_cast<StructType const&>(_typeOnStack);
solAssert(
targetType.location() != DataLocation::CallData
, "");
switch (targetType.location())
{
case DataLocation::Storage:
@ -1208,7 +1204,8 @@ void CompilerUtils::convertType(
}
break;
case DataLocation::CallData:
solAssert(false, "Invalid type conversion target location CallData.");
solAssert(_typeOnStack == _targetType, "");
// nothing to do
break;
}
break;

View File

@ -0,0 +1,20 @@
pragma abicoder v2;
library L {
function reverse(bytes calldata _b) internal pure returns (bytes1, bytes1) {
return (_b[1], _b[0]);
}
}
contract C {
using L for bytes;
function test(uint, bytes calldata _b, uint) external pure returns (bytes1, bytes1) {
return _b.reverse();
}
}
// ====
// compileViaYul: also
// ----
// test(uint256,bytes,uint256): 7, 0x60, 4, 2, "ab" -> "b", "a"

View File

@ -0,0 +1,25 @@
pragma abicoder v2;
library L {
function reverse(uint[] calldata _a) internal pure returns (uint, uint) {
return (_a[1], _a[0]);
}
}
contract C {
using L for *;
function testArray(uint, uint[] calldata _a, uint) external pure returns (uint, uint) {
return _a.reverse();
}
function testSlice(uint, uint[] calldata _a, uint) external pure returns (uint, uint) {
return _a[:].reverse();
}
}
// ====
// compileViaYul: also
// ----
// testArray(uint256,uint256[],uint256): 7, 0x60, 4, 2, 66, 77 -> 77, 66
// testSlice(uint256,uint256[],uint256): 7, 0x60, 4, 2, 66, 77 -> 77, 66

View File

@ -0,0 +1,20 @@
pragma abicoder v2;
library L {
function reverse(uint[2] calldata _a) internal pure returns (uint, uint) {
return (_a[1], _a[0]);
}
}
contract C {
using L for uint[2];
function test(uint, uint[2] calldata _a, uint) external pure returns (uint, uint) {
return _a.reverse();
}
}
// ====
// compileViaYul: also
// ----
// test(uint256,uint256[2],uint256): 7, 66, 77, 4 -> 77, 66

View File

@ -0,0 +1,24 @@
pragma abicoder v2;
struct S {
uint x;
uint y;
}
library L {
function reverse(S calldata _s) internal pure returns (uint, uint) {
return (_s.y, _s.x);
}
}
contract C {
using L for S;
function test(uint, S calldata _s, uint) external pure returns (uint, uint) {
return _s.reverse();
}
}
// ====
// compileViaYul: also
// ----
// test(uint256,(uint256,uint256),uint256): 7, 66, 77, 4 -> 77, 66

View File

@ -0,0 +1,22 @@
pragma abicoder v2;
struct S {
uint x;
uint y;
}
library L {
function reverse(S calldata _s) internal pure returns (uint, uint) {
return (_s.y, _s.x);
}
}
contract C {
function test(uint, S calldata _s, uint) external pure returns (uint, uint) {
return L.reverse(_s);
}
}
// ====
// compileViaYul: also
// ----
// test(uint256,(uint256,uint256),uint256): 7, 66, 77, 4 -> 77, 66

View File

@ -0,0 +1,15 @@
struct S {
uint x;
}
library L {
function f(S calldata) internal pure {}
}
contract C {
using L for S;
function run(S calldata _s) external pure {
_s.f();
}
}