Fix typedef of parameterized class for member access (#5977)

Defer RefDType resolution in linkDotPrimary when the classOrPackageRef
target is a typedef to a parameterized class. Previously only direct
class references were deferred, so `typedef outer_cls#(params) drv_t;
drv_t::beat_t x;` would resolve against the generic class which V3Param
later deletes.
This commit is contained in:
Leela Pakanati 2026-02-05 22:06:31 -06:00
parent 388fb9db2d
commit c2d3655569
4 changed files with 88 additions and 0 deletions

View File

@ -5310,6 +5310,11 @@ class LinkDotResolveVisitor final : public VNVisitor {
iterate(cpackagep);
return;
}
// Also defer if target is a typedef to a parameterized class (#5977)
if (m_statep->forPrimary() && isParamedClassRef(cpackagerefp)) {
iterate(cpackagep);
return;
}
if (!cpackagerefp->classOrPackageSkipp()) {
VSymEnt* const foundp = m_statep->resolveClassOrPackage(
m_ds.m_dotSymp, cpackagerefp, true, false, "class/package reference");

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,45 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Leela Pakanati
// SPDX-License-Identifier: CC0-1.0
// Test for issue #5977: Typedef of parameterized class for member access
// verilog_format: off
`define stop $stop
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
package pkg;
class cls_l0 #(parameter AW = 32);
logic [AW-1:0] addr;
function new();
addr = '0;
endfunction
endclass
class cls_l1 #(parameter int AW = 32);
typedef cls_l0 #(.AW(AW)) beat_t;
endclass
endpackage
module t;
// Typedef of parameterized class, then access member typedef via ::
typedef pkg::cls_l1 #(.AW(64)) drv64_t;
typedef pkg::cls_l1 #(.AW(128)) drv128_t;
initial begin
// Access class-type typedef member through module-level typedef
automatic drv64_t::beat_t item1 = new;
automatic drv128_t::beat_t item2 = new;
item1.addr = 64'hDEAD_BEEF_CAFE_BABE;
`checkd(item1.addr, 64'hDEAD_BEEF_CAFE_BABE);
`checkd($bits(item1.addr), 64);
`checkd($bits(item2.addr), 128);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,20 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.top_filename = "t/t_class_param_typedef8.v"
test.compile(verilator_flags2=['--binary', '-fno-inline'])
test.execute()
test.passes()