mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Anything outside storage is always a pointer.
This commit is contained in:
parent
148b87c977
commit
fe659ceb41
@ -9,6 +9,8 @@ Compiler Features:
|
|||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
* Inline Assembly: Fix internal error when accessing incorrect constant variables.
|
* 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)
|
### 0.6.4 (2020-03-10)
|
||||||
|
@ -1487,11 +1487,19 @@ TypeResult ReferenceType::unaryOperatorResult(Token _operator) const
|
|||||||
case DataLocation::Memory:
|
case DataLocation::Memory:
|
||||||
return TypeProvider::emptyTuple();
|
return TypeProvider::emptyTuple();
|
||||||
case DataLocation::Storage:
|
case DataLocation::Storage:
|
||||||
return m_isPointer ? nullptr : TypeProvider::emptyTuple();
|
return isPointer() ? nullptr : TypeProvider::emptyTuple();
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ReferenceType::isPointer() const
|
||||||
|
{
|
||||||
|
if (m_location == DataLocation::Storage)
|
||||||
|
return m_isPointer;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
TypePointer ReferenceType::copyForLocationIfReference(Type const* _type) const
|
TypePointer ReferenceType::copyForLocationIfReference(Type const* _type) const
|
||||||
{
|
{
|
||||||
return TypeProvider::withLocationIfReference(m_location, _type);
|
return TypeProvider::withLocationIfReference(m_location, _type);
|
||||||
@ -1502,7 +1510,7 @@ string ReferenceType::stringForReferencePart() const
|
|||||||
switch (m_location)
|
switch (m_location)
|
||||||
{
|
{
|
||||||
case DataLocation::Storage:
|
case DataLocation::Storage:
|
||||||
return string("storage ") + (m_isPointer ? "pointer" : "ref");
|
return string("storage ") + (isPointer() ? "pointer" : "ref");
|
||||||
case DataLocation::CallData:
|
case DataLocation::CallData:
|
||||||
return "calldata";
|
return "calldata";
|
||||||
case DataLocation::Memory:
|
case DataLocation::Memory:
|
||||||
@ -1868,7 +1876,8 @@ u256 ArrayType::memoryDataSize() const
|
|||||||
std::unique_ptr<ReferenceType> ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const
|
std::unique_ptr<ReferenceType> ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const
|
||||||
{
|
{
|
||||||
auto copy = make_unique<ArrayType>(_location);
|
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_arrayKind = m_arrayKind;
|
||||||
copy->m_baseType = copy->copyForLocationIfReference(m_baseType);
|
copy->m_baseType = copy->copyForLocationIfReference(m_baseType);
|
||||||
copy->m_hasDynamicLength = m_hasDynamicLength;
|
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
|
std::unique_ptr<ReferenceType> StructType::copyForLocation(DataLocation _location, bool _isPointer) const
|
||||||
{
|
{
|
||||||
auto copy = make_unique<StructType>(m_struct, _location);
|
auto copy = make_unique<StructType>(m_struct, _location);
|
||||||
copy->m_isPointer = _isPointer;
|
if (_location == DataLocation::Storage)
|
||||||
|
copy->m_isPointer = _isPointer;
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,7 +701,9 @@ public:
|
|||||||
/// pointer type, state variables are bound references. Assignments to pointers or deleting
|
/// 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
|
/// 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.
|
/// 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
|
bool operator==(ReferenceType const& _other) const
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"storageLocation": "memory",
|
"storageLocation": "memory",
|
||||||
"typeDescriptions":
|
"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[][]"
|
"typeString": "uint256[][]"
|
||||||
},
|
},
|
||||||
"typeName":
|
"typeName":
|
||||||
|
@ -14,9 +14,9 @@ contract C {
|
|||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// creation:
|
// creation:
|
||||||
// codeDepositCost: 1120000
|
// codeDepositCost: 1094400
|
||||||
// executionCost: 1160
|
// executionCost: 1134
|
||||||
// totalCost: 1121160
|
// totalCost: 1095534
|
||||||
// external:
|
// external:
|
||||||
// a(): 1130
|
// a(): 1130
|
||||||
// b(uint256): infinite
|
// b(uint256): infinite
|
||||||
|
@ -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"
|
@ -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"
|
@ -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;
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user