aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2018-07-13 07:26:50 +0800
committerGitHub <noreply@github.com>2018-07-13 07:26:50 +0800
commitbab4a3975fd9f49850d11337dc6abf00a2542f1d (patch)
treeec14c09e76d9f63977591320ea5916bdbe798c79 /libsolidity/analysis
parent052f19c6b0aac3b4f60ee8a7f340033e0b5350f0 (diff)
parentfaa55f6544b2fd4e3eeadda14b7db83e76037843 (diff)
downloaddexon-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.cpp29
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);