Browse Source

Fix and test for not really recursive structs.

Fixes #2223.
cl-refactor
chriseth 10 years ago
parent
commit
c7b257acde
  1. 33
      libsolidity/AST.cpp
  2. 11
      test/libsolidity/SolidityNameAndTypeResolution.cpp

33
libsolidity/AST.cpp

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

11
test/libsolidity/SolidityNameAndTypeResolution.cpp

@ -190,6 +190,17 @@ BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError); BOOST_CHECK_THROW(parseTextAndResolveNames(text), ParserError);
} }
BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive)
{
char const* text = R"(
contract test {
struct s1 { uint a; }
struct s2 { s1 x; s1 y; }
}
)";
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping) BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping)
{ {
char const* text = "contract test {\n" char const* text = "contract test {\n"

Loading…
Cancel
Save