Merge pull request #825 from larsclausen/typed-constructor
Add support for typed constructor calls
This commit is contained in:
commit
cc2ba4f8cb
4
PExpr.cc
4
PExpr.cc
|
|
@ -488,8 +488,8 @@ PENewClass::PENewClass(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PENewClass::PENewClass(const list<PExpr*>&p)
|
PENewClass::PENewClass(const list<PExpr*>&p, data_type_t *class_type)
|
||||||
: parms_(p.size())
|
: parms_(p.size()), class_type_(class_type)
|
||||||
{
|
{
|
||||||
size_t tmp_idx = 0;
|
size_t tmp_idx = 0;
|
||||||
for (list<PExpr*>::const_iterator cur = p.begin()
|
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
|
// New without (or with default) constructor
|
||||||
explicit PENewClass ();
|
explicit PENewClass ();
|
||||||
// New with constructor arguments
|
// 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();
|
~PENewClass();
|
||||||
|
|
||||||
|
|
@ -577,6 +578,7 @@ class PENewClass : public PExpr {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<PExpr*>parms_;
|
std::vector<PExpr*>parms_;
|
||||||
|
data_type_t *class_type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PENewCopy : public PExpr {
|
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;
|
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()) {
|
if (ctype->is_virtual()) {
|
||||||
cerr << get_fileline() << ": error: "
|
cerr << get_fileline() << ": error: "
|
||||||
<< "Can not create object of virtual class `"
|
<< "Can not create object of virtual class `"
|
||||||
|
|
@ -6670,7 +6696,7 @@ NetExpr* PENewClass::elaborate_expr(Design*des, NetScope*scope,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr*obj = new NetENew(ntype);
|
NetExpr*obj = new NetENew(ctype);
|
||||||
obj->set_line(*this);
|
obj->set_line(*this);
|
||||||
|
|
||||||
obj = elaborate_expr_constructor_(des, scope, ctype, obj, flags);
|
obj = elaborate_expr_constructor_(des, scope, ctype, obj, flags);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Check that typed constructor calls are supported.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class C;
|
||||||
|
function new;
|
||||||
|
$display("PASSED");
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
C c;
|
||||||
|
c = C::new;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Check that typed constructor calls are supported when assigning to an
|
||||||
|
// variable of a base class type.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class B;
|
||||||
|
int x = 0;
|
||||||
|
|
||||||
|
task check;
|
||||||
|
if (x === 10) begin
|
||||||
|
$display("PASSED");
|
||||||
|
end else begin
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
endtask
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class C extends B;
|
||||||
|
function new;
|
||||||
|
x = 10;
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
B b;
|
||||||
|
b = C::new;
|
||||||
|
b.check;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Check that typed constructor calls are supported when the type is a typedef
|
||||||
|
// of a class type.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class C;
|
||||||
|
function new;
|
||||||
|
$display("PASSED");
|
||||||
|
endfunction
|
||||||
|
endclass
|
||||||
|
|
||||||
|
typedef C T;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
T c;
|
||||||
|
c = T::new;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Check that an error is reported when using a typed constructor call to assign
|
||||||
|
// to a class that is not a base class.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class B;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class C;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
B b;
|
||||||
|
b = C::new; // This should fail, B is not a base class of C
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Check that an error is reported when using a typed constructor call to assign
|
||||||
|
// to a class that is an inherited class.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class B;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class C extends B;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
C c;
|
||||||
|
c = B::new; // This should fail, B is a base class of C, but C is not a
|
||||||
|
// base class of B.
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Check that an error is reported when using a typed constructor call to assign
|
||||||
|
// to a class that has a common base class, but is not directly related.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class B;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class C extends B;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
class D extends B;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
D d;
|
||||||
|
d = C::new; // This should fail, C and D share a common base class, but are
|
||||||
|
// not compatible
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Check that an error is reported when trying to use a typed constructor call
|
||||||
|
// with a type that is not a class.
|
||||||
|
|
||||||
|
module test;
|
||||||
|
|
||||||
|
class C;
|
||||||
|
endclass
|
||||||
|
|
||||||
|
typedef int T;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
C c;
|
||||||
|
c = T::new; // This should fail, T is not a class
|
||||||
|
$display("FAILED");
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
@ -561,6 +561,13 @@ sv_class_localparam normal,-g2009 ivltests
|
||||||
sv_class_new_fail1 CE,-g2009 ivltests
|
sv_class_new_fail1 CE,-g2009 ivltests
|
||||||
sv_class_new_fail2 CE,-g2009 ivltests
|
sv_class_new_fail2 CE,-g2009 ivltests
|
||||||
sv_class_new_init normal,-g2009 ivltests
|
sv_class_new_init normal,-g2009 ivltests
|
||||||
|
sv_class_new_typed1 normal,-g2009 ivltests
|
||||||
|
sv_class_new_typed2 normal,-g2009 ivltests
|
||||||
|
sv_class_new_typed3 normal,-g2009 ivltests
|
||||||
|
sv_class_new_typed_fail1 CE,-g2009 ivltests
|
||||||
|
sv_class_new_typed_fail2 CE,-g2009 ivltests
|
||||||
|
sv_class_new_typed_fail3 CE,-g2009 ivltests
|
||||||
|
sv_class_new_typed_fail4 CE,-g2009 ivltests
|
||||||
sv_class_in_module_decl normal,-g2009 ivltests
|
sv_class_in_module_decl normal,-g2009 ivltests
|
||||||
sv_class_method_call_void normal,-g2009 ivltests
|
sv_class_method_call_void normal,-g2009 ivltests
|
||||||
sv_class_method_default1 normal,-g2009 ivltests
|
sv_class_method_default1 normal,-g2009 ivltests
|
||||||
|
|
|
||||||
|
|
@ -416,6 +416,9 @@ sv_class_empty_item CE,-g2009 ivltests
|
||||||
sv_class_extends_scoped CE,-g2009 ivltests
|
sv_class_extends_scoped CE,-g2009 ivltests
|
||||||
sv_class_localparam CE,-g2009 ivltests
|
sv_class_localparam CE,-g2009 ivltests
|
||||||
sv_class_new_init CE,-g2009 ivltests
|
sv_class_new_init CE,-g2009 ivltests
|
||||||
|
sv_class_new_typed1 CE,-g2009 ivltests
|
||||||
|
sv_class_new_typed2 CE,-g2009 ivltests
|
||||||
|
sv_class_new_typed3 CE,-g2009 ivltests
|
||||||
sv_class_in_module_decl CE,-g2009 ivltests
|
sv_class_in_module_decl CE,-g2009 ivltests
|
||||||
sv_class_method_call_void CE,-g2009 ivltests
|
sv_class_method_call_void CE,-g2009 ivltests
|
||||||
sv_class_method_default1 CE,-g2009 ivltests
|
sv_class_method_default1 CE,-g2009 ivltests
|
||||||
|
|
|
||||||
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> packed_array_data_type
|
||||||
%type <data_type> ps_type_identifier
|
%type <data_type> ps_type_identifier
|
||||||
%type <data_type> simple_packed_type
|
%type <data_type> simple_packed_type
|
||||||
|
%type <data_type> class_scope
|
||||||
%type <struct_member> struct_union_member
|
%type <struct_member> struct_union_member
|
||||||
%type <struct_members> struct_union_member_list
|
%type <struct_members> struct_union_member_list
|
||||||
%type <struct_type> struct_data_type
|
%type <struct_type> struct_data_type
|
||||||
|
|
@ -978,6 +979,9 @@ class_item_qualifier_opt
|
||||||
| { $$ = property_qualifier_t::make_none(); }
|
| { $$ = property_qualifier_t::make_none(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
class_scope
|
||||||
|
: ps_type_identifier K_SCOPE_RES { $$ = $1; }
|
||||||
|
|
||||||
class_new /* IEEE1800-2005 A.2.4 */
|
class_new /* IEEE1800-2005 A.2.4 */
|
||||||
: K_new argument_list_parens_opt
|
: K_new argument_list_parens_opt
|
||||||
{ std::list<PExpr*>*expr_list = $2;
|
{ std::list<PExpr*>*expr_list = $2;
|
||||||
|
|
@ -987,6 +991,16 @@ class_new /* IEEE1800-2005 A.2.4 */
|
||||||
delete $2;
|
delete $2;
|
||||||
$$ = tmp;
|
$$ = 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
|
| K_new hierarchy_identifier
|
||||||
{ PEIdent*tmpi = new PEIdent(*$2);
|
{ PEIdent*tmpi = new PEIdent(*$2);
|
||||||
FILE_NAME(tmpi, @2);
|
FILE_NAME(tmpi, @2);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue