Browse Source

Type conversion specialities for storage references.

cl-refactor
chriseth 10 years ago
parent
commit
c75c72a994
  1. 9
      libsolidity/CompilerUtils.cpp
  2. 23
      libsolidity/ExpressionCompiler.cpp
  3. 3
      libsolidity/Types.h
  4. 10
      test/libsolidity/SolidityEndToEndTest.cpp

9
libsolidity/CompilerUtils.cpp

@ -274,10 +274,13 @@ void CompilerUtils::encodeToMemory(
else else
{ {
copyToStackTop(argSize - stackPos + dynPointers + 2, _givenTypes[i]->getSizeOnStack()); copyToStackTop(argSize - stackPos + dynPointers + 2, _givenTypes[i]->getSizeOnStack());
if (targetType->isValueType())
convertType(*_givenTypes[i], *targetType, true);
solAssert(!!targetType, "Externalable type expected."); solAssert(!!targetType, "Externalable type expected.");
storeInMemoryDynamic(*targetType, _padToWordBoundaries); TypePointer type = targetType;
if (_givenTypes[i]->isInStorage())
type = _givenTypes[i]; // delay conversion
else
convertType(*_givenTypes[i], *targetType, true);
storeInMemoryDynamic(*type, _padToWordBoundaries);
} }
stackPos += _givenTypes[i]->getSizeOnStack(); stackPos += _givenTypes[i]->getSizeOnStack();
} }

23
libsolidity/ExpressionCompiler.cpp

@ -146,10 +146,13 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
{ {
CompilerContext::LocationSetter locationSetter(m_context, _assignment); CompilerContext::LocationSetter locationSetter(m_context, _assignment);
_assignment.getRightHandSide().accept(*this); _assignment.getRightHandSide().accept(*this);
if (_assignment.getType()->isValueType()) TypePointer type = _assignment.getRightHandSide().getType();
utils().convertType(*_assignment.getRightHandSide().getType(), *_assignment.getType()); if (!_assignment.getType()->isInStorage())
// We need this conversion mostly in the case of compound assignments. For non-value types {
// the conversion is done in LValue::storeValue. utils().convertType(*type, *_assignment.getType());
type = _assignment.getType();
}
_assignment.getLeftHandSide().accept(*this); _assignment.getLeftHandSide().accept(*this);
solAssert(!!m_currentLValue, "LValue not retrieved."); solAssert(!!m_currentLValue, "LValue not retrieved.");
@ -175,7 +178,7 @@ bool ExpressionCompiler::visit(Assignment const& _assignment)
m_context << eth::swapInstruction(itemSize + lvalueSize) << eth::Instruction::POP; m_context << eth::swapInstruction(itemSize + lvalueSize) << eth::Instruction::POP;
} }
} }
m_currentLValue->storeValue(*_assignment.getRightHandSide().getType(), _assignment.getLocation()); m_currentLValue->storeValue(*type, _assignment.getLocation());
m_currentLValue.reset(); m_currentLValue.reset();
return false; return false;
} }
@ -1119,14 +1122,10 @@ void ExpressionCompiler::appendExternalFunctionCall(
void ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression) void ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedType, Expression const& _expression)
{ {
solAssert(_expectedType.isValueType(), "Not implemented for non-value types.");
_expression.accept(*this); _expression.accept(*this);
if (_expectedType.isValueType()) utils().convertType(*_expression.getType(), _expectedType, true);
{ utils().storeInMemoryDynamic(_expectedType);
utils().convertType(*_expression.getType(), _expectedType, true);
utils().storeInMemoryDynamic(_expectedType);
}
else
utils().storeInMemoryDynamic(*_expression.getType()->mobileType());
} }
void ExpressionCompiler::setLValueFromDeclaration(Declaration const& _declaration, Expression const& _expression) void ExpressionCompiler::setLValueFromDeclaration(Declaration const& _declaration, Expression const& _expression)

3
libsolidity/Types.h

@ -202,6 +202,8 @@ public:
/// This returns the corresponding integer type for IntegerConstantTypes and the pointer type /// This returns the corresponding integer type for IntegerConstantTypes and the pointer type
/// for storage reference types. /// for storage reference types.
virtual TypePointer mobileType() const { return shared_from_this(); } virtual TypePointer mobileType() const { return shared_from_this(); }
/// @returns true if this type is a storage pointer or reference.
virtual bool isInStorage() const { return false; }
/// Returns the list of all members of this type. Default implementation: no members. /// Returns the list of all members of this type. Default implementation: no members.
virtual MemberList const& getMembers() const { return EmptyMemberList; } virtual MemberList const& getMembers() const { return EmptyMemberList; }
@ -374,6 +376,7 @@ public:
virtual TypePointer copyForLocation(Location _location, bool _isPointer) const = 0; virtual TypePointer copyForLocation(Location _location, bool _isPointer) const = 0;
virtual TypePointer mobileType() const override { return copyForLocation(m_location, true); } virtual TypePointer mobileType() const override { return copyForLocation(m_location, true); }
virtual bool isInStorage() const override { return m_location == Location::Storage; }
/// Storage references can be pointers or bound references. In general, local variables are of /// Storage references can be pointers or bound references. In general, local variables are of
/// pointer type, state variables are bound references. Assignments to pointers or deleting /// pointer type, state variables are bound references. Assignments to pointers or deleting

10
test/libsolidity/SolidityEndToEndTest.cpp

@ -4243,9 +4243,9 @@ BOOST_AUTO_TEST_CASE(return_string)
function get1() returns (string r) { function get1() returns (string r) {
return s; return s;
} }
// function get2() returns (string r) { function get2() returns (string r) {
// r = s; r = s;
// } }
} }
)"; )";
compileAndRun(sourceCode, 0, "Main"); compileAndRun(sourceCode, 0, "Main");
@ -4253,8 +4253,8 @@ BOOST_AUTO_TEST_CASE(return_string)
bytes args = encodeArgs(u256(0x20), u256(s.length()), s); bytes args = encodeArgs(u256(0x20), u256(s.length()), s);
BOOST_REQUIRE(callContractFunction("set(string)", asString(args)) == encodeArgs()); BOOST_REQUIRE(callContractFunction("set(string)", asString(args)) == encodeArgs());
BOOST_CHECK(callContractFunction("get1()") == args); BOOST_CHECK(callContractFunction("get1()") == args);
// BOOST_CHECK(callContractFunction("get2()") == args); BOOST_CHECK(callContractFunction("get2()") == args);
// BOOST_CHECK(callContractFunction("s()") == args); BOOST_CHECK(callContractFunction("s()") == args);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

Loading…
Cancel
Save