mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #10896 from ethereum/issue-10870
Fix issue with pop on storage array.
This commit is contained in:
@@ -584,8 +584,12 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
FunctionType const& function = *functionType;
|
||||
if (function.bound())
|
||||
// Only delegatecall and internal functions can be bound, this might be lifted later.
|
||||
solAssert(function.kind() == FunctionType::Kind::DelegateCall || function.kind() == FunctionType::Kind::Internal, "");
|
||||
solAssert(
|
||||
function.kind() == FunctionType::Kind::DelegateCall ||
|
||||
function.kind() == FunctionType::Kind::Internal ||
|
||||
function.kind() == FunctionType::Kind::ArrayPush ||
|
||||
function.kind() == FunctionType::Kind::ArrayPop,
|
||||
"");
|
||||
switch (function.kind())
|
||||
{
|
||||
case FunctionType::Kind::Declaration:
|
||||
@@ -945,9 +949,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
appendExternalFunctionCall(function, arguments, false);
|
||||
break;
|
||||
}
|
||||
case FunctionType::Kind::ByteArrayPush:
|
||||
case FunctionType::Kind::ArrayPush:
|
||||
{
|
||||
solAssert(function.bound(), "");
|
||||
_functionCall.expression().accept(*this);
|
||||
|
||||
if (function.parameterTypes().size() == 0)
|
||||
@@ -955,10 +959,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
auto paramType = function.returnParameterTypes().at(0);
|
||||
solAssert(paramType, "");
|
||||
|
||||
ArrayType const* arrayType =
|
||||
function.kind() == FunctionType::Kind::ArrayPush ?
|
||||
TypeProvider::array(DataLocation::Storage, paramType) :
|
||||
TypeProvider::bytesStorage();
|
||||
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(function.selfType());
|
||||
solAssert(arrayType, "");
|
||||
|
||||
// stack: ArrayReference
|
||||
m_context << u256(1) << Instruction::DUP2;
|
||||
@@ -978,10 +980,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
solAssert(function.parameterTypes().size() == 1, "");
|
||||
solAssert(!!function.parameterTypes()[0], "");
|
||||
TypePointer paramType = function.parameterTypes()[0];
|
||||
ArrayType const* arrayType =
|
||||
function.kind() == FunctionType::Kind::ArrayPush ?
|
||||
TypeProvider::array(DataLocation::Storage, paramType) :
|
||||
TypeProvider::bytesStorage();
|
||||
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(function.selfType());
|
||||
solAssert(arrayType, "");
|
||||
|
||||
// stack: ArrayReference
|
||||
arguments[0]->accept(*this);
|
||||
@@ -1004,7 +1004,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
utils().moveToStackTop(1 + type->sizeOnStack());
|
||||
utils().moveToStackTop(1 + type->sizeOnStack());
|
||||
// stack: argValue storageSlot slotOffset
|
||||
if (function.kind() == FunctionType::Kind::ArrayPush)
|
||||
if (!arrayType->isByteArray())
|
||||
StorageItem(m_context, *paramType).storeValue(*type, _functionCall.location(), true);
|
||||
else
|
||||
StorageByteArrayElement(m_context).storeValue(*type, _functionCall.location(), true);
|
||||
@@ -1014,14 +1014,11 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
||||
case FunctionType::Kind::ArrayPop:
|
||||
{
|
||||
_functionCall.expression().accept(*this);
|
||||
solAssert(function.bound(), "");
|
||||
solAssert(function.parameterTypes().empty(), "");
|
||||
|
||||
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(
|
||||
*dynamic_cast<MemberAccess const&>(_functionCall.expression()).expression().annotation().type
|
||||
);
|
||||
solAssert(arrayType.dataStoredIn(DataLocation::Storage), "");
|
||||
|
||||
ArrayUtils(m_context).popStorageArrayElement(arrayType);
|
||||
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(function.selfType());
|
||||
solAssert(arrayType && arrayType->dataStoredIn(DataLocation::Storage), "");
|
||||
ArrayUtils(m_context).popStorageArrayElement(*arrayType);
|
||||
break;
|
||||
}
|
||||
case FunctionType::Kind::ObjectCreation:
|
||||
@@ -1325,6 +1322,12 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
utils().pushCombinedFunctionEntryLabel(funDef);
|
||||
utils().moveIntoStack(funType->selfType()->sizeOnStack(), 1);
|
||||
}
|
||||
else if (
|
||||
funType->kind() == FunctionType::Kind::ArrayPop ||
|
||||
funType->kind() == FunctionType::Kind::ArrayPush
|
||||
)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
solAssert(funType->kind() == FunctionType::Kind::DelegateCall, "");
|
||||
|
||||
@@ -1276,30 +1276,31 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
}
|
||||
case FunctionType::Kind::ArrayPop:
|
||||
{
|
||||
auto const& memberAccessExpression = dynamic_cast<MemberAccess const&>(_functionCall.expression()).expression();
|
||||
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*memberAccessExpression.annotation().type);
|
||||
solAssert(functionType->bound(), "");
|
||||
solAssert(functionType->parameterTypes().empty(), "");
|
||||
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(functionType->selfType());
|
||||
solAssert(arrayType, "");
|
||||
define(_functionCall) <<
|
||||
m_utils.storageArrayPopFunction(arrayType) <<
|
||||
m_utils.storageArrayPopFunction(*arrayType) <<
|
||||
"(" <<
|
||||
IRVariable(_functionCall.expression()).commaSeparatedList() <<
|
||||
")\n";
|
||||
break;
|
||||
}
|
||||
case FunctionType::Kind::ByteArrayPush:
|
||||
case FunctionType::Kind::ArrayPush:
|
||||
{
|
||||
auto const& memberAccessExpression = dynamic_cast<MemberAccess const&>(_functionCall.expression()).expression();
|
||||
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*memberAccessExpression.annotation().type);
|
||||
ArrayType const* arrayType = dynamic_cast<ArrayType const*>(functionType->selfType());
|
||||
solAssert(arrayType, "");
|
||||
|
||||
if (arguments.empty())
|
||||
{
|
||||
auto slotName = m_context.newYulVariable();
|
||||
auto offsetName = m_context.newYulVariable();
|
||||
m_code << "let " << slotName << ", " << offsetName << " := " <<
|
||||
m_utils.storageArrayPushZeroFunction(arrayType) <<
|
||||
m_utils.storageArrayPushZeroFunction(*arrayType) <<
|
||||
"(" << IRVariable(_functionCall.expression()).commaSeparatedList() << ")\n";
|
||||
setLValue(_functionCall, IRLValue{
|
||||
*arrayType.baseType(),
|
||||
*arrayType->baseType(),
|
||||
IRLValue::Storage{
|
||||
slotName,
|
||||
offsetName,
|
||||
@@ -1309,12 +1310,12 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
||||
else
|
||||
{
|
||||
IRVariable argument =
|
||||
arrayType.baseType()->isValueType() ?
|
||||
convert(*arguments.front(), *arrayType.baseType()) :
|
||||
arrayType->baseType()->isValueType() ?
|
||||
convert(*arguments.front(), *arrayType->baseType()) :
|
||||
*arguments.front();
|
||||
|
||||
m_code <<
|
||||
m_utils.storageArrayPushFunction(arrayType, &argument.type()) <<
|
||||
m_utils.storageArrayPushFunction(*arrayType, &argument.type()) <<
|
||||
"(" <<
|
||||
IRVariable(_functionCall.expression()).commaSeparatedList() <<
|
||||
(argument.stackSlots().empty() ? "" : (", " + argument.commaSeparatedList())) <<
|
||||
@@ -1590,16 +1591,24 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
}).count(objectCategory) > 0, "");
|
||||
|
||||
define(IRVariable(_memberAccess).part("self"), _memberAccess.expression());
|
||||
auto const& functionDefinition = dynamic_cast<FunctionDefinition const&>(memberFunctionType->declaration());
|
||||
solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
|
||||
if (memberFunctionType->kind() == FunctionType::Kind::Internal)
|
||||
{
|
||||
auto const& functionDefinition = dynamic_cast<FunctionDefinition const&>(memberFunctionType->declaration());
|
||||
define(IRVariable(_memberAccess).part("functionIdentifier")) << to_string(functionDefinition.id()) << "\n";
|
||||
if (!_memberAccess.annotation().calledDirectly)
|
||||
m_context.addToInternalDispatch(functionDefinition);
|
||||
}
|
||||
else if (
|
||||
memberFunctionType->kind() == FunctionType::Kind::ArrayPush ||
|
||||
memberFunctionType->kind() == FunctionType::Kind::ArrayPop
|
||||
)
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const& functionDefinition = dynamic_cast<FunctionDefinition const&>(memberFunctionType->declaration());
|
||||
solAssert(memberFunctionType->kind() == FunctionType::Kind::DelegateCall, "");
|
||||
auto contract = dynamic_cast<ContractDefinition const*>(functionDefinition.scope());
|
||||
solAssert(contract && contract->isLibrary(), "");
|
||||
|
||||
Reference in New Issue
Block a user