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)
|
||||
: 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);
|
||||
|
|
|
|||
|
|
@ -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_fail2 CE,-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_method_call_void 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_localparam 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_method_call_void 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> 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
|
||||
|
|
@ -978,6 +979,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;
|
||||
|
|
@ -987,6 +991,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