diff options
author | chriseth <chris@ethereum.org> | 2018-07-13 07:26:50 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-07-13 07:26:50 +0800 |
commit | bab4a3975fd9f49850d11337dc6abf00a2542f1d (patch) | |
tree | ec14c09e76d9f63977591320ea5916bdbe798c79 /libsolidity/analysis | |
parent | 052f19c6b0aac3b4f60ee8a7f340033e0b5350f0 (diff) | |
parent | faa55f6544b2fd4e3eeadda14b7db83e76037843 (diff) | |
download | dexon-solidity-bab4a3975fd9f49850d11337dc6abf00a2542f1d.tar dexon-solidity-bab4a3975fd9f49850d11337dc6abf00a2542f1d.tar.gz dexon-solidity-bab4a3975fd9f49850d11337dc6abf00a2542f1d.tar.bz2 dexon-solidity-bab4a3975fd9f49850d11337dc6abf00a2542f1d.tar.lz dexon-solidity-bab4a3975fd9f49850d11337dc6abf00a2542f1d.tar.xz dexon-solidity-bab4a3975fd9f49850d11337dc6abf00a2542f1d.tar.zst dexon-solidity-bab4a3975fd9f49850d11337dc6abf00a2542f1d.zip |
Merge pull request #4501 from ethereum/recursiveStructsWithFixedArrays
Consider fixed-size arrays when checking for recursive structs.
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r-- | libsolidity/analysis/TypeChecker.cpp | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e2e4d9c3..cc373e03 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,22 +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 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)) { - auto const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->typeName()); - check(&dynamic_cast<StructDefinition const&>(*typeName.annotation().referencedDeclaration), 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); |