Fix chain call of abstract class constructor (#3868) (#3883)

This commit is contained in:
Ilya Barkov 2023-01-17 21:02:39 +03:00 committed by GitHub
parent 46cc7b5d07
commit ff2f711d0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 4 deletions

View File

@ -45,6 +45,7 @@ HungMingWu
HyungKi Jeong
Iru Cai
Ivan Vnučec
Ilya Barkov
Iztok Jeras
Jake Merdich
James Hanlon

View File

@ -3626,6 +3626,10 @@ private:
// Either made explicitly or V3LinkDot made implicitly
classp->v3fatalSrc("Can't find class's new");
}
if (classp->isVirtual()) {
nodep->v3error(
"Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21)");
}
} else { // super.new case
// in this case class and taskp() should be properly linked in V3LinkDot.cpp during
// "super" reference resolution
@ -3634,10 +3638,6 @@ private:
UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked taskp()");
nodep->dtypeFrom(nodep->taskp());
}
if (classp->isVirtual()) {
nodep->v3error(
"Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21)");
}
userIterate(nodep->taskp(), nullptr);
processFTaskRefArgs(nodep);
}

View File

@ -0,0 +1,16 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2023 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
lint();
ok(1);
1;

View File

@ -0,0 +1,34 @@
// DESCRIPTION: Verilator: Check that an abstract class' contstructor
// can be called indirectly from a constructor of a derived class.
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Ilya Barkov
// SPDX-License-Identifier: CC0-1.0
// It's illegal to call
// VBase b = new;
// see t_class_virtual_bad
virtual class VBase;
function new(); endfunction
endclass
// Another constructor of an abstact class in the chain
virtual class VChild1 extends VBase;
function new();
super.new();
endfunction
endclass
// It shall be perfectly fine to create an instance of a
// non-abstract VChild2
class VChild2 extends VChild1;
function new();
super.new();
endfunction
endclass
module t;
initial begin
VChild2 c = new;
end
endmodule