From 561e461ded32f4e3c3ccd0514e9022d06dc816e1 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Thu, 26 Mar 2015 12:22:49 +0100 Subject: [PATCH 1/6] added createing FunctionType from ArrayType VariableDeclaration added test --- libsolidity/ExpressionCompiler.cpp | 20 ++++++++++++-------- libsolidity/Types.cpp | 17 +++++++++++------ test/SolidityEndToEndTest.cpp | 13 +++++++++++++ 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index daea21623..59781f821 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -71,16 +71,20 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& m_context << location.first; TypePointer returnType = _varDecl.getType(); - for (TypePointer const& paramType: paramTypes) + if (ArrayType const* arrayType = dynamic_cast(returnType.get())) { - // move offset to memory - CompilerUtils(m_context).storeInMemory(length); - unsigned argLen = paramType->getCalldataEncodedSize(); - length -= argLen; - m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; + (void)arrayType; + } else + for (TypePointer const& paramType: paramTypes) + { + // move offset to memory + CompilerUtils(m_context).storeInMemory(length); + unsigned argLen = paramType->getCalldataEncodedSize(); + length -= argLen; + m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; - returnType = dynamic_cast(*returnType).getValueType(); - } + returnType = dynamic_cast(*returnType).getValueType(); + } unsigned retSizeOnStack = 0; solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 78649cc95..0c80a0f7d 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -1002,12 +1002,17 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): retParamNames.push_back(member.first); retParams.push_back(member.second); } - } - else - { - retParams.push_back(returnType); - retParamNames.push_back(""); - } + } else + if (auto arrayType = dynamic_cast(returnType.get())) + { + params.push_back(make_shared(256)); + paramNames.push_back(""); + returnType = arrayType->getBaseType(); + } else + { + retParams.push_back(returnType); + retParamNames.push_back(""); + } swap(params, m_parameterTypes); swap(paramNames, m_parameterNames); diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index b169263da..3c4c2bc0e 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -966,6 +966,19 @@ BOOST_AUTO_TEST_CASE(simple_accessor) BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); } +BOOST_AUTO_TEST_CASE(array_accessor) +{ + char const* sourceCode = R"( + contract test { + uint[8] datas; + function test() { + datas[2] = 8; + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("data(2)") == encodeArgs(8)); +} + BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) { char const* sourceCode = "contract test {\n" From 518daee5465570714d4fb59bc227c3195c64bdf6 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Tue, 31 Mar 2015 11:07:10 +0200 Subject: [PATCH 2/6] some more tests --- libsolidity/CompilerContext.h | 1 + libsolidity/ExpressionCompiler.cpp | 46 +++++++++++++++++++----------- libsolidity/Types.cpp | 22 +++++++------- test/SolidityEndToEndTest.cpp | 39 +++++++++++++++++++++---- 4 files changed, 74 insertions(+), 34 deletions(-) diff --git a/libsolidity/CompilerContext.h b/libsolidity/CompilerContext.h index 87f90d4c4..e752d59b8 100644 --- a/libsolidity/CompilerContext.h +++ b/libsolidity/CompilerContext.h @@ -83,6 +83,7 @@ public: /// Converts an offset relative to the current stack height to a value that can be used later /// with baseToCurrentStackOffset to point to the same stack element. unsigned currentToBaseStackOffset(unsigned _offset) const; + /// @returns pair of slot and byte offset of the value inside this slot. std::pair getStorageLocationOfVariable(Declaration const& _declaration) const; /// Appends a JUMPI instruction to a new tag and @returns the tag diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 59781f821..30cc3c6f8 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -62,8 +62,19 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& unsigned length = 0; TypePointers const& paramTypes = accessorType.getParameterTypes(); - // move arguments to memory - for (TypePointer const& paramType: boost::adaptors::reverse(paramTypes)) + + // to exclude the last key if it is an array + TypePointer finalMappingValueType = _varDecl.getType(); + while (finalMappingValueType->getCategory() == Type::Category::Mapping) + finalMappingValueType = dynamic_cast(*finalMappingValueType).getValueType(); + + bool finalIsArrayType = finalMappingValueType->getCategory() == Type::Category::Array; + TypePointers mappingKeys(paramTypes); + if (finalIsArrayType) + mappingKeys.pop_back(); + + // move mapping arguments to memory + for (TypePointer const& paramType: boost::adaptors::reverse(mappingKeys)) length += CompilerUtils(m_context).storeInMemory(length, *paramType, true); // retrieve the position of the variable @@ -71,20 +82,21 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& m_context << location.first; TypePointer returnType = _varDecl.getType(); - if (ArrayType const* arrayType = dynamic_cast(returnType.get())) + + for (TypePointer const& paramType: mappingKeys) { - (void)arrayType; - } else - for (TypePointer const& paramType: paramTypes) - { - // move offset to memory - CompilerUtils(m_context).storeInMemory(length); - unsigned argLen = paramType->getCalldataEncodedSize(); - length -= argLen; - m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; + // move offset to memory + CompilerUtils(m_context).storeInMemory(length); + unsigned argLen = paramType->getCalldataEncodedSize(); + length -= argLen; + m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; - returnType = dynamic_cast(*returnType).getValueType(); - } + returnType = dynamic_cast(*returnType).getValueType(); + } + if (finalMappingValueType->isDynamicallySized()) + { + + } unsigned retSizeOnStack = 0; solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); @@ -100,7 +112,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& pair const& offsets = structType->getStorageOffsetsOfMember(names[i]); m_context << eth::Instruction::DUP1 << u256(offsets.first) << eth::Instruction::ADD << u256(offsets.second); StorageItem(m_context, *types[i]).retrieveValue(SourceLocation(), true); - solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 not yet implemented."); + solAssert(types[i]->getSizeOnStack() == 1, "Returning struct elements with stack size != 1 is not yet implemented."); m_context << eth::Instruction::SWAP1; retSizeOnStack += types[i]->getSizeOnStack(); } @@ -114,7 +126,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& StorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true); retSizeOnStack = returnType->getSizeOnStack(); } - solAssert(retSizeOnStack <= 15, "Stack too deep."); + solAssert(retSizeOnStack <= 15, "Stack is too deep."); m_context << eth::dupInstruction(retSizeOnStack + 1); m_context.appendJump(eth::AssemblyItem::JumpType::OutOfFunction); } @@ -753,7 +765,7 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) appendTypeMoveToMemory(IntegerType(256)); m_context << u256(0) << eth::Instruction::SHA3; m_context << u256(0); - setLValueToStorageItem( _indexAccess); + setLValueToStorageItem(_indexAccess); } else if (baseType.getCategory() == Type::Category::Array) { diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 0c80a0f7d..9a5b120b6 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -1002,17 +1002,17 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): retParamNames.push_back(member.first); retParams.push_back(member.second); } - } else - if (auto arrayType = dynamic_cast(returnType.get())) - { - params.push_back(make_shared(256)); - paramNames.push_back(""); - returnType = arrayType->getBaseType(); - } else - { - retParams.push_back(returnType); - retParamNames.push_back(""); - } + } else if (auto arrayType = dynamic_cast(returnType.get())) + { + params.push_back(make_shared(256)); + paramNames.push_back(""); + returnType = arrayType->getBaseType(); + } + else + { + retParams.push_back(returnType); + retParamNames.push_back(""); + } swap(params, m_parameterTypes); swap(paramNames, m_parameterNames); diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 3c4c2bc0e..1b7f4129c 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -967,16 +967,43 @@ BOOST_AUTO_TEST_CASE(simple_accessor) } BOOST_AUTO_TEST_CASE(array_accessor) +{ + char const* sourceCode = R"( + contract test { + uint[8] data; + uint[] dynamicData; + function test() { + data[2] = 8; + dynamicData.length = 3; + dynamicData[2] = 8; + } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("data(uint256)", 2) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("data(uint256)", 8) == encodeArgs()); + BOOST_CHECK(callContractFunction("dynamicData(uint256)", 2) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("dynamicData(uint256)", 8) == encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) { char const* sourceCode = R"( contract test { - uint[8] datas; - function test() { - datas[2] = 8; - } - })"; + mapping(uint => uint[8]) data; + mapping(uint => uint[]) dynamicData; + function test() { + data[2][2] = 8; + dynamicData[2].length = 3; + dynamicData[2][2] = 8; + } + } + )"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("data(2)") == encodeArgs(8)); + BOOST_CHECK(callContractFunction("data(uint256,uint256)", 2, 2) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("data(uint256, 256)", 2, 8) == encodeArgs()); + BOOST_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 2) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("dynamicData(uint256,uint256)", 2, 8) == encodeArgs()); } BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) From 46eb3f366b5c1226fdb6ea21279913afce9d40a6 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Wed, 1 Apr 2015 14:22:42 +0200 Subject: [PATCH 3/6] added implementation to append code for State variable accessor fixed tests --- libsolidity/CompilerUtils.cpp | 8 +++-- libsolidity/CompilerUtils.h | 2 ++ libsolidity/ExpressionCompiler.cpp | 48 +++++++++++++----------------- libsolidity/Types.cpp | 25 ++++++++++------ test/SolidityEndToEndTest.cpp | 9 +++--- 5 files changed, 50 insertions(+), 42 deletions(-) diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index 511254fa5..454951147 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -157,8 +157,12 @@ void CompilerUtils::copyToStackTop(unsigned _stackDepth, unsigned _itemSize) void CompilerUtils::popStackElement(Type const& _type) { - unsigned const size = _type.getSizeOnStack(); - for (unsigned i = 0; i < size; ++i) + popStackSlots(_type.getSizeOnStack()); +} + +void CompilerUtils::popStackSlots(size_t _amount) +{ + for (size_t i = 0; i < _amount; ++i) m_context << eth::Instruction::POP; } diff --git a/libsolidity/CompilerUtils.h b/libsolidity/CompilerUtils.h index 043de41dd..5b809beac 100644 --- a/libsolidity/CompilerUtils.h +++ b/libsolidity/CompilerUtils.h @@ -79,6 +79,8 @@ public: void copyToStackTop(unsigned _stackDepth, unsigned _itemSize); /// Removes the current value from the top of the stack. void popStackElement(Type const& _type); + /// Removes element from the top of the stack _amount times. + void popStackSlots(size_t _amount); template static unsigned getSizeOnStack(std::vector const& _variables); diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 30cc3c6f8..92fca636e 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -60,43 +60,37 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& CompilerContext::LocationSetter locationSetter(m_context, _varDecl); FunctionType accessorType(_varDecl); - unsigned length = 0; TypePointers const& paramTypes = accessorType.getParameterTypes(); - // to exclude the last key if it is an array - TypePointer finalMappingValueType = _varDecl.getType(); - while (finalMappingValueType->getCategory() == Type::Category::Mapping) - finalMappingValueType = dynamic_cast(*finalMappingValueType).getValueType(); - - bool finalIsArrayType = finalMappingValueType->getCategory() == Type::Category::Array; - TypePointers mappingKeys(paramTypes); - if (finalIsArrayType) - mappingKeys.pop_back(); - - // move mapping arguments to memory - for (TypePointer const& paramType: boost::adaptors::reverse(mappingKeys)) - length += CompilerUtils(m_context).storeInMemory(length, *paramType, true); - // retrieve the position of the variable auto const& location = m_context.getStorageLocationOfVariable(_varDecl); m_context << location.first; TypePointer returnType = _varDecl.getType(); - for (TypePointer const& paramType: mappingKeys) - { - // move offset to memory - CompilerUtils(m_context).storeInMemory(length); - unsigned argLen = paramType->getCalldataEncodedSize(); - length -= argLen; - m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3; - - returnType = dynamic_cast(*returnType).getValueType(); - } - if (finalMappingValueType->isDynamicallySized()) + for (size_t i = 0; i < paramTypes.size(); ++i) { - + if (auto mappingType = dynamic_cast(returnType.get())) + { + // move storage offset to memory. + CompilerUtils(m_context).storeInMemory(32); + //move key to memory. + CompilerUtils(m_context).copyToStackTop(paramTypes.size() - i, 1); + CompilerUtils(m_context).storeInMemory(0); + m_context << u256(64) << u256(0) << eth::Instruction::SHA3; + returnType = mappingType->getValueType(); + } + else if (auto arrayType = dynamic_cast(returnType.get())) + { + CompilerUtils(m_context).copyToStackTop(paramTypes.size() - i + 1, 1); + ArrayUtils(m_context).accessIndex(*arrayType); + returnType = arrayType->getBaseType(); + } + else + solAssert(false, "Index access is allowed only for \"mapping\" and \"array\" types."); } + //remove index arguments. + CompilerUtils(m_context).popStackSlots(paramTypes.size()); unsigned retSizeOnStack = 0; solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 9a5b120b6..9ac909daf 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -985,11 +985,23 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): vector paramNames; auto returnType = _varDecl.getType(); - while (auto mappingType = dynamic_cast(returnType.get())) + while (true) { - params.push_back(mappingType->getKeyType()); - paramNames.push_back(""); - returnType = mappingType->getValueType(); + auto mappingType = dynamic_cast(returnType.get()); + auto arrayType = dynamic_cast(returnType.get()); + if (mappingType) + { + params.push_back(mappingType->getKeyType()); + paramNames.push_back(""); + returnType = mappingType->getValueType(); + } + else if (arrayType) + { + returnType = arrayType->getBaseType(); + params.push_back(make_shared(256)); + } + else + break; } TypePointers retParams; @@ -1002,11 +1014,6 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): retParamNames.push_back(member.first); retParams.push_back(member.second); } - } else if (auto arrayType = dynamic_cast(returnType.get())) - { - params.push_back(make_shared(256)); - paramNames.push_back(""); - returnType = arrayType->getBaseType(); } else { diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 1b7f4129c..ee9c1f69b 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -970,8 +970,8 @@ BOOST_AUTO_TEST_CASE(array_accessor) { char const* sourceCode = R"( contract test { - uint[8] data; - uint[] dynamicData; + uint[8] public data; + uint[] public dynamicData; function test() { data[2] = 8; dynamicData.length = 3; @@ -980,6 +980,7 @@ BOOST_AUTO_TEST_CASE(array_accessor) } )"; compileAndRun(sourceCode); + auto res = callContractFunction("data(uint256)", 2) ; BOOST_CHECK(callContractFunction("data(uint256)", 2) == encodeArgs(8)); BOOST_CHECK(callContractFunction("data(uint256)", 8) == encodeArgs()); BOOST_CHECK(callContractFunction("dynamicData(uint256)", 2) == encodeArgs(8)); @@ -990,8 +991,8 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) { char const* sourceCode = R"( contract test { - mapping(uint => uint[8]) data; - mapping(uint => uint[]) dynamicData; + mapping(uint => uint[8]) public data; + mapping(uint => uint[]) public dynamicData; function test() { data[2][2] = 8; dynamicData[2].length = 3; From 99b3f7a55c1489abaa3fa6c4c9f479668186ff7a Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Wed, 1 Apr 2015 18:16:57 +0200 Subject: [PATCH 4/6] added < uint256 uinttype to test --- test/SolidityEndToEndTest.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index ee9c1f69b..7163d4692 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -972,10 +972,13 @@ BOOST_AUTO_TEST_CASE(array_accessor) contract test { uint[8] public data; uint[] public dynamicData; + uint24[] public smallTypeData; function test() { data[2] = 8; dynamicData.length = 3; dynamicData[2] = 8; + smallTypeData.length = 2; + smallTypeData[1] = 2; } } )"; @@ -985,6 +988,8 @@ BOOST_AUTO_TEST_CASE(array_accessor) BOOST_CHECK(callContractFunction("data(uint256)", 8) == encodeArgs()); BOOST_CHECK(callContractFunction("dynamicData(uint256)", 2) == encodeArgs(8)); BOOST_CHECK(callContractFunction("dynamicData(uint256)", 8) == encodeArgs()); + BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 1) == encodeArgs(2)); + BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 8) == encodeArgs()); } BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) From 2cf5fdcadf67a334844a0440bd572cd8a3786304 Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Thu, 2 Apr 2015 17:03:02 +0200 Subject: [PATCH 5/6] fixes added more tests --- libsolidity/ExpressionCompiler.cpp | 29 ++++++++++++++++++++++------- libsolidity/Types.cpp | 17 ++++++++--------- test/SolidityEndToEndTest.cpp | 22 +++++++++++++++------- 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 92fca636e..dcfb6e17c 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -64,7 +64,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& // retrieve the position of the variable auto const& location = m_context.getStorageLocationOfVariable(_varDecl); - m_context << location.first; + m_context << location.first << u256(location.second); TypePointer returnType = _varDecl.getType(); @@ -72,16 +72,22 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& { if (auto mappingType = dynamic_cast(returnType.get())) { + // pop offset + m_context << eth::Instruction::POP; // move storage offset to memory. CompilerUtils(m_context).storeInMemory(32); - //move key to memory. + // move key to memory. CompilerUtils(m_context).copyToStackTop(paramTypes.size() - i, 1); CompilerUtils(m_context).storeInMemory(0); m_context << u256(64) << u256(0) << eth::Instruction::SHA3; + // push offset + m_context << u256(0); returnType = mappingType->getValueType(); } else if (auto arrayType = dynamic_cast(returnType.get())) { + // pop offset + m_context << eth::Instruction::POP; CompilerUtils(m_context).copyToStackTop(paramTypes.size() - i + 1, 1); ArrayUtils(m_context).accessIndex(*arrayType); returnType = arrayType->getBaseType(); @@ -89,19 +95,28 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& else solAssert(false, "Index access is allowed only for \"mapping\" and \"array\" types."); } - //remove index arguments. - CompilerUtils(m_context).popStackSlots(paramTypes.size()); - + // remove index arguments. + if (paramTypes.size() == 1) + m_context << eth::Instruction::SWAP2 << eth::Instruction::POP << eth::Instruction::SWAP1; + else if (paramTypes.size() >= 2) + { + m_context << eth::swapInstruction(paramTypes.size()); + m_context << eth::Instruction::POP; + m_context << eth::swapInstruction(paramTypes.size()); + CompilerUtils(m_context).popStackSlots(paramTypes.size() - 1); + } unsigned retSizeOnStack = 0; solAssert(accessorType.getReturnParameterTypes().size() >= 1, ""); if (StructType const* structType = dynamic_cast(returnType.get())) { + // remove offset + m_context << eth::Instruction::POP; auto const& names = accessorType.getReturnParameterNames(); auto const& types = accessorType.getReturnParameterTypes(); // struct for (size_t i = 0; i < names.size(); ++i) { - if (types[i]->getCategory() == Type::Category::Mapping) + if (types[i]->getCategory() == Type::Category::Mapping || types[i]->getCategory() == Type::Category::Array) continue; pair const& offsets = structType->getStorageOffsetsOfMember(names[i]); m_context << eth::Instruction::DUP1 << u256(offsets.first) << eth::Instruction::ADD << u256(offsets.second); @@ -110,13 +125,13 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& m_context << eth::Instruction::SWAP1; retSizeOnStack += types[i]->getSizeOnStack(); } + // remove slot m_context << eth::Instruction::POP; } else { // simple value solAssert(accessorType.getReturnParameterTypes().size() == 1, ""); - m_context << u256(location.second); StorageItem(m_context, *returnType).retrieveValue(SourceLocation(), true); retSizeOnStack = returnType->getSizeOnStack(); } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 9ac909daf..bfde7187a 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -981,24 +981,23 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal FunctionType::FunctionType(VariableDeclaration const& _varDecl): m_location(Location::External), m_isConstant(true), m_declaration(&_varDecl) { - TypePointers params; + TypePointers paramTypes; vector paramNames; auto returnType = _varDecl.getType(); while (true) { - auto mappingType = dynamic_cast(returnType.get()); - auto arrayType = dynamic_cast(returnType.get()); - if (mappingType) + if (auto mappingType = dynamic_cast(returnType.get())) { - params.push_back(mappingType->getKeyType()); + paramTypes.push_back(mappingType->getKeyType()); paramNames.push_back(""); returnType = mappingType->getValueType(); } - else if (arrayType) + else if (auto arrayType = dynamic_cast(returnType.get())) { returnType = arrayType->getBaseType(); - params.push_back(make_shared(256)); + paramNames.push_back(""); + paramTypes.push_back(make_shared(256)); } else break; @@ -1009,7 +1008,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): if (auto structType = dynamic_cast(returnType.get())) { for (pair const& member: structType->getMembers()) - if (member.second->canLiveOutsideStorage()) + if (member.second->getCategory() != Category::Mapping && member.second->getCategory() != Category::Array) { retParamNames.push_back(member.first); retParams.push_back(member.second); @@ -1021,7 +1020,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): retParamNames.push_back(""); } - swap(params, m_parameterTypes); + swap(paramTypes, m_parameterTypes); swap(paramNames, m_parameterNames); swap(retParams, m_returnParameterTypes); swap(retParamNames, m_returnParameterNames); diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index 7163d4692..4622e4228 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -973,23 +973,31 @@ BOOST_AUTO_TEST_CASE(array_accessor) uint[8] public data; uint[] public dynamicData; uint24[] public smallTypeData; + struct st { uint a; uint[] finalArray; } + mapping(uint256 => mapping(uint256 => st[5])) public multiple_map; + function test() { - data[2] = 8; + data[0] = 8; dynamicData.length = 3; dynamicData[2] = 8; - smallTypeData.length = 2; - smallTypeData[1] = 2; + smallTypeData.length = 128; + smallTypeData[1] = 22; + smallTypeData[127] = 2; + multiple_map[2][1][2].a = 3; + multiple_map[2][1][2].finalArray.length = 4; + multiple_map[2][1][2].finalArray[3] = 5; } } )"; compileAndRun(sourceCode); - auto res = callContractFunction("data(uint256)", 2) ; - BOOST_CHECK(callContractFunction("data(uint256)", 2) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("data(uint256)", 0) == encodeArgs(8)); BOOST_CHECK(callContractFunction("data(uint256)", 8) == encodeArgs()); BOOST_CHECK(callContractFunction("dynamicData(uint256)", 2) == encodeArgs(8)); BOOST_CHECK(callContractFunction("dynamicData(uint256)", 8) == encodeArgs()); - BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 1) == encodeArgs(2)); - BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 8) == encodeArgs()); + BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 1) == encodeArgs(22)); + BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 127) == encodeArgs(2)); + BOOST_CHECK(callContractFunction("smallTypeData(uint256)", 128) == encodeArgs()); + BOOST_CHECK(callContractFunction("multiple_map(uint256,uint256,uint256)", 2, 1, 2) == encodeArgs(3)); } BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) From a37ad1e7ce3b62dc889ca4167edc7146930771bf Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Wed, 8 Apr 2015 18:18:37 +0200 Subject: [PATCH 6/6] Fixing the build --- libtestutils/StateLoader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libtestutils/StateLoader.cpp b/libtestutils/StateLoader.cpp index 07eb2cef5..9eff30b29 100644 --- a/libtestutils/StateLoader.cpp +++ b/libtestutils/StateLoader.cpp @@ -54,5 +54,4 @@ StateLoader::StateLoader(Json::Value const& _json, std::string const& _dbPath): } m_state.commit(); - m_state.db().commit(); }