Fix crash on sub-interface method call via a virtual interface

This commit is contained in:
Yilou Wang 2026-06-18 11:23:03 +02:00
parent d84af81a11
commit ed143a6cc2
4 changed files with 64 additions and 0 deletions

View File

@ -4782,6 +4782,15 @@ class WidthVisitor final : public VNVisitor {
}
void methodCallIfaceRef(AstMethodCall* nodep, AstIfaceRefDType* adtypep) {
AstIface* const ifacep = adtypep->ifacep();
if (!ifacep) {
// A sub-interface reached through a virtual interface handle has a
// ref dtype with cellp set but ifacep null; the per-instance binding
// is not modelled, so the call cannot be resolved to one instance.
nodep->v3warn(E_UNSUPPORTED, "Unsupported: method call on a sub-interface "
"accessed through a virtual interface");
nodep->dtypeSetVoid();
return;
}
UINFO(5, __FUNCTION__ << ":" << nodep);
if (AstNodeFTask* const ftaskp
= VN_CAST(m_memberMap.findMember(ifacep, nodep->name()), NodeFTask)) {

View File

@ -0,0 +1,6 @@
%Error-UNSUPPORTED: t/t_interface_virtual_sub_iface_method_bad.v:21:16: Unsupported: method call on a sub-interface accessed through a virtual interface
: ... note: In instance 't'
21 | vif.sub_if.set_active();
| ^~~~~~~~~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -0,0 +1,16 @@
#!/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('linter')
test.lint(fails=True, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,33 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0
interface inner_if;
logic active = 1'b0;
function automatic void set_active();
active = 1'b1;
endfunction
endinterface
interface outer_if;
inner_if sub_if ();
endinterface
class cfg_c;
virtual outer_if vif;
function void doit();
vif.sub_if.set_active();
endfunction
endclass
module t;
outer_if oif ();
cfg_c cfg;
initial begin
cfg = new();
cfg.vif = oif;
cfg.doit();
end
endmodule