aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-09-24 07:12:51 +0800
committerchriseth <c@ethdev.com>2015-09-24 07:12:51 +0800
commit4a2114ba35eae0a9dae5be2526d107dd19d33baf (patch)
tree93c0d7c98daf8345bb2d2572fc0ce1cbdda856bb
parent09f1f1e5955fc358697b49542c6c8eb42496ef10 (diff)
parentc096c3c3490176c8fa61345a38b14078a399962f (diff)
downloaddexon-solidity-4a2114ba35eae0a9dae5be2526d107dd19d33baf.tar.gz
dexon-solidity-4a2114ba35eae0a9dae5be2526d107dd19d33baf.tar.zst
dexon-solidity-4a2114ba35eae0a9dae5be2526d107dd19d33baf.zip
Merge pull request #83 from LianaHus/sol_split_the_source_tree
fixed-sized arrays as return type for functions
-rw-r--r--libsolidity/CompilerUtils.cpp25
-rw-r--r--libsolidity/ExpressionCompiler.cpp10
-rw-r--r--libsolidity/Types.cpp9
-rw-r--r--libsolidity/Types.h1
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp29
5 files changed, 64 insertions, 10 deletions
diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp
index b9b554e8..a77e6536 100644
--- a/libsolidity/CompilerUtils.cpp
+++ b/libsolidity/CompilerUtils.cpp
@@ -86,16 +86,27 @@ void CompilerUtils::loadFromMemoryDynamic(
bool _padToWordBoundaries,
bool _keepUpdatedMemoryOffset
)
-{
- solAssert(_type.category() != Type::Category::Array, "Arrays not yet implemented.");
+{
if (_keepUpdatedMemoryOffset)
m_context << eth::Instruction::DUP1;
- unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries);
- if (_keepUpdatedMemoryOffset)
+
+ if (auto arrayType = dynamic_cast<ArrayType const*>(&_type))
{
- // update memory counter
- moveToStackTop(_type.sizeOnStack());
- m_context << u256(numBytes) << eth::Instruction::ADD;
+ solAssert(!arrayType->isDynamicallySized(), "");
+ solAssert(!_fromCalldata, "");
+ solAssert(_padToWordBoundaries, "");
+ if (_keepUpdatedMemoryOffset)
+ m_context << arrayType->memorySize() << eth::Instruction::ADD;
+ }
+ else
+ {
+ unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries);
+ if (_keepUpdatedMemoryOffset)
+ {
+ // update memory counter
+ moveToStackTop(_type.sizeOnStack());
+ m_context << u256(numBytes) << eth::Instruction::ADD;
+ }
}
}
diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp
index 65706602..49bf2559 100644
--- a/libsolidity/ExpressionCompiler.cpp
+++ b/libsolidity/ExpressionCompiler.cpp
@@ -1256,10 +1256,14 @@ void ExpressionCompiler::appendExternalFunctionCall(
}
else if (firstReturnType)
{
- //@todo manually update free memory pointer if we accept returning memory-stored objects
utils().fetchFreeMemoryPointer();
- utils().loadFromMemoryDynamic(*firstReturnType, false, true, false);
-
+ if (dynamic_cast<ReferenceType const*>(firstReturnType))
+ {
+ utils().loadFromMemoryDynamic(*firstReturnType, false, true, true);
+ utils().storeFreeMemoryPointer();
+ }
+ else
+ utils().loadFromMemoryDynamic(*firstReturnType, false, true, false);
}
}
diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp
index 68e8e91d..18f2817e 100644
--- a/libsolidity/Types.cpp
+++ b/libsolidity/Types.cpp
@@ -853,6 +853,15 @@ TypePointer ArrayType::externalType() const
return std::make_shared<ArrayType>(DataLocation::Memory, baseExt, m_length);
}
+u256 ArrayType::memorySize() const
+{
+ solAssert(!isDynamicallySized(), "");
+ solAssert(m_location == DataLocation::Memory, "");
+ u256 size = m_length * m_baseType->memoryHeadSize();
+ solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned.");
+ return size;
+}
+
TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const
{
auto copy = make_shared<ArrayType>(_location);
diff --git a/libsolidity/Types.h b/libsolidity/Types.h
index 11218b7a..73111e48 100644
--- a/libsolidity/Types.h
+++ b/libsolidity/Types.h
@@ -501,6 +501,7 @@ public:
bool isString() const { return m_arrayKind == ArrayKind::String; }
TypePointer const& baseType() const { solAssert(!!m_baseType, ""); return m_baseType;}
u256 const& length() const { return m_length; }
+ u256 memorySize() const;
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 8026f216..3124f9cf 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -5325,6 +5325,35 @@ BOOST_AUTO_TEST_CASE(strings_in_struct)
BOOST_CHECK(callContractFunction("getLast()") == encodeDyn(s));
}
+BOOST_AUTO_TEST_CASE(fixed_arrays_as_return_type)
+{
+ char const* sourceCode = R"(
+ contract A {
+ function f(uint16 input) constant returns (uint16[5] arr)
+ {
+ arr[0] = input;
+ arr[1] = ++input;
+ arr[2] = ++input;
+ arr[3] = ++input;
+ arr[4] = ++input;
+ }
+ }
+ contract B {
+ function f() returns (uint16[5] res, uint16[5] res2)
+ {
+ var a = new A();
+ res = a.f(2);
+ res2 = a.f(1000);
+ }
+ }
+ )";
+ compileAndRun(sourceCode, 0, "B");
+ BOOST_CHECK(callContractFunction("f()") == encodeArgs(
+ u256(2), u256(3), u256(4), u256(5), u256(6), // first return argument
+ u256(1000), u256(1001), u256(1002), u256(1003), u256(1004)) // second return argument
+ );
+}
+
BOOST_AUTO_TEST_SUITE_END()
}