Add support for typed constructor calls
By default when creating a new class object the type of the object is determined by the type of the target. SystemVerilog also allows to explicitly specify the type of the object to be created. The specified class still needs to be assignment compatible with the target. This is e.g. useful to construct an object of a derived class of the target. E.g. ``` class B; ... endclass class C extends B; ... endclass B b; b = C::new; ``` Add support for this to the parser as well as handling it during elaboration. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
580d79eae3
commit
df82410a37
4
PExpr.cc
4
PExpr.cc
|
|
@ -488,8 +488,8 @@ PENewClass::PENewClass(void)
|
|||
{
|
||||
}
|
||||
|
||||
PENewClass::PENewClass(const list<PExpr*>&p)
|
||||
: parms_(p.size())
|
||||
PENewClass::PENewClass(const list<PExpr*>&p, data_type_t *class_type)
|
||||
: parms_(p.size()), class_type_(class_type)
|
||||
{
|
||||
size_t tmp_idx = 0;
|
||||
for (list<PExpr*>::const_iterator cur = p.begin()
|
||||
|
|
|
|||
4
PExpr.h
4
PExpr.h
|
|
@ -555,7 +555,8 @@ class PENewClass : public PExpr {
|
|||
// New without (or with default) constructor
|
||||
explicit PENewClass ();
|
||||
// New with constructor arguments
|
||||
explicit PENewClass (const std::list<PExpr*>&p);
|
||||
explicit PENewClass (const std::list<PExpr*>&p,
|
||||
data_type_t *class_type = nullptr);
|
||||
|
||||
~PENewClass();
|
||||
|
||||
|
|
@ -577,6 +578,7 @@ class PENewClass : public PExpr {
|
|||
|
||||
private:
|
||||
std::vector<PExpr*>parms_;
|
||||
data_type_t *class_type_;
|
||||
};
|
||||
|
||||
class PENewCopy : public PExpr {
|
||||
|
|
|
|||
28
elab_expr.cc
28
elab_expr.cc
|
|
@ -6662,6 +6662,32 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (class_type_) {
|
||||
ivl_type_t elab_class_type = class_type_->elaborate_type(des,
|
||||
scope);
|
||||
ctype = dynamic_cast<const netclass_t*> (elab_class_type);
|
||||
if (!ctype) {
|
||||
cerr << get_fileline() << ": error: Incompatible type in"
|
||||
<< " typed constructor call.\n"
|
||||
<< get_fileline() << ": : Constructor type `"
|
||||
<< *elab_class_type << "` is not a class type."
|
||||
<< endl;
|
||||
des->errors++;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!ntype->type_compatible(ctype)) {
|
||||
cerr << get_fileline() << ": error: Incompatible type in"
|
||||
<< " typed constructor call.\n"
|
||||
<< get_fileline() << ": : Constructor type `"
|
||||
<< *ctype
|
||||
<< "` is not compatible with the target type `"
|
||||
<< *ntype << "`." << endl;
|
||||
des->errors++;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (ctype->is_virtual()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Can not create object of virtual class `"
|
||||
|
|
@ -6670,7 +6696,7 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*obj = new NetENew(ntype);
|
||||
NetExpr*obj = new NetENew(ctype);
|
||||
obj->set_line(*this);
|
||||
|
||||
obj = elaborate_expr_constructor_(des, scope, ctype, obj, flags);
|
||||
|
|
|
|||
14
parse.y
14
parse.y
|
|
@ -652,6 +652,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
|
|||
%type <data_type> packed_array_data_type
|
||||
%type <data_type> ps_type_identifier
|
||||
%type <data_type> simple_packed_type
|
||||
%type <data_type> class_scope
|
||||
%type <struct_member> struct_union_member
|
||||
%type <struct_members> struct_union_member_list
|
||||
%type <struct_type> struct_data_type
|
||||
|
|
@ -968,6 +969,9 @@ class_item_qualifier_opt
|
|||
| { $$ = property_qualifier_t::make_none(); }
|
||||
;
|
||||
|
||||
class_scope
|
||||
: ps_type_identifier K_SCOPE_RES { $$ = $1; }
|
||||
|
||||
class_new /* IEEE1800-2005 A.2.4 */
|
||||
: K_new argument_list_parens_opt
|
||||
{ std::list<PExpr*>*expr_list = $2;
|
||||
|
|
@ -977,6 +981,16 @@ class_new /* IEEE1800-2005 A.2.4 */
|
|||
delete $2;
|
||||
$$ = tmp;
|
||||
}
|
||||
// This can't be a class_scope_opt because it will lead to shift/reduce
|
||||
// conflicts with array_new
|
||||
| class_scope K_new argument_list_parens_opt
|
||||
{ std::list<PExpr*>*expr_list = $3;
|
||||
strip_tail_items(expr_list);
|
||||
PENewClass *new_expr = new PENewClass(*expr_list, $1);
|
||||
FILE_NAME(new_expr, @2);
|
||||
delete $3;
|
||||
$$ = new_expr;
|
||||
}
|
||||
| K_new hierarchy_identifier
|
||||
{ PEIdent*tmpi = new PEIdent(*$2);
|
||||
FILE_NAME(tmpi, @2);
|
||||
|
|
|
|||
Loading…
Reference in New Issue