From e0ec2ed3862cf00514c55653c5e597205f0aebc3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 19 Sep 2022 20:23:02 +0200 Subject: [PATCH 1/2] Do not allow to create objects of virtual classes It is not allowed to create objects of virtual classes. Currently the virtual keyword is accepted by the parser, but otherwise ignored. Keep track of whether a class is virtual and generate an error when the class new operator is used for a virtual type. Signed-off-by: Lars-Peter Clausen --- elab_expr.cc | 8 ++++++++ elab_scope.cc | 1 + netclass.h | 5 +++++ parse.y | 2 +- pform.h | 3 ++- pform_pclass.cc | 4 +++- pform_types.h | 2 ++ 7 files changed, 22 insertions(+), 3 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index acd599a25..464b549e7 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -6652,6 +6652,14 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope, return 0; } + if (ctype->is_virtual()) { + cerr << get_fileline() << ": error: " + << "Can not create object of virtual class `" + << ctype->get_name() << "`." << endl; + des->errors++; + return 0; + } + NetExpr*obj = new NetENew(ntype); obj->set_line(*this); diff --git a/elab_scope.cc b/elab_scope.cc index 1980eaf0d..bdab0b879 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -493,6 +493,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) class_scope->set_class_def(use_class); use_class->set_class_scope(class_scope); use_class->set_definition_scope(scope); + use_class->set_virtual(use_type->virtual_class); set_scope_timescale(des, class_scope, pclass); class_scope->add_typedefs(&pclass->typedefs); diff --git a/netclass.h b/netclass.h index af473ba71..0c598fe32 100644 --- a/netclass.h +++ b/netclass.h @@ -116,6 +116,9 @@ class netclass_t : public ivl_type_s { const NetExpr* get_parameter(Design *des, perm_string name, ivl_type_t &par_type) const; + void set_virtual(bool virtual_class) { virtual_class_ = virtual_class; } + bool is_virtual() const { return virtual_class_; } + private: perm_string name_; // If this is derived from another base class, point to it @@ -137,6 +140,8 @@ class netclass_t : public ivl_type_s { // This holds the context for the class type definition. NetScope*definition_scope_; + + bool virtual_class_; }; inline NetScope*netclass_t::definition_scope(void) diff --git a/parse.y b/parse.y index 79b4d4a35..409b359a8 100644 --- a/parse.y +++ b/parse.y @@ -797,7 +797,7 @@ class_declaration /* IEEE1800-2005: A.1.2 */ 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); + pform_start_class_declaration(@2, class_type, $5.type, $5.exprs, $3, $1); } class_items_opt K_endclass { // Process a class. diff --git a/pform.h b/pform.h index d2f44c293..be3e94918 100644 --- a/pform.h +++ b/pform.h @@ -173,7 +173,8 @@ extern void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type, std::list*base_exprs, - LexicalScope::lifetime_t lifetime); + LexicalScope::lifetime_t lifetime, + bool virtual_class); extern void pform_class_property(const struct vlltype&loc, property_qualifier_t pq, data_type_t*data_type, diff --git a/pform_pclass.cc b/pform_pclass.cc index f1692ad4f..c69c62c70 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -43,7 +43,8 @@ void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type, list*base_exprs, - LexicalScope::lifetime_t lifetime) + LexicalScope::lifetime_t lifetime, + bool virtual_class) { PClass*class_scope = pform_push_class_scope(loc, type->name, lifetime); class_scope->type = type; @@ -52,6 +53,7 @@ void pform_start_class_declaration(const struct vlltype&loc, assert(type->base_type == 0); type->base_type.reset(base_type); + type->virtual_class = virtual_class; assert(type->base_args.empty()); if (base_exprs) { diff --git a/pform_types.h b/pform_types.h index 3a44d696f..2300ce818 100644 --- a/pform_types.h +++ b/pform_types.h @@ -379,6 +379,8 @@ struct class_type_t : public data_type_t { std::unique_ptr base_type; std::listbase_args; + bool virtual_class; + // This is a map of the properties. Map the name to the type. struct prop_info_t : public LineInfo { inline prop_info_t() : qual(property_qualifier_t::make_none()) { } From 569ba887b374cec71169ee2773c3e569f0745da9 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Tue, 13 Dec 2022 21:27:09 -0800 Subject: [PATCH 2/2] Add regression test for creating instances of virtual classes Check that an error is reported when trying to create an object of a virtual class. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_class_virt_new_fail.v | 15 +++++++++++++++ ivtest/regress-sv.list | 1 + 2 files changed, 16 insertions(+) create mode 100644 ivtest/ivltests/sv_class_virt_new_fail.v diff --git a/ivtest/ivltests/sv_class_virt_new_fail.v b/ivtest/ivltests/sv_class_virt_new_fail.v new file mode 100644 index 000000000..8a5724594 --- /dev/null +++ b/ivtest/ivltests/sv_class_virt_new_fail.v @@ -0,0 +1,15 @@ +// Check that an error is reported when trying to create an object of a virtual +// class. + +module test; + + virtual class C; + endclass + + C c; + + initial begin + c = new; // This should fail + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index e9f4a5ad2..84c2b5642 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -554,6 +554,7 @@ sv_class_static_prop3 normal,-g2009 ivltests sv_class_super1 normal,-g2009 ivltests sv_class_super2 normal,-g2009 ivltests sv_class_task1 normal,-g2009 ivltests +sv_class_virt_new_fail CE,-g2009 ivltests sv_darray1 normal,-g2009 ivltests sv_darray2 normal,-g2009 ivltests sv_darray3 normal,-g2009 ivltests