aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-07-16 07:06:19 +0800
committerchriseth <c@ethdev.com>2015-07-16 07:10:09 +0800
commita2796c3d15593d9744433dbfb35d166c07e3dec6 (patch)
treee51e8932396b808915468fc09f6889174a8b7e96
parentd747f34466ed6b3f3be0ea0c0d5278a7670e4d57 (diff)
downloaddexon-solidity-a2796c3d15593d9744433dbfb35d166c07e3dec6.tar
dexon-solidity-a2796c3d15593d9744433dbfb35d166c07e3dec6.tar.gz
dexon-solidity-a2796c3d15593d9744433dbfb35d166c07e3dec6.tar.bz2
dexon-solidity-a2796c3d15593d9744433dbfb35d166c07e3dec6.tar.lz
dexon-solidity-a2796c3d15593d9744433dbfb35d166c07e3dec6.tar.xz
dexon-solidity-a2796c3d15593d9744433dbfb35d166c07e3dec6.tar.zst
dexon-solidity-a2796c3d15593d9744433dbfb35d166c07e3dec6.zip
Allow structs containing mappings in memory.
-rw-r--r--AST.cpp30
-rw-r--r--Types.cpp26
-rw-r--r--Types.h9
3 files changed, 48 insertions, 17 deletions
diff --git a/AST.cpp b/AST.cpp
index 0cca63a8..3a83058c 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -830,11 +830,14 @@ void FunctionCall::checkTypeRequirements(TypePointers const*)
return;
}
+ /// For error message: Struct members that were removed during conversion to memory.
+ set<string> membersRemovedForStructConstructor;
if (isStructConstructorCall())
{
TypeType const& type = dynamic_cast<TypeType const&>(*expressionType);
auto const& structType = dynamic_cast<StructType const&>(*type.getActualType());
functionType = structType.constructorType();
+ membersRemovedForStructConstructor = structType.membersMissingInMemory();
}
else
functionType = dynamic_pointer_cast<FunctionType const>(expressionType);
@@ -847,13 +850,22 @@ void FunctionCall::checkTypeRequirements(TypePointers const*)
// function parameters
TypePointers const& parameterTypes = functionType->getParameterTypes();
if (!functionType->takesArbitraryParameters() && parameterTypes.size() != m_arguments.size())
- BOOST_THROW_EXCEPTION(createTypeError(
+ {
+ string msg =
"Wrong argument count for function call: " +
toString(m_arguments.size()) +
" arguments given but expected " +
toString(parameterTypes.size()) +
- "."
- ));
+ ".";
+ // Extend error message in case we try to construct a struct with mapping member.
+ if (isStructConstructorCall() && !membersRemovedForStructConstructor.empty())
+ {
+ msg += " Members that have to be skipped in memory:";
+ for (auto const& member: membersRemovedForStructConstructor)
+ msg += " " + member;
+ }
+ BOOST_THROW_EXCEPTION(createTypeError(msg));
+ }
if (isPositionalCall)
{
@@ -972,10 +984,22 @@ void MemberAccess::checkTypeRequirements(TypePointers const* _argumentTypes)
++it;
}
if (possibleMembers.size() == 0)
+ {
+ auto storageType = ReferenceType::copyForLocationIfReference(
+ DataLocation::Storage,
+ m_expression->getType()
+ );
+ if (!storageType->getMembers().membersByName(*m_memberName).empty())
+ BOOST_THROW_EXCEPTION(createTypeError(
+ "Member \"" + *m_memberName + "\" is not available in " +
+ type.toString() +
+ " outside of storage."
+ ));
BOOST_THROW_EXCEPTION(createTypeError(
"Member \"" + *m_memberName + "\" not found or not visible "
"after argument-dependent lookup in " + type.toString()
));
+ }
else if (possibleMembers.size() > 1)
BOOST_THROW_EXCEPTION(createTypeError(
"Member \"" + *m_memberName + "\" not unique "
diff --git a/Types.cpp b/Types.cpp
index 91ef16b5..d85c0511 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -1040,14 +1040,6 @@ u256 StructType::getStorageSize() const
return max<u256>(1, getMembers().getStorageSize());
}
-bool StructType::canLiveOutsideStorage() const
-{
- for (auto const& member: getMembers())
- if (!member.type->canLiveOutsideStorage())
- return false;
- return true;
-}
-
string StructType::toString(bool _short) const
{
string ret = "struct " + m_struct.getName();
@@ -1064,9 +1056,13 @@ MemberList const& StructType::getMembers() const
MemberList::MemberMap members;
for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
{
+ TypePointer type = variable->getType();
+ // Skip all mapping members if we are not in storage.
+ if (location() != DataLocation::Storage && !type->canLiveOutsideStorage())
+ continue;
members.push_back(MemberList::Member(
variable->getName(),
- copyForLocationIfReference(variable->getType()),
+ copyForLocationIfReference(type),
variable.get())
);
}
@@ -1077,8 +1073,7 @@ MemberList const& StructType::getMembers() const
TypePointer StructType::copyForLocation(DataLocation _location, bool _isPointer) const
{
- auto copy = make_shared<StructType>(m_struct);
- copy->m_location = _location;
+ auto copy = make_shared<StructType>(m_struct, _location);
copy->m_isPointer = _isPointer;
return copy;
}
@@ -1122,6 +1117,15 @@ u256 StructType::memoryOffsetOfMember(string const& _name) const
return 0;
}
+set<string> StructType::membersMissingInMemory() const
+{
+ set<string> missing;
+ for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
+ if (!variable->getType()->canLiveOutsideStorage())
+ missing.insert(variable->getName());
+ return missing;
+}
+
TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const
{
return _operator == Token::Delete ? make_shared<VoidType>() : TypePointer();
diff --git a/Types.h b/Types.h
index 8bdfc5e6..f18855b2 100644
--- a/Types.h
+++ b/Types.h
@@ -574,14 +574,14 @@ class StructType: public ReferenceType
{
public:
virtual Category getCategory() const override { return Category::Struct; }
- explicit StructType(StructDefinition const& _struct):
- ReferenceType(DataLocation::Storage), m_struct(_struct) {}
+ explicit StructType(StructDefinition const& _struct, DataLocation _location = DataLocation::Storage):
+ ReferenceType(_location), m_struct(_struct) {}
virtual bool isImplicitlyConvertibleTo(const Type& _convertTo) const override;
virtual bool operator==(Type const& _other) const override;
virtual unsigned getCalldataEncodedSize(bool _padded) const override;
u256 memorySize() const;
virtual u256 getStorageSize() const override;
- virtual bool canLiveOutsideStorage() const override;
+ virtual bool canLiveOutsideStorage() const override { return true; }
virtual std::string toString(bool _short) const override;
virtual MemberList const& getMembers() const override;
@@ -597,6 +597,9 @@ public:
StructDefinition const& structDefinition() const { return m_struct; }
+ /// @returns the set of all members that are removed in the memory version (typically mappings).
+ std::set<std::string> membersMissingInMemory() const;
+
private:
StructDefinition const& m_struct;
/// List of member types, will be lazy-initialized because of recursive references.