diff options
author | chriseth <chris@ethereum.org> | 2017-06-01 17:48:38 +0800 |
---|---|---|
committer | Alex Beregszaszi <alex@rtfs.hu> | 2017-09-16 19:12:43 +0800 |
commit | 59ea19b3b957949fc53bfb5dc4e199d2196f8d18 (patch) | |
tree | 37f749081a21b2a0534131bc65e186e1d2228edf /libsolidity/ast | |
parent | 2e72bd163a149183c119ca9664b98b0c5473da41 (diff) | |
download | dexon-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.cpp | 27 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 4 |
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; }; |