diff options
-rw-r--r-- | AST.cpp | 33 |
1 files changed, 20 insertions, 13 deletions
@@ -21,6 +21,7 @@ */ #include <algorithm> +#include <functional> #include <boost/range/adaptor/reversed.hpp> #include <libsolidity/Utils.h> #include <libsolidity/AST.h> @@ -434,23 +435,29 @@ void StructDefinition::checkMemberTypes() const void StructDefinition::checkRecursion() const { - set<StructDefinition const*> definitionsSeen; - vector<StructDefinition const*> queue = {this}; - while (!queue.empty()) + using StructPointer = StructDefinition const*; + using StructPointersSet = set<StructPointer>; + function<void(StructPointer,StructPointersSet const&)> check = [&](StructPointer _struct, StructPointersSet const& _parents) { - StructDefinition const* def = queue.back(); - queue.pop_back(); - if (definitionsSeen.count(def)) - BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation()) - << errinfo_comment("Recursive struct definition.")); - definitionsSeen.insert(def); - for (ASTPointer<VariableDeclaration> const& member: def->getMembers()) + if (_parents.count(_struct)) + BOOST_THROW_EXCEPTION( + ParserError() << + errinfo_sourceLocation(_struct->getLocation()) << + errinfo_comment("Recursive struct definition.") + ); + set<StructDefinition const*> parents = _parents; + parents.insert(_struct); + for (ASTPointer<VariableDeclaration> const& member: _struct->getMembers()) if (member->getType()->getCategory() == Type::Category::Struct) { - UserDefinedTypeName const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->getTypeName()); - queue.push_back(&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration())); + auto const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->getTypeName()); + check( + &dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()), + parents + ); } - } + }; + check(this, {}); } TypePointer EnumDefinition::getType(ContractDefinition const*) const |