fixed-sized arrays as return type

Conflicts:
	test/libsolidity/SolidityEndToEndTest.cpp
This commit is contained in:
LianaHus 2015-09-23 17:31:37 +02:00
parent 09f1f1e595
commit 9547c4563c
5 changed files with 54 additions and 10 deletions

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -853,6 +853,14 @@ 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, "");
return m_length * m_baseType->memoryHeadSize();
}
TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const
{
auto copy = make_shared<ArrayType>(_location);

View File

@ -501,9 +501,11 @@ 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;
private:
/// String is interpreted as a subtype of Bytes.
enum class ArrayKind { Ordinary, Bytes, String };

View File

@ -5325,6 +5325,25 @@ 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() constant returns (uint16[5] arr)
{
}
}
contract B {
function f()
{
var a = new A();
uint16[5] memory res = a.f();
}
}
)";
compileAndRun(sourceCode, 0, "B");
}
BOOST_AUTO_TEST_SUITE_END()
}