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:
|
||||
* 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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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":
|
||||
|
@ -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
|
||||
|
@ -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