aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/ast
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-06-01 17:48:38 +0800
committerAlex Beregszaszi <alex@rtfs.hu>2017-09-16 19:12:43 +0800
commit59ea19b3b957949fc53bfb5dc4e199d2196f8d18 (patch)
tree37f749081a21b2a0534131bc65e186e1d2228edf /libsolidity/ast
parent2e72bd163a149183c119ca9664b98b0c5473da41 (diff)
downloaddexon-solidity-59ea19b3b957949fc53bfb5dc4e199d2196f8d18.tar.gz
dexon-solidity-59ea19b3b957949fc53bfb5dc4e199d2196f8d18.tar.zst
dexon-solidity-59ea19b3b957949fc53bfb5dc4e199d2196f8d18.zip
Check for recursive structs.
Diffstat (limited to 'libsolidity/ast')
-rw-r--r--libsolidity/ast/Types.cpp27
-rw-r--r--libsolidity/ast/Types.h4
2 files changed, 30 insertions, 1 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 3a93b74e..44316403 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -1769,8 +1769,10 @@ TypePointer StructType::interfaceType(bool _inLibrary) const
{
if (_inLibrary && location() == DataLocation::Storage)
return shared_from_this();
- else
+ else if (!recursive())
return copyForLocation(DataLocation::Memory, true);
+ else
+ return TypePointer();
}
TypePointer StructType::copyForLocation(DataLocation _location, bool _isPointer) const
@@ -1836,6 +1838,29 @@ set<string> StructType::membersMissingInMemory() const
return missing;
}
+bool StructType::recursive() const
+{
+ set<StructDefinition const*> structsSeen;
+ function<bool(StructType const*)> check = [&](StructType const* t) -> bool
+ {
+ StructDefinition const* str = &t->structDefinition();
+ if (structsSeen.count(str))
+ return true;
+ structsSeen.insert(str);
+ for (ASTPointer<VariableDeclaration> const& variable: str->members())
+ {
+ Type const* memberType = variable->annotation().type.get();
+ while (dynamic_cast<ArrayType const*>(memberType))
+ memberType = dynamic_cast<ArrayType const*>(memberType)->baseType().get();
+ if (StructType const* innerStruct = dynamic_cast<StructType const*>(memberType))
+ if (check(innerStruct))
+ return true;
+ }
+ return false;
+ };
+ return check(this);
+}
+
TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const
{
return _operator == Token::Delete ? make_shared<TupleType>() : TypePointer();
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index d4d6da69..e6d3a7b1 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -758,6 +758,10 @@ public:
/// @returns the set of all members that are removed in the memory version (typically mappings).
std::set<std::string> membersMissingInMemory() const;
+ /// @returns true if the same struct is used recursively in one of its members. Only
+ /// analyses the "memory" representation, i.e. mappings are ignored in all structs.
+ bool recursive() const;
+
private:
StructDefinition const& m_struct;
};