mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Check for recursive structs.
This commit is contained in:
parent
2e72bd163a
commit
59ea19b3b9
@ -546,7 +546,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
||||
if (!type(*var)->canLiveOutsideStorage())
|
||||
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
|
||||
if (_function.visibility() >= FunctionDefinition::Visibility::Public && !(type(*var)->interfaceType(isLibraryFunction)))
|
||||
m_errorReporter.fatalTypeError(var->location(), "Internal type is not allowed for public or external functions.");
|
||||
m_errorReporter.fatalTypeError(var->location(), "Internal or recursive type is not allowed for public or external functions.");
|
||||
|
||||
var->accept(*this);
|
||||
}
|
||||
@ -641,7 +641,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
|
||||
_variable.visibility() >= VariableDeclaration::Visibility::Public &&
|
||||
!FunctionType(_variable).interfaceFunctionType()
|
||||
)
|
||||
m_errorReporter.typeError(_variable.location(), "Internal type is not allowed for public state variables.");
|
||||
m_errorReporter.typeError(_variable.location(), "Internal or recursive type is not allowed for public state variables.");
|
||||
|
||||
if (varType->category() == Type::Category::Array)
|
||||
if (auto arrayType = dynamic_cast<ArrayType const*>(varType.get()))
|
||||
@ -728,7 +728,7 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
|
||||
if (!type(*var)->canLiveOutsideStorage())
|
||||
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
|
||||
if (!type(*var)->interfaceType(false))
|
||||
m_errorReporter.typeError(var->location(), "Internal type is not allowed as event parameter type.");
|
||||
m_errorReporter.typeError(var->location(), "Internal or recursive type is not allowed as event parameter type.");
|
||||
}
|
||||
if (_eventDef.isAnonymous() && numIndexed > 4)
|
||||
m_errorReporter.typeError(_eventDef.location(), "More than 4 indexed arguments for anonymous event.");
|
||||
|
@ -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();
|
||||
|
@ -758,6 +758,10 @@ public:
|
||||
/// @returns the set of all members that are removed in the memory version (typically mappings).
|
||||
std::set<std::string> membersMissingInMemory() const;
|
||||
|
||||
/// @returns true if the same struct is used recursively in one of its members. Only
|
||||
/// analyses the "memory" representation, i.e. mappings are ignored in all structs.
|
||||
bool recursive() const;
|
||||
|
||||
private:
|
||||
StructDefinition const& m_struct;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user