Check for recursive structs.

This commit is contained in:
chriseth
2017-09-16 12:12:43 +01:00
committed by Alex Beregszaszi
parent 2e72bd163a
commit 59ea19b3b9
3 changed files with 33 additions and 4 deletions
+26 -1
View File
@@ -1769,8 +1769,10 @@ TypePointer StructType::interfaceType(bool _inLibrary) const
{
if (_inLibrary && location() == DataLocation::Storage)
return shared_from_this();
else
else if (!recursive())
return copyForLocation(DataLocation::Memory, true);
else
return TypePointer();
}
TypePointer StructType::copyForLocation(DataLocation _location, bool _isPointer) const
@@ -1836,6 +1838,29 @@ set<string> StructType::membersMissingInMemory() const
return missing;
}
bool StructType::recursive() const
{
set<StructDefinition const*> structsSeen;
function<bool(StructType const*)> check = [&](StructType const* t) -> bool
{
StructDefinition const* str = &t->structDefinition();
if (structsSeen.count(str))
return true;
structsSeen.insert(str);
for (ASTPointer<VariableDeclaration> const& variable: str->members())
{
Type const* memberType = variable->annotation().type.get();
while (dynamic_cast<ArrayType const*>(memberType))
memberType = dynamic_cast<ArrayType const*>(memberType)->baseType().get();
if (StructType const* innerStruct = dynamic_cast<StructType const*>(memberType))
if (check(innerStruct))
return true;
}
return false;
};
return check(this);
}
TypePointer EnumType::unaryOperatorResult(Token::Value _operator) const
{
return _operator == Token::Delete ? make_shared<TupleType>() : TypePointer();