diff options
author | Daniel Kirchner <daniel@ekpyron.org> | 2018-07-13 02:11:32 +0800 |
---|---|---|
committer | Daniel Kirchner <daniel@ekpyron.org> | 2018-07-13 02:14:02 +0800 |
commit | d71a023c0b7bdfa5af3598a919079cc5529106bb (patch) | |
tree | 0913a71829164d9163c74246d67399e96f4fa37e /libsolidity | |
parent | d4dfd2869402a2559ea720e4e3800d42b0f90221 (diff) | |
download | dexon-solidity-d71a023c0b7bdfa5af3598a919079cc5529106bb.tar dexon-solidity-d71a023c0b7bdfa5af3598a919079cc5529106bb.tar.gz dexon-solidity-d71a023c0b7bdfa5af3598a919079cc5529106bb.tar.bz2 dexon-solidity-d71a023c0b7bdfa5af3598a919079cc5529106bb.tar.lz dexon-solidity-d71a023c0b7bdfa5af3598a919079cc5529106bb.tar.xz dexon-solidity-d71a023c0b7bdfa5af3598a919079cc5529106bb.tar.zst dexon-solidity-d71a023c0b7bdfa5af3598a919079cc5529106bb.zip |
Use CycleDetector and account for multi-dimensional arrays.
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 35 |
1 files 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 <libsolidity/inlineasm/AsmAnalysisInfo.h> #include <libsolidity/inlineasm/AsmData.h> #include <libsolidity/interface/ErrorReporter.h> +#include <libdevcore/Algorithms.h> 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<StructPointer>; - function<void(StructPointer,StructPointersSet const&)> 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<VariableDeclaration> const& member: _struct->members()) - if (type(*member)->category() == Type::Category::Struct) - { - auto const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->typeName()); - check(&dynamic_cast<StructDefinition const&>(*typeName.annotation().referencedDeclaration), parents); - } - else if (auto arrayType = dynamic_cast<ArrayType const*>(type(*member).get())) + auto visitor = [&](StructDefinition const& _struct, CycleDetector<StructDefinition>& _cycleDetector) + { + for (ASTPointer<VariableDeclaration> const& member: _struct.members()) + { + Type const* memberType = type(*member).get(); + while (auto arrayType = dynamic_cast<ArrayType const*>(memberType)) { - if (!arrayType->isDynamicallySized()) - if (auto structType = dynamic_cast<StructType const*>(arrayType->baseType().get())) - check(&structType->structDefinition(), parents); + if (arrayType->isDynamicallySized()) + break; + memberType = arrayType->baseType().get(); } + if (auto structType = dynamic_cast<StructType const*>(memberType)) + if (_cycleDetector.run(structType->structDefinition())) + return; + } }; - check(&_struct, StructPointersSet{}); + if (CycleDetector<StructDefinition>(visitor).run(_struct) != nullptr) + m_errorReporter.fatalTypeError(_struct.location(), "Recursive struct definition."); ASTNode::listAccept(_struct.members(), *this); |