diff --git a/elab_scope.cc b/elab_scope.cc index 5f8d980e0..d8072ec04 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -336,8 +336,7 @@ static void blend_class_constructors(PClass*pclass) // If we do not have an explicit constructor chain, but there // is a parent class, then create an implicit chain. if (chain_new==0 && pclass->type->base_type!=0) { - listtmp_parms; - chain_new = new PChainConstructor(tmp_parms); + chain_new = new PChainConstructor(pclass->type->base_args); chain_new->set_line(*pclass); } diff --git a/parse.y b/parse.y index fbcded31f..29c3ea978 100644 --- a/parse.y +++ b/parse.y @@ -418,6 +418,11 @@ static void current_function_set_statement(const YYLTYPE&loc, vector property_qualifier_t property_qualifier; PPackage*package; + struct { + data_type_t*type; + list*exprs; + } class_declaration_extends; + verinum* number; verireal* realtime; @@ -591,12 +596,13 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type list_of_variable_decl_assignments %type data_type data_type_or_implicit data_type_or_implicit_or_void -%type class_declaration_extends_opt %type class_identifier %type struct_union_member %type struct_union_member_list %type struct_data_type +%type class_declaration_extends_opt + %type class_item_qualifier property_qualifier %type class_item_qualifier_list property_qualifier_list %type class_item_qualifier_opt property_qualifier_opt @@ -683,7 +689,7 @@ assignment_pattern /* IEEE1800-2005: A.6.7.1 */ class_declaration /* IEEE1800-2005: A.1.2 */ : K_virtual_opt K_class class_identifier class_declaration_extends_opt ';' - { pform_start_class_declaration(@2, $3, $4); } + { pform_start_class_declaration(@2, $3, $4.type, $4.exprs); } class_items_opt K_endclass { // Process a class. pform_end_class_declaration(@8); @@ -751,9 +757,15 @@ class_declaration_endlabel_opt class_declaration_extends_opt /* IEEE1800-2005: A.1.2 */ : K_extends TYPE_IDENTIFIER - { $$ = $2; } + { $$.type = $2; + $$.exprs= 0; + } + | K_extends TYPE_IDENTIFIER '(' expression_list_with_nuls ')' + { $$.type = $2; + $$.exprs = $4; + } | - { $$ = 0; } + { $$.type = 0; $$.exprs = 0; } ; /* The class_items_opt and class_items rules together implement the diff --git a/pform.h b/pform.h index 70db36c87..420f437bd 100644 --- a/pform.h +++ b/pform.h @@ -182,7 +182,8 @@ extern void pform_endmodule(const char*, bool inside_celldefine, extern void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, - data_type_t*base_type); + data_type_t*base_type, + std::list*base_exprs); extern void pform_class_property(const struct vlltype&loc, property_qualifier_t pq, data_type_t*data_type, diff --git a/pform_dump.cc b/pform_dump.cc index 845fa5477..26d8c5b98 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -180,10 +180,22 @@ void struct_type_t::pform_dump(ostream&out, unsigned indent) const void class_type_t::pform_dump(ostream&out, unsigned indent) const { - out << setw(indent) << "" << "class " << name << " {"; + out << setw(indent) << "" << "class " << name; - if (base_type) out << " (extends)"; + if (base_type) out << " extends "; + if (base_args.size() > 0) { + out << " ("; + for (list::const_iterator cur = base_args.begin() + ; cur != base_args.end() ; ++cur) { + const PExpr*curp = *cur; + if (cur != base_args.begin()) + out << ", "; + curp->dump(out); + } + out << ")"; + } + out << " {"; for (map::const_iterator cur = properties.begin() ; cur != properties.end() ; ++cur) { out << " " << cur->first; diff --git a/pform_pclass.cc b/pform_pclass.cc index f3da71dda..3b7b94d59 100644 --- a/pform_pclass.cc +++ b/pform_pclass.cc @@ -26,7 +26,17 @@ */ static PClass*pform_cur_class = 0; -void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type) +/* + * The base_type is set to the base class if this declaration is + * starting a derived class. For example, for the syntax: + * + * class foo extends bar (exprs) ... + * + * the base_type is the type of the class "bar", and the base_exprs, + * if present, are the "exprs" that would be passed to a chained + * constructor. + */ +void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type, list*base_exprs) { PClass*class_scope = pform_push_class_scope(loc, type->name); class_scope->type = type; @@ -35,6 +45,15 @@ void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, assert(type->base_type == 0); type->base_type = base_type; + + assert(type->base_args.size() == 0); + if (base_exprs) { + for (list::iterator cur = base_exprs->begin() + ; cur != base_exprs->end() ; ++ cur) { + type->base_args.push_back(*cur); + } + delete base_exprs; + } } void pform_class_property(const struct vlltype&loc, diff --git a/pform_types.h b/pform_types.h index 5619e6d39..84700275c 100644 --- a/pform_types.h +++ b/pform_types.h @@ -235,8 +235,10 @@ struct class_type_t : public data_type_t { // This is the named type that is supposed to be the base // class that we are extending. This is nil if there is no - // hierarchy. + // hierarchy. If there are arguments to the base class, then + // put them in the base_args vector. data_type_t*base_type; + std::listbase_args; // This is a map of the properties. Map the name to the type. struct prop_info_t {