Fix variable initialization in class methods

Up to 1800-2017 the grammar in the LRM allowed an optional lifetime
qualifier for class declarations. Icarus supports this and uses this as the
default lifetime for methods of the class. But the LRM never specified what
this qualifier should do actually actually. Starting with 1800-2023 the
qualifier will be removed from the grammar[1].

Furthermore the LRM states that methods of a class are supposed to have
automatic storage and static storage is forbidden.

This currently works in Icarus for the most part since the liftime attached
to class methods is ignored during elaboration in most places. Where it
does not work is for variable initializers where it results in broken code
being generated and vvp crashes at runtime. E.g.

```
class C;
  task t;
    int x = 10;
  endtask
endclass
```

Keep the optional lifetime qualifier for classes in the grammar for now, to
ensure backwards compatibility in case somebody is actually using it. But
ignore it and print a warning if it is specified.

In addition set the default lifetime for all classes to automatic. This
makes sure that variable initialization in classes works as expected.

[1] https://accellera.mantishub.io/view.php?id=3561

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-12-18 15:55:09 -08:00
parent 580d79eae3
commit 54a4e7ff0b
4 changed files with 16 additions and 10 deletions

14
parse.y
View File

@ -796,12 +796,22 @@ block_identifier_opt /* */
class_declaration /* IEEE1800-2005: A.1.2 */
: K_virtual_opt K_class lifetime_opt identifier_name class_declaration_extends_opt ';'
{
{ /* Up to 1800-2017 the grammar in the LRM allowed an optional lifetime
* qualifier for class declarations. But the LRM never specified what
* this qualifier should do. Starting with 1800-2023 the qualifier has
* been removed from the grammar. Allow it for backwards compatibility,
* but print a warning.
*/
if ($3 != LexicalScope::INHERITED) {
cerr << @1 << ": warning: Class lifetime qualifier is deprecated "
"and has no effect." << endl;
warn_count += 1;
}
perm_string name = lex_strings.make($4);
class_type_t *class_type= new class_type_t(name);
FILE_NAME(class_type, @4);
pform_set_typedef(@4, name, class_type, nullptr);
pform_start_class_declaration(@2, class_type, $5.type, $5.exprs, $3, $1);
pform_start_class_declaration(@2, class_type, $5.type, $5.exprs, $1);
}
class_items_opt K_endclass
{ // Process a class.

View File

@ -602,11 +602,10 @@ static void pform_set_scope_timescale(PScope*scope, const PScope*parent)
scope->time_prec_is_default = parent->time_prec_is_default;
}
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime)
PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name)
{
PClass*class_scope = new PClass(name, lexical_scope);
class_scope->default_lifetime = find_lifetime(lifetime);
class_scope->default_lifetime = LexicalScope::AUTOMATIC;
FILE_NAME(class_scope, loc);
PScopeExtra*scopex = find_nearest_scopex(lexical_scope);

View File

@ -173,7 +173,6 @@ extern void pform_start_class_declaration(const struct vlltype&loc,
class_type_t*type,
data_type_t*base_type,
std::list<PExpr*>*base_exprs,
LexicalScope::lifetime_t lifetime,
bool virtual_class);
extern void pform_class_property(const struct vlltype&loc,
property_qualifier_t pq,
@ -241,8 +240,7 @@ extern void pform_pop_scope();
*/
extern LexicalScope* pform_peek_scope();
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
LexicalScope::lifetime_t lifetime);
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name);
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);

View File

@ -43,10 +43,9 @@ void pform_start_class_declaration(const struct vlltype&loc,
class_type_t*type,
data_type_t*base_type,
list<PExpr*>*base_exprs,
LexicalScope::lifetime_t lifetime,
bool virtual_class)
{
PClass*class_scope = pform_push_class_scope(loc, type->name, lifetime);
PClass*class_scope = pform_push_class_scope(loc, type->name);
class_scope->type = type;
assert(pform_cur_class == 0);
pform_cur_class = class_scope;