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/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 37e53b4e9..c04b1ca67 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -555,6 +555,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 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()) { }