From d71a023c0b7bdfa5af3598a919079cc5529106bb Mon Sep 17 00:00:00 2001 From: Daniel Kirchner Date: Thu, 12 Jul 2018 20:11:32 +0200 Subject: Use CycleDetector and account for multi-dimensional arrays. --- libsolidity/analysis/TypeChecker.cpp | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 9d7625c4..f0070382 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -30,6 +30,7 @@ #include #include #include +#include using namespace std; using namespace dev; @@ -593,28 +594,24 @@ bool TypeChecker::visit(StructDefinition const& _struct) m_errorReporter.typeError(member->location(), "Type cannot be used in struct."); // Check recursion, fatal error if detected. - using StructPointer = StructDefinition const*; - using StructPointersSet = set; - function check = [&](StructPointer _struct, StructPointersSet const& _parents) - { - if (_parents.count(_struct)) - m_errorReporter.fatalTypeError(_struct->location(), "Recursive struct definition."); - StructPointersSet parents = _parents; - parents.insert(_struct); - for (ASTPointer const& member: _struct->members()) - if (type(*member)->category() == Type::Category::Struct) - { - auto const& typeName = dynamic_cast(*member->typeName()); - check(&dynamic_cast(*typeName.annotation().referencedDeclaration), parents); - } - else if (auto arrayType = dynamic_cast(type(*member).get())) + auto visitor = [&](StructDefinition const& _struct, CycleDetector& _cycleDetector) + { + for (ASTPointer const& member: _struct.members()) + { + Type const* memberType = type(*member).get(); + while (auto arrayType = dynamic_cast(memberType)) { - if (!arrayType->isDynamicallySized()) - if (auto structType = dynamic_cast(arrayType->baseType().get())) - check(&structType->structDefinition(), parents); + if (arrayType->isDynamicallySized()) + break; + memberType = arrayType->baseType().get(); } + if (auto structType = dynamic_cast(memberType)) + if (_cycleDetector.run(structType->structDefinition())) + return; + } }; - check(&_struct, StructPointersSet{}); + if (CycleDetector(visitor).run(_struct) != nullptr) + m_errorReporter.fatalTypeError(_struct.location(), "Recursive struct definition."); ASTNode::listAccept(_struct.members(), *this); -- cgit