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:
parent
580d79eae3
commit
54a4e7ff0b
14
parse.y
14
parse.y
|
|
@ -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.
|
||||
|
|
|
|||
5
pform.cc
5
pform.cc
|
|
@ -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);
|
||||
|
|
|
|||
4
pform.h
4
pform.h
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue