Detect circular type definitions

With forward type declarations it is possible to create a circular type
definition where a type resolves to itself. E.g.

```
typedef T1;
typedef T1 T2;
typedef T2 T1;
```

Flag a type as elaborating when elaboration of the type is started and
clear it when elaboration finishes. If the elaboration function is entered
again while the flag is still set a circular type has been detected and an
error is reported.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-04-15 11:38:08 +02:00
parent 2e0d6d5af1
commit 8ee9d6b5ea
2 changed files with 16 additions and 1 deletions

View File

@ -49,7 +49,20 @@ ivl_type_t data_type_t::elaborate_type(Design*des, NetScope*scope)
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
return pos->second;
ivl_type_t tmp = elaborate_type_raw(des, scope);
ivl_type_t tmp;
if (elaborating) {
des->errors++;
cerr << get_fileline() << ": error: "
<< "Circular type definition found involving `" << *this << "`."
<< endl;
// Try to recover
tmp = netvector_t::integer_type();
} else {
elaborating = true;
tmp = elaborate_type_raw(des, scope);
elaborating = false;
}
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_t>(scope, tmp));
return tmp;
}

View File

@ -167,6 +167,8 @@ class data_type_t : public PNamedItem {
virtual ivl_type_t elaborate_type_raw(Design*des, NetScope*scope) const;
virtual NetScope *find_scope(Design* des, NetScope *scope) const;
bool elaborating = false;
// Keep per-scope elaboration results cached.
std::map<Definitions*,ivl_type_t> cache_type_elaborate_;
};