Browse Source

Fix and test for not really recursive structs.

Fixes #2223.
cl-refactor
chriseth 9 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 <functional>
#include <boost/range/adaptor/reversed.hpp>
#include <libsolidity/Utils.h>
#include <libsolidity/AST.h>
@ -434,23 +435,29 @@ void StructDefinition::checkMemberTypes() const
void StructDefinition::checkRecursion() const
{
set<StructDefinition const*> definitionsSeen;
vector<StructDefinition const*> queue = {this};
while (!queue.empty())
using StructPointer = StructDefinition const*;
using StructPointersSet = set<StructPointer>;
function<void(StructPointer,StructPointersSet const&)> check = [&](StructPointer _struct, StructPointersSet const& _parents)
{
StructDefinition const* def = queue.back();
queue.pop_back();
if (definitionsSeen.count(def))
BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation())
<< errinfo_comment("Recursive struct definition."));
definitionsSeen.insert(def);
for (ASTPointer<VariableDeclaration> const& member: def->getMembers())
if (_parents.count(_struct))
BOOST_THROW_EXCEPTION(
ParserError() <<
errinfo_sourceLocation(_struct->getLocation()) <<
errinfo_comment("Recursive struct definition.")
);
set<StructDefinition const*> parents = _parents;
parents.insert(_struct);
for (ASTPointer<VariableDeclaration> const& member: _struct->getMembers())
if (member->getType()->getCategory() == Type::Category::Struct)
{
UserDefinedTypeName const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->getTypeName());
queue.push_back(&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()));
auto const& typeName = dynamic_cast<UserDefinedTypeName const&>(*member->getTypeName());
check(
&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()),
parents
);
}
}
};
check(this, {});
}
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_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)
{
char const* text = "contract test {\n"

Loading…
Cancel
Save