Anything outside storage is always a pointer.

This commit is contained in:
Daniel Kirchner 2020-03-13 12:50:14 +01:00 committed by chriseth
parent 148b87c977
commit fe659ceb41
9 changed files with 98 additions and 9 deletions

View File

@ -9,6 +9,8 @@ Compiler Features:
Bugfixes:
* Inline Assembly: Fix internal error when accessing incorrect constant variables.
* Inheritance: Allow public state variables to override functions with dynamic memory types in their return values.
* JSON AST: Always add pointer suffix for memory reference types.
### 0.6.4 (2020-03-10)

View File

@ -1487,11 +1487,19 @@ TypeResult ReferenceType::unaryOperatorResult(Token _operator) const
case DataLocation::Memory:
return TypeProvider::emptyTuple();
case DataLocation::Storage:
return m_isPointer ? nullptr : TypeProvider::emptyTuple();
return isPointer() ? nullptr : TypeProvider::emptyTuple();
}
return nullptr;
}
bool ReferenceType::isPointer() const
{
if (m_location == DataLocation::Storage)
return m_isPointer;
else
return true;
}
TypePointer ReferenceType::copyForLocationIfReference(Type const* _type) const
{
return TypeProvider::withLocationIfReference(m_location, _type);
@ -1502,7 +1510,7 @@ string ReferenceType::stringForReferencePart() const
switch (m_location)
{
case DataLocation::Storage:
return string("storage ") + (m_isPointer ? "pointer" : "ref");
return string("storage ") + (isPointer() ? "pointer" : "ref");
case DataLocation::CallData:
return "calldata";
case DataLocation::Memory:
@ -1868,7 +1876,8 @@ u256 ArrayType::memoryDataSize() const
std::unique_ptr<ReferenceType> ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const
{
auto copy = make_unique<ArrayType>(_location);
copy->m_isPointer = _isPointer;
if (_location == DataLocation::Storage)
copy->m_isPointer = _isPointer;
copy->m_arrayKind = m_arrayKind;
copy->m_baseType = copy->copyForLocationIfReference(m_baseType);
copy->m_hasDynamicLength = m_hasDynamicLength;
@ -2247,7 +2256,8 @@ TypeResult StructType::interfaceType(bool _inLibrary) const
std::unique_ptr<ReferenceType> StructType::copyForLocation(DataLocation _location, bool _isPointer) const
{
auto copy = make_unique<StructType>(m_struct, _location);
copy->m_isPointer = _isPointer;
if (_location == DataLocation::Storage)
copy->m_isPointer = _isPointer;
return copy;
}

View File

@ -701,7 +701,9 @@ public:
/// pointer type, state variables are bound references. Assignments to pointers or deleting
/// them will not modify storage (that will only change the pointer). Assignment from
/// non-storage objects to a variable of storage pointer type is not possible.
bool isPointer() const { return m_isPointer; }
/// For anything other than storage, this always returns true because assignments
/// never change the contents of the original value.
bool isPointer() const;
bool operator==(ReferenceType const& _other) const
{

View File

@ -54,7 +54,7 @@
"storageLocation": "memory",
"typeDescriptions":
{
"typeIdentifier": "t_array$_t_array$_t_uint256_$dyn_memory_$dyn_memory_ptr",
"typeIdentifier": "t_array$_t_array$_t_uint256_$dyn_memory_ptr_$dyn_memory_ptr",
"typeString": "uint256[][]"
},
"typeName":

View File

@ -14,9 +14,9 @@ contract C {
}
// ----
// creation:
// codeDepositCost: 1120000
// executionCost: 1160
// totalCost: 1121160
// codeDepositCost: 1094400
// executionCost: 1134
// totalCost: 1095534
// external:
// a(): 1130
// b(uint256): infinite

View File

@ -0,0 +1,24 @@
pragma experimental ABIEncoderV2;
struct S { uint256 v; string s; }
contract A
{
function test() external virtual returns (uint256 v, string memory s)
{
v = 42;
s = "test";
}
}
contract X is A
{
S public override test;
function set() public { test.v = 2; test.s = "statevar"; }
}
// ----
// test() -> 0, 64, 0
// set() ->
// test() -> 2, 0x40, 8, "statevar"

View File

@ -0,0 +1,26 @@
pragma experimental ABIEncoderV2;
struct S { uint256 v; string s; }
contract A
{
function test(uint256 x) external virtual returns (uint256 v, string memory s)
{
v = x;
s = "test";
}
}
contract X is A
{
mapping(uint256 => S) public override test;
function set() public { test[42].v = 2; test[42].s = "statevar"; }
}
// ----
// test(uint256): 0 -> 0, 64, 0
// test(uint256): 42 -> 0, 64, 0
// set() ->
// test(uint256): 0 -> 0, 64, 0
// test(uint256): 42 -> 2, 0x40, 8, "statevar"

View File

@ -0,0 +1,12 @@
pragma experimental ABIEncoderV2;
abstract contract C {
struct S {
uint256 x;
string y;
}
function f(address x) external virtual returns (uint256, string memory);
}
contract D is C {
mapping(address => S) public override f;
}

View File

@ -0,0 +1,13 @@
pragma experimental ABIEncoderV2;
abstract contract C {
struct S {
uint256 x;
string y;
}
function f() external virtual returns (uint256, string memory);
}
contract D is C {
S public override f;
}