diff options
Diffstat (limited to 'AST.cpp')
-rw-r--r-- | AST.cpp | 36 |
1 files changed, 35 insertions, 1 deletions
@@ -51,6 +51,40 @@ void StructDefinition::accept(ASTVisitor& _visitor) _visitor.endVisit(*this); } +void StructDefinition::checkValidityOfMembers() +{ + checkMemberTypes(); + checkRecursion(); +} + +void StructDefinition::checkMemberTypes() +{ + for (ASTPointer<VariableDeclaration> const& member: getMembers()) + if (!member->getType()->canBeStored()) + BOOST_THROW_EXCEPTION(member->createTypeError("Type cannot be used in struct.")); +} + +void StructDefinition::checkRecursion() +{ + set<StructDefinition const*> definitionsSeen; + vector<StructDefinition const*> queue = {this}; + while (!queue.empty()) + { + 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 (member->getType()->getCategory() == Type::Category::STRUCT) + { + UserDefinedTypeName const& typeName = dynamic_cast<UserDefinedTypeName&>(*member->getTypeName()); + queue.push_back(&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration())); + } + } +} + void ParameterList::accept(ASTVisitor& _visitor) { if (_visitor.visit(*this)) @@ -258,7 +292,7 @@ void Literal::accept(ASTVisitor& _visitor) _visitor.endVisit(*this); } -TypeError ASTNode::createTypeError(string const& _description) +TypeError ASTNode::createTypeError(string const& _description) const { return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description); } |