diff options
author | Christian <c@ethdev.com> | 2015-02-18 07:15:08 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2015-02-18 07:15:32 +0800 |
commit | 197b184d256dcfc086ce1ff0e3f63e053aba2276 (patch) | |
tree | be00c1a03aceebb3b35b25078ac6ebe201157aa7 /ExpressionCompiler.cpp | |
parent | 294648b534e294554f5ceb8467667eac3a60a3f1 (diff) | |
download | dexon-solidity-197b184d256dcfc086ce1ff0e3f63e053aba2276.tar.gz dexon-solidity-197b184d256dcfc086ce1ff0e3f63e053aba2276.tar.zst dexon-solidity-197b184d256dcfc086ce1ff0e3f63e053aba2276.zip |
Fixes for assigning and deleting structs containing byte arrays.
Diffstat (limited to 'ExpressionCompiler.cpp')
-rw-r--r-- | ExpressionCompiler.cpp | 25 |
1 files changed, 24 insertions, 1 deletions
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) |