aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-02-18 20:31:15 +0800
committerchriseth <c@ethdev.com>2015-02-18 20:31:15 +0800
commit906b1de8620e240fc7c4c64fa1fac86e13318c07 (patch)
tree93ecf427fa04e76c112b8c8c184b72a1a85e71ec
parentde574487e43b15184ce81e7cb9885fd1387f4964 (diff)
parent197b184d256dcfc086ce1ff0e3f63e053aba2276 (diff)
downloaddexon-solidity-906b1de8620e240fc7c4c64fa1fac86e13318c07.tar
dexon-solidity-906b1de8620e240fc7c4c64fa1fac86e13318c07.tar.gz
dexon-solidity-906b1de8620e240fc7c4c64fa1fac86e13318c07.tar.bz2
dexon-solidity-906b1de8620e240fc7c4c64fa1fac86e13318c07.tar.lz
dexon-solidity-906b1de8620e240fc7c4c64fa1fac86e13318c07.tar.xz
dexon-solidity-906b1de8620e240fc7c4c64fa1fac86e13318c07.tar.zst
dexon-solidity-906b1de8620e240fc7c4c64fa1fac86e13318c07.zip
Merge pull request #1083 from chriseth/sol_structAssigndAndDeleteWithByteArray
Fixes for assigning and deleting structs containing byte arrays.
-rw-r--r--CompilerContext.h1
-rw-r--r--ExpressionCompiler.cpp25
-rw-r--r--ExpressionCompiler.h2
3 files changed, 26 insertions, 2 deletions
diff --git a/CompilerContext.h b/CompilerContext.h
index 6d6a65b6..f202d7f4 100644
--- a/CompilerContext.h
+++ b/CompilerContext.h
@@ -48,6 +48,7 @@ public:
bytes const& getCompiledContract(ContractDefinition const& _contract) const;
void adjustStackOffset(int _adjustment) { m_asm.adjustDeposit(_adjustment); }
+ unsigned getStackHeight() { solAssert(m_asm.deposit() >= 0, ""); return unsigned(m_asm.deposit()); }
bool isMagicGlobal(Declaration const* _declaration) const { return m_magicGlobals.count(_declaration) != 0; }
bool isLocalVariable(Declaration const* _declaration) const;
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 3bf1c8c9..a8bc53e0 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -1119,9 +1119,13 @@ void ExpressionCompiler::LValue::storeValue(Type const& _sourceType, Location co
{
solAssert(_sourceType.getCategory() == m_dataType->getCategory(), "");
if (m_dataType->getCategory() == Type::Category::ByteArray)
+ {
CompilerUtils(*m_context).copyByteArrayToStorage(
dynamic_cast<ByteArrayType const&>(*m_dataType),
dynamic_cast<ByteArrayType const&>(_sourceType));
+ if (_move)
+ *m_context << eth::Instruction::POP;
+ }
else if (m_dataType->getCategory() == Type::Category::Struct)
{
// stack layout: source_ref target_ref
@@ -1136,12 +1140,14 @@ void ExpressionCompiler::LValue::storeValue(Type const& _sourceType, Location co
*m_context << structType.getStorageOffsetOfMember(member.first)
<< eth::Instruction::DUP3 << eth::Instruction::DUP2
<< eth::Instruction::ADD;
+ // stack: source_ref target_ref member_offset source_member_ref
LValue rightHandSide(*m_context, LValueType::Storage, memberType);
rightHandSide.retrieveValue(_location, true);
- // stack: source_ref target_ref offset source_value...
+ // stack: source_ref target_ref member_offset source_value...
*m_context << eth::dupInstruction(2 + memberType->getSizeOnStack())
<< eth::dupInstruction(2 + memberType->getSizeOnStack())
<< eth::Instruction::ADD;
+ // stack: source_ref target_ref member_offset source_value... target_member_ref
LValue memberLValue(*m_context, LValueType::Storage, memberType);
memberLValue.storeValue(*memberType, _location, true);
*m_context << eth::Instruction::POP;
@@ -1189,6 +1195,23 @@ void ExpressionCompiler::LValue::setToZero(Location const& _location) const
case LValueType::Storage:
if (m_dataType->getCategory() == Type::Category::ByteArray)
CompilerUtils(*m_context).clearByteArray(dynamic_cast<ByteArrayType const&>(*m_dataType));
+ else if (m_dataType->getCategory() == Type::Category::Struct)
+ {
+ // stack layout: ref
+ auto const& structType = dynamic_cast<StructType const&>(*m_dataType);
+ for (auto const& member: structType.getMembers())
+ {
+ // zero each member that is not a mapping
+ TypePointer const& memberType = member.second;
+ if (memberType->getCategory() == Type::Category::Mapping)
+ continue;
+ *m_context << structType.getStorageOffsetOfMember(member.first)
+ << eth::Instruction::DUP2 << eth::Instruction::ADD;
+ LValue memberValue(*m_context, LValueType::Storage, memberType);
+ memberValue.setToZero();
+ }
+ *m_context << eth::Instruction::POP;
+ }
else
{
if (m_size == 0)
diff --git a/ExpressionCompiler.h b/ExpressionCompiler.h
index 734da50d..471d8186 100644
--- a/ExpressionCompiler.h
+++ b/ExpressionCompiler.h
@@ -144,7 +144,7 @@ private:
void retrieveValue(Location const& _location, bool _remove = false) const;
/// Moves a value from the stack to the lvalue. Removes the value if @a _move is true.
/// @a _location is the source location of the expression that caused this operation.
- /// Stack pre: [lvalue_ref] value
+ /// Stack pre: value [lvalue_ref]
/// Stack post if !_move: value_of(lvalue_ref)
void storeValue(Type const& _sourceType, Location const& _location = Location(), bool _move = false) const;
/// Stores zero in the lvalue.