Merge pull request #824 from larsclausen/class-lifetime
Fix variable initialization in class methods
This commit is contained in:
commit
7b1fad78c3
|
|
@ -517,7 +517,14 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
|||
|
||||
hname_t use_name (cur->first);
|
||||
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::TASK);
|
||||
|
||||
// Task methods are always automatic...
|
||||
if (!cur->second->is_auto()) {
|
||||
cerr << "error: Lifetime of method `"
|
||||
<< scope_path(method_scope)
|
||||
<< "` must not be static" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
method_scope->is_auto(true);
|
||||
method_scope->set_line(cur->second);
|
||||
method_scope->add_imports(&cur->second->explicit_imports);
|
||||
|
|
@ -536,7 +543,14 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
|||
|
||||
hname_t use_name (cur->first);
|
||||
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::FUNC);
|
||||
|
||||
// Function methods are always automatic...
|
||||
if (!cur->second->is_auto()) {
|
||||
cerr << "error: Lifetime of method `"
|
||||
<< scope_path(method_scope)
|
||||
<< "` must not be static" << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
method_scope->is_auto(true);
|
||||
method_scope->set_line(cur->second);
|
||||
method_scope->add_imports(&cur->second->explicit_imports);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
// Check that specifing static lifetime for a class method taks results in an
|
||||
// error.
|
||||
|
||||
module test;
|
||||
|
||||
class C;
|
||||
// This should fail, all class methods have automatic lifetime
|
||||
task static t(int x);
|
||||
int y;
|
||||
y = 2 * x;
|
||||
endtask
|
||||
endclass
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Check that specifing static lifetime for a class method function results in
|
||||
// an error.
|
||||
|
||||
module test;
|
||||
|
||||
class C;
|
||||
// This should fail, all class methods have automatic lifetime
|
||||
function static int t(int x);
|
||||
int y;
|
||||
y = 2 * x;
|
||||
return y;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
initial begin
|
||||
$display("FAILED");
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// Check that variable initialization as part of the declaration works as
|
||||
// expected in class methods.
|
||||
|
||||
module test;
|
||||
class C;
|
||||
task t(bit check);
|
||||
int x = 10; // The initialization should happen on each invocation
|
||||
if (check) begin
|
||||
if (x === 10) begin
|
||||
$display("PASSED");
|
||||
end else begin
|
||||
$display("FAILED");
|
||||
end
|
||||
end
|
||||
x = 20;
|
||||
endtask
|
||||
endclass
|
||||
|
||||
initial begin
|
||||
C c;
|
||||
c = new;
|
||||
c.t(1'b0);
|
||||
c.t(1'b1);
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -565,8 +565,11 @@ sv_class_in_module_decl normal,-g2009 ivltests
|
|||
sv_class_method_call_void normal,-g2009 ivltests
|
||||
sv_class_method_default1 normal,-g2009 ivltests
|
||||
sv_class_method_default2 normal,-g2009 ivltests
|
||||
sv_class_method_lt_static1 CE,-g2009 ivltests
|
||||
sv_class_method_lt_static2 CE,-g2009 ivltests
|
||||
sv_class_method_signed1 normal,-g2009 ivltests
|
||||
sv_class_method_signed2 normal,-g2009 ivltests
|
||||
sv_class_method_var_init normal,-g2009 ivltests
|
||||
sv_class_property_signed1 normal,-g2009 ivltests
|
||||
sv_class_property_signed2 normal,-g2009 ivltests
|
||||
sv_class_property_signed3 normal,-g2009 ivltests
|
||||
|
|
|
|||
|
|
@ -422,6 +422,7 @@ sv_class_method_default1 CE,-g2009 ivltests
|
|||
sv_class_method_default2 CE,-g2009 ivltests
|
||||
sv_class_method_signed1 CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_class_method_signed2 CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_class_method_var_init CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_class_property_signed1 CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_class_property_signed2 CE,-g2009,-pallowsigned=1 ivltests
|
||||
sv_class_property_signed3 CE,-g2009,-pallowsigned=1 ivltests
|
||||
|
|
|
|||
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