Merge pull request #8942 from ethereum/calldataVariables

Calldata variables.
This commit is contained in:
chriseth 2020-05-26 11:34:40 +02:00 committed by GitHub
commit e6b399c86e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 295 additions and 86 deletions

View File

@ -1,6 +1,7 @@
### 0.6.9 (unreleased)
Language Features:
* Permit calldata location for all variables.
Compiler Features:

View File

@ -13,8 +13,7 @@ arrays and mappings. If you use a reference type, you always have to explicitly
provide the data area where the type is stored: ``memory`` (whose lifetime is limited
to an external function call), ``storage`` (the location where the state variables
are stored, where the lifetime is limited to the lifetime of a contract)
or ``calldata`` (special data location that contains the function arguments,
only available for external function call parameters).
or ``calldata`` (special data location that contains the function arguments).
An assignment or type conversion that changes the data location will always incur an automatic copy operation,
while assignments inside the same data location only copy in some cases for storage types.
@ -26,9 +25,9 @@ Data location
Every reference type has an additional
annotation, the "data location", about where it is stored. There are three data locations:
``memory``, ``storage`` and ``calldata``. Calldata is only valid for parameters of external contract
functions and is required for this type of parameter. Calldata is a non-modifiable,
``memory``, ``storage`` and ``calldata``. Calldata is a non-modifiable,
non-persistent area where function arguments are stored, and behaves mostly like memory.
It is required for parameters of external functions but can also be used for other variables.
.. note::
@ -36,6 +35,12 @@ non-persistent area where function arguments are stored, and behaves mostly like
depending on the kind of variable, function type, etc., but all complex types must now give an explicit
data location.
.. note::
If you can, try to use ``calldata`` as data location because it will avoid copies and
also makes sure that the data cannot be modified. Arrays and structs with ``calldata``
data location can also be returned from functions, but it is not possible to
allocate such types.
.. _data-location-assignment:
Data location and assignment behaviour

View File

@ -94,7 +94,10 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
case VariableOccurrence::Kind::Return:
if (unassignedVariables.count(&variableOccurrence.declaration()))
{
if (variableOccurrence.declaration().type()->dataStoredIn(DataLocation::Storage))
if (
variableOccurrence.declaration().type()->dataStoredIn(DataLocation::Storage) ||
variableOccurrence.declaration().type()->dataStoredIn(DataLocation::CallData)
)
// Merely store the unassigned access. We do not generate an error right away, since this
// path might still always revert. It is only an error if this is propagated to the exit
// node of the function (i.e. there is a path with an uninitialized access).
@ -135,13 +138,16 @@ void ControlFlowAnalyzer::checkUninitializedAccess(CFGNode const* _entry, CFGNod
if (variableOccurrence->occurrence())
ssl.append("The variable was declared here.", variableOccurrence->declaration().location());
bool isStorage = variableOccurrence->declaration().type()->dataStoredIn(DataLocation::Storage);
m_errorReporter.typeError(
3464_error,
variableOccurrence->occurrence() ?
*variableOccurrence->occurrence() :
variableOccurrence->declaration().location(),
ssl,
string("This variable is of storage pointer type and can be ") +
"This variable is of " +
string(isStorage ? "storage" : "calldata") +
" pointer type and can be " +
(variableOccurrence->kind() == VariableOccurrence::Kind::Return ? "returned" : "accessed") +
" without prior assignment, which would lead to undefined behaviour."
);

View File

@ -338,7 +338,13 @@ TypePointer FunctionDefinition::type() const
TypePointer FunctionDefinition::typeViaContractName() const
{
if (annotation().contract->isLibrary())
{
if (isPublic())
return FunctionType(*this).asCallableFunction(true);
else
return TypeProvider::function(*this, FunctionType::Kind::Internal);
}
else
return TypeProvider::function(*this, FunctionType::Kind::Declaration);
}
@ -616,18 +622,14 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c
if (!hasReferenceOrMappingType() || isStateVariable() || isEventParameter())
return set<Location>{ Location::Unspecified };
else if (isExternalCallableParameter())
{
set<Location> locations{ Location::CallData };
if (isLibraryFunctionParameter())
locations.insert(Location::Storage);
return locations;
}
else if (isCallableOrCatchParameter())
{
set<Location> locations{ Location::Memory };
if (isInternalCallableParameter() || isLibraryFunctionParameter() || isTryCatchParameter())
locations.insert(Location::Storage);
if (!isTryCatchParameter())
locations.insert(Location::CallData);
return locations;
}
else if (isLocalVariable())
@ -642,8 +644,7 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c
case Type::Category::Mapping:
return set<Location>{ Location::Storage };
default:
// TODO: add Location::Calldata once implemented for local variables.
return set<Location>{ Location::Memory, Location::Storage };
return set<Location>{ Location::Memory, Location::Storage, Location::CallData };
}
};
return dataLocations(typeName()->annotation().type, dataLocations);

View File

@ -1218,6 +1218,15 @@ void CompilerUtils::pushZeroValue(Type const& _type)
m_context << u256(0);
return;
}
if (referenceType->location() == DataLocation::CallData)
{
solAssert(referenceType->sizeOnStack() == 1 || referenceType->sizeOnStack() == 2, "");
m_context << Instruction::CALLDATASIZE;
if (referenceType->sizeOnStack() == 2)
m_context << 0;
return;
}
solAssert(referenceType->location() == DataLocation::Memory, "");
if (auto arrayType = dynamic_cast<ArrayType const*>(&_type))
if (arrayType->isDynamicallySized())

View File

@ -2240,6 +2240,27 @@ string YulUtilFunctions::zeroValueFunction(Type const& _type, bool _splitFunctio
("functionName", functionName)
.render();
if (_type.dataStoredIn(DataLocation::CallData))
{
solAssert(
_type.category() == Type::Category::Struct ||
_type.category() == Type::Category::Array,
"");
Whiskers templ(R"(
function <functionName>() -> offset<?hasLength>, length</hasLength> {
offset := calldatasize()
<?hasLength> length := 0 </hasLength>
}
)");
templ("functionName", functionName);
templ("hasLength",
_type.category() == Type::Category::Array &&
dynamic_cast<ArrayType const&>(_type).isDynamicallySized()
);
return templ.render();
}
Whiskers templ(R"(
function <functionName>() -> ret {
ret := <zeroValue>
@ -2624,4 +2645,3 @@ string YulUtilFunctions::copyConstructorArgumentsToMemoryFunction(
.render();
});
}

View File

@ -0,0 +1,12 @@
contract C {
function f(bytes calldata b, uint i) internal pure returns (byte) {
return b[i];
}
function f(uint, bytes calldata b, uint) external pure returns (byte) {
return f(b, 2);
}
}
// ====
// compileViaYul: also
// ----
// f(uint256,bytes,uint256): 7, 0x60, 7, 4, "abcd" -> "c"

View File

@ -0,0 +1,17 @@
contract C {
function(bytes calldata) returns (byte) x;
constructor() public { x = f; }
function f(bytes calldata b) internal pure returns (byte) {
return b[2];
}
function h(bytes calldata b) external returns (byte) {
return x(b);
}
function g() external returns (byte) {
bytes memory a = new bytes(34);
a[2] = byte(uint8(7));
return this.h(a);
}
}
// ----
// g() -> 0x0700000000000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,22 @@
library L {
function f(uint, bytes calldata _x, uint) internal returns (byte) {
return _x[2];
}
}
contract C {
function f(bytes calldata a)
external
returns (byte)
{
return L.f(3, a, 9);
}
function g() public returns (byte) {
bytes memory x = new bytes(4);
x[2] = 0x08;
return this.f(x);
}
}
// ====
// compileViaYul: also
// ----
// g() -> 0x0800000000000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,23 @@
pragma experimental ABIEncoderV2;
contract C {
function g(uint[][2] calldata s) internal pure returns (uint, uint[] calldata) {
return (s[0][1], s[1]);
}
function f(uint, uint[][2] calldata s, uint) external pure returns (uint, uint) {
(uint x, uint[] calldata y) = g(s);
return (x, y[0]);
}
function g() public returns (uint, uint) {
uint[][2] memory x;
x[0] = new uint[](2);
x[1] = new uint[](2);
x[0][1] = 7;
x[1][0] = 8;
return this.f(4, x, 5);
}
}
// ====
// compileViaYul: also
// ----
// g() -> 7, 8

View File

@ -0,0 +1,19 @@
contract C {
function g(uint[3][2] calldata s) internal pure returns (uint, uint[3] calldata) {
return (s[0][1], s[1]);
}
function f(uint, uint[3][2] calldata s, uint) external pure returns (uint, uint) {
(uint x, uint[3] calldata y) = g(s);
return (x, y[0]);
}
function g() public returns (uint, uint) {
uint[3][2] memory x;
x[0][1] = 7;
x[1][0] = 8;
return this.f(4, x, 5);
}
}
// ====
// compileViaYul: also
// ----
// g() -> 7, 8

View File

@ -0,0 +1,21 @@
contract C {
function f(bytes memory _a, bytes calldata _b, bytes memory _c)
public
returns (uint, byte, byte, byte)
{
return (_a.length + _b.length + _c.length, _a[1], _b[1], _c[1]);
}
function g() public returns (uint, byte, byte, byte) {
bytes memory x = new bytes(3);
bytes memory y = new bytes(4);
bytes memory z = new bytes(7);
x[1] = 0x08;
y[1] = 0x09;
z[1] = 0x0a;
return this.f(x, y, z);
}
}
// ====
// compileViaYul: also
// ----
// g() -> 0x0e, 0x0800000000000000000000000000000000000000000000000000000000000000, 0x0900000000000000000000000000000000000000000000000000000000000000, 0x0a00000000000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,17 @@
pragma experimental ABIEncoderV2;
struct S {
uint x;
uint y;
}
contract C {
function f(S calldata s) internal pure returns (uint, uint) {
return (s.x, s.y);
}
function f(uint, S calldata s, uint) external pure returns (uint, uint) {
return f(s);
}
}
// ----
// f(uint256,(uint256,uint256),uint256): 7, 1, 2, 4 -> 1, 2

View File

@ -6,4 +6,4 @@ contract C {
// ----
// DeclarationError: (28-45): The "constant" keyword can only be used for state variables.
// TypeError: (69-72): Invalid array length, expected integer literal or constant expression.
// TypeError: (64-75): Data location must be "storage" or "memory" for variable, but none was given.
// TypeError: (64-75): Data location must be "storage", "memory" or "calldata" for variable, but none was given.

View File

@ -0,0 +1,10 @@
contract C {
function f(uint[] calldata _c) public pure {
uint[] calldata c;
if (_c[2] > 10)
c = _c;
c[2];
}
}
// ----
// TypeError: (141-142): This variable is of calldata pointer type and can be accessed without prior assignment, which would lead to undefined behaviour.

View File

@ -0,0 +1,11 @@
contract C {
function f(uint[] calldata _c) public pure {
uint[] calldata c;
if (_c[2] > 10)
c = _c;
else
c = _c;
c[2];
}
}
// ----

View File

@ -0,0 +1,16 @@
contract C {
function g() internal pure returns (bytes calldata) {
return msg.data;
}
function h(uint[] calldata _c) internal pure {
uint[] calldata c;
c = _c;
c[2];
}
function i(uint[] calldata _c) internal pure {
uint[] calldata c;
(c) = _c;
c[2];
}
}
// ----

View File

@ -5,5 +5,4 @@ library L {
}
// ----
// TypeError: (66-81): Data location must be "memory" for parameter in function, but "calldata" was given.
// TypeError: (159-173): Data location must be "memory" for parameter in function, but "storage" was given.
// TypeError: (159-173): Data location must be "memory" or "calldata" for parameter in function, but "storage" was given.

View File

@ -2,4 +2,4 @@ contract C {
function i() external pure returns(uint[]) {}
}
// ----
// TypeError: (52-58): Data location must be "memory" for return parameter in function, but none was given.
// TypeError: (52-58): Data location must be "memory" or "calldata" for return parameter in function, but none was given.

View File

@ -2,4 +2,5 @@ contract test {
function f(bytes memory) external;
}
// ----
// TypeError: (31-43): Data location must be "calldata" for parameter in external function, but "memory" was given.
// TypeError: (0-56): Contract "test" should be marked as abstract.
// TypeError: (20-54): Functions without implementation must be marked virtual.

View File

@ -2,4 +2,4 @@ contract test {
function f(bytes storage) external;
}
// ----
// TypeError: (31-44): Data location must be "calldata" for parameter in external function, but "storage" was given.
// TypeError: (31-44): Data location must be "memory" or "calldata" for parameter in external function, but "storage" was given.

View File

@ -2,4 +2,5 @@ contract test {
function f(bytes calldata) internal;
}
// ----
// TypeError: (31-45): Data location must be "storage" or "memory" for parameter in function, but "calldata" was given.
// TypeError: (0-58): Contract "test" should be marked as abstract.
// TypeError: (20-56): Functions without implementation must be marked virtual.

View File

@ -2,4 +2,4 @@ contract C {
function g(uint[]) internal pure {}
}
// ----
// TypeError: (28-34): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (28-34): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.

View File

@ -2,4 +2,4 @@ contract C {
function g() internal pure returns(uint[]) {}
}
// ----
// TypeError: (52-58): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (52-58): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.

View File

@ -6,7 +6,7 @@ library L {
function j(mapping(uint => uint)) external pure {}
}
// ----
// TypeError: (52-59): Data location must be "storage" or "calldata" for parameter in external function, but none was given.
// TypeError: (93-99): Data location must be "storage" or "calldata" for parameter in external function, but none was given.
// TypeError: (133-134): Data location must be "storage" or "calldata" for parameter in external function, but none was given.
// TypeError: (168-189): Data location must be "storage" or "calldata" for parameter in external function, but none was given.
// TypeError: (52-59): Data location must be "storage", "memory" or "calldata" for parameter in external function, but none was given.
// TypeError: (93-99): Data location must be "storage", "memory" or "calldata" for parameter in external function, but none was given.
// TypeError: (133-134): Data location must be "storage", "memory" or "calldata" for parameter in external function, but none was given.
// TypeError: (168-189): Data location must be "storage", "memory" or "calldata" for parameter in external function, but none was given.

View File

@ -6,7 +6,7 @@ library L {
function j() external pure returns (mapping(uint => uint)) {}
}
// ----
// TypeError: (77-84): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (129-135): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (180-181): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (226-247): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (77-84): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (129-135): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (180-181): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (226-247): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.

View File

@ -10,11 +10,11 @@ library L {
function jp(mapping(uint => uint)) internal pure {}
}
// ----
// TypeError: (77-84): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (129-135): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (180-181): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (226-247): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (268-275): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (310-316): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (351-352): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (387-408): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (77-84): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (129-135): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (180-181): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (226-247): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (268-275): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (310-316): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (351-352): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (387-408): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.

View File

@ -10,11 +10,11 @@ library L {
function jp(mapping(uint => uint)) private pure {}
}
// ----
// TypeError: (76-83): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (127-133): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (177-178): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (222-243): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (264-271): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (305-311): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (345-346): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (380-401): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (76-83): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (127-133): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (177-178): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (222-243): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (264-271): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (305-311): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (345-346): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (380-401): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.

View File

@ -9,11 +9,11 @@ library L {
function ip(S) private pure {}
function jp(mapping(uint => uint)) private pure {}}
// ----
// TypeError: (76-83): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (127-133): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (177-178): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (222-243): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (264-271): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (305-311): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (345-346): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (380-401): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (76-83): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (127-133): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (177-178): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (222-243): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.
// TypeError: (264-271): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (305-311): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (345-346): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.
// TypeError: (380-401): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.

View File

@ -2,4 +2,3 @@ library test {
function f(bytes memory) external {}
}
// ----
// TypeError: (30-42): Data location must be "storage" or "calldata" for parameter in external function, but "memory" was given.

View File

@ -2,4 +2,3 @@ library test {
function f(bytes calldata) internal pure {}
}
// ----
// TypeError: (30-44): Data location must be "storage" or "memory" for parameter in function, but "calldata" was given.

View File

@ -2,4 +2,4 @@ contract C {
function f(uint[]) private pure {}
}
// ----
// TypeError: (28-34): Data location must be "storage" or "memory" for parameter in function, but none was given.
// TypeError: (28-34): Data location must be "storage", "memory" or "calldata" for parameter in function, but none was given.

View File

@ -2,4 +2,4 @@ contract C {
function f() private pure returns(uint[]) {}
}
// ----
// TypeError: (51-57): Data location must be "storage" or "memory" for return parameter in function, but none was given.
// TypeError: (51-57): Data location must be "storage", "memory" or "calldata" for return parameter in function, but none was given.

View File

@ -2,4 +2,5 @@ contract test {
function f(bytes calldata) public;
}
// ----
// TypeError: (31-45): Data location must be "memory" for parameter in function, but "calldata" was given.
// TypeError: (0-56): Contract "test" should be marked as abstract.
// TypeError: (20-54): Functions without implementation must be marked virtual.

View File

@ -2,4 +2,4 @@ contract test {
function f(bytes storage) public;
}
// ----
// TypeError: (31-44): Data location must be "memory" for parameter in function, but "storage" was given.
// TypeError: (31-44): Data location must be "memory" or "calldata" for parameter in function, but "storage" was given.

View File

@ -2,4 +2,4 @@ contract C {
function h(uint[]) public pure {}
}
// ----
// TypeError: (28-34): Data location must be "memory" for parameter in function, but none was given.
// TypeError: (28-34): Data location must be "memory" or "calldata" for parameter in function, but none was given.

View File

@ -2,4 +2,4 @@ contract C {
function h() public pure returns(uint[]) {}
}
// ----
// TypeError: (50-56): Data location must be "memory" for return parameter in function, but none was given.
// TypeError: (50-56): Data location must be "memory" or "calldata" for return parameter in function, but none was given.

View File

@ -3,4 +3,4 @@ contract c {
}
// ----
// TypeError: (51-52): Invalid array length, expected integer literal or constant expression.
// TypeError: (45-55): Data location must be "storage" or "memory" for variable, but none was given.
// TypeError: (45-55): Data location must be "storage", "memory" or "calldata" for variable, but none was given.

View File

@ -3,4 +3,4 @@ contract c {
}
// ----
// TypeError: (51-53): Array with negative length specified.
// TypeError: (45-56): Data location must be "storage" or "memory" for variable, but none was given.
// TypeError: (45-56): Data location must be "storage", "memory" or "calldata" for variable, but none was given.

View File

@ -2,4 +2,3 @@ contract C {
function f(uint[] memory a) external {}
}
// ----
// TypeError: (28-43): Data location must be "calldata" for parameter in external function, but "memory" was given.

View File

@ -2,4 +2,4 @@ contract C {
function f(uint[] storage a) external {}
}
// ----
// TypeError: (28-44): Data location must be "calldata" for parameter in external function, but "storage" was given.
// TypeError: (28-44): Data location must be "memory" or "calldata" for parameter in external function, but "storage" was given.

View File

@ -5,4 +5,4 @@ contract test {
}
// ----
// TypeError: (55-58): Array with fractional length specified.
// TypeError: (50-61): Data location must be "storage" or "memory" for variable, but none was given.
// TypeError: (50-61): Data location must be "storage", "memory" or "calldata" for variable, but none was given.

View File

@ -5,4 +5,4 @@ contract test {
}
// ----
// TypeError: (55-65): Invalid array length, expected integer literal or constant expression.
// TypeError: (50-68): Data location must be "storage" or "memory" for variable, but none was given.
// TypeError: (50-68): Data location must be "storage", "memory" or "calldata" for variable, but none was given.

View File

@ -5,4 +5,4 @@ contract test {
}
// ----
// TypeError: (55-66): Invalid array length, expected integer literal or constant expression.
// TypeError: (50-69): Data location must be "storage" or "memory" for variable, but none was given.
// TypeError: (50-69): Data location must be "storage", "memory" or "calldata" for variable, but none was given.

View File

@ -9,5 +9,5 @@ contract C {
}
}
// ----
// TypeError: (104-107): Data location must be "storage" or "memory" for variable, but none was given.
// TypeError: (123-131): Data location must be "storage" or "memory" for variable, but none was given.
// TypeError: (104-107): Data location must be "storage", "memory" or "calldata" for variable, but none was given.
// TypeError: (123-131): Data location must be "storage", "memory" or "calldata" for variable, but none was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (28-57): Data location must be "calldata" for parameter in external function, but "storage" was given.
// TypeError: (28-57): Data location must be "memory" or "calldata" for parameter in external function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (28-57): Data location must be "memory" for parameter in function, but "storage" was given.
// TypeError: (28-57): Data location must be "memory" or "calldata" for parameter in function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (28-59): Data location must be "calldata" for parameter in external function, but "storage" was given.
// TypeError: (28-59): Data location must be "memory" or "calldata" for parameter in external function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (28-59): Data location must be "memory" for parameter in function, but "storage" was given.
// TypeError: (28-59): Data location must be "memory" or "calldata" for parameter in function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (37-64): Data location must be "memory" for parameter in function, but "storage" was given.
// TypeError: (37-64): Data location must be "memory" or "calldata" for parameter in function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (57-84): Data location must be "memory" for return parameter in function, but "storage" was given.
// TypeError: (57-84): Data location must be "memory" or "calldata" for return parameter in function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (53-84): Data location must be "memory" for return parameter in function, but "storage" was given.
// TypeError: (53-84): Data location must be "memory" or "calldata" for return parameter in function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (51-82): Data location must be "memory" for return parameter in function, but "storage" was given.
// TypeError: (51-82): Data location must be "memory" or "calldata" for return parameter in function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (53-82): Data location must be "memory" for return parameter in function, but "storage" was given.
// TypeError: (53-82): Data location must be "memory" or "calldata" for return parameter in function, but "storage" was given.

View File

@ -3,4 +3,4 @@ contract C {
}
}
// ----
// TypeError: (51-80): Data location must be "memory" for return parameter in function, but "storage" was given.
// TypeError: (51-80): Data location must be "memory" or "calldata" for return parameter in function, but "storage" was given.