mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Allow access to `_slot
` for local storage pointer variables.
This commit is contained in:
parent
44bcff42f5
commit
45041e5d3a
@ -1,6 +1,7 @@
|
|||||||
### 0.6.4 (unreleased)
|
### 0.6.4 (unreleased)
|
||||||
|
|
||||||
Language Features:
|
Language Features:
|
||||||
|
* Inline Assembly: Allow assigning to `_slot` of local storage variable pointers.
|
||||||
|
|
||||||
|
|
||||||
Compiler Features:
|
Compiler Features:
|
||||||
|
@ -172,6 +172,11 @@ Assignments are possible to assembly-local variables and to function-local
|
|||||||
variables. Take care that when you assign to variables that point to
|
variables. Take care that when you assign to variables that point to
|
||||||
memory or storage, you will only change the pointer and not the data.
|
memory or storage, you will only change the pointer and not the data.
|
||||||
|
|
||||||
|
You can assign to the ``_slot`` part of a local storage variable pointer.
|
||||||
|
For these (structs, arrays or mappings), the ``_offset`` part is always zero.
|
||||||
|
It is not possible to assign to the ``_slot`` or ``_offset`` part of a state variable,
|
||||||
|
though.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Things to Avoid
|
Things to Avoid
|
||||||
@ -225,4 +230,3 @@ first slot of the array and followed by the array elements.
|
|||||||
Statically-sized memory arrays do not have a length field, but it might be added later
|
Statically-sized memory arrays do not have a length field, but it might be added later
|
||||||
to allow better convertibility between statically- and dynamically-sized arrays, so
|
to allow better convertibility between statically- and dynamically-sized arrays, so
|
||||||
do not rely on this.
|
do not rely on this.
|
||||||
|
|
||||||
|
@ -677,10 +677,20 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
|||||||
m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
|
m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
|
||||||
return size_t(-1);
|
return size_t(-1);
|
||||||
}
|
}
|
||||||
else if (_context != yul::IdentifierContext::RValue)
|
else if (_context == yul::IdentifierContext::LValue)
|
||||||
{
|
{
|
||||||
m_errorReporter.typeError(_identifier.location, "Storage variables cannot be assigned to.");
|
if (var->isStateVariable())
|
||||||
return size_t(-1);
|
{
|
||||||
|
m_errorReporter.typeError(_identifier.location, "State variables cannot be assigned to - you have to use \"sstore()\".");
|
||||||
|
return size_t(-1);
|
||||||
|
}
|
||||||
|
else if (ref->second.isOffset)
|
||||||
|
{
|
||||||
|
m_errorReporter.typeError(_identifier.location, "Only _slot can be assigned to.");
|
||||||
|
return size_t(-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
solAssert(ref->second.isSlot, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!var->isConstant() && var->isStateVariable())
|
else if (!var->isConstant() && var->isStateVariable())
|
||||||
|
@ -781,7 +781,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// lvalue context
|
// lvalue context
|
||||||
solAssert(!ref->second.isOffset && !ref->second.isSlot, "");
|
solAssert(!ref->second.isOffset, "");
|
||||||
auto variable = dynamic_cast<VariableDeclaration const*>(decl);
|
auto variable = dynamic_cast<VariableDeclaration const*>(decl);
|
||||||
solAssert(
|
solAssert(
|
||||||
!!variable && m_context.isLocalVariable(variable),
|
!!variable && m_context.isLocalVariable(variable),
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
contract C {
|
||||||
|
struct S {
|
||||||
|
uint a;
|
||||||
|
uint b;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapping(uint => S) public mappingAccess;
|
||||||
|
|
||||||
|
function data() internal view returns (S storage _data) {
|
||||||
|
// We need to assign it from somewhere, otherwise we would
|
||||||
|
// get an "uninitialized access" error.
|
||||||
|
_data = mappingAccess[20];
|
||||||
|
|
||||||
|
bytes32 slot = keccak256(abi.encode(uint(1), uint(0)));
|
||||||
|
assembly {
|
||||||
|
_data_slot := slot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function set(uint x) public {
|
||||||
|
data().a = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
function get() public view returns (uint) {
|
||||||
|
return data().a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// get() -> 0
|
||||||
|
// mappingAccess(uint256): 1 -> 0, 0
|
||||||
|
// set(uint256): 4
|
||||||
|
// get() -> 4
|
||||||
|
// mappingAccess(uint256): 1 -> 4, 0
|
@ -9,5 +9,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (114-120): Storage variables cannot be assigned to.
|
// TypeError: (138-146): Only _slot can be assigned to.
|
||||||
// TypeError: (138-146): Storage variables cannot be assigned to.
|
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
contract C {
|
||||||
|
uint[] x;
|
||||||
|
fallback() external {
|
||||||
|
assembly {
|
||||||
|
x_slot := 1
|
||||||
|
x_offset := 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (84-90): State variables cannot be assigned to - you have to use "sstore()".
|
||||||
|
// TypeError: (108-116): State variables cannot be assigned to - you have to use "sstore()".
|
@ -0,0 +1,12 @@
|
|||||||
|
contract C {
|
||||||
|
uint[] x;
|
||||||
|
fallback() external {
|
||||||
|
uint[] storage y = x;
|
||||||
|
assembly {
|
||||||
|
y_slot := 1
|
||||||
|
y_offset := 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (138-146): Only _slot can be assigned to.
|
Loading…
Reference in New Issue
Block a user