Fix class initial-automatic insertion order (#7086 repair)

This commit is contained in:
Wilson Snyder 2026-02-25 19:01:19 -05:00
parent d658517715
commit 22290a74c2
3 changed files with 98 additions and 7 deletions

View File

@ -291,18 +291,23 @@ private:
iterateChildren(nodep);
}
UASSERT_OBJ(m_ctorp, nodep, "class constructor missing"); // LinkDot always makes it
AstNode* insertp = nullptr;
for (AstInitialAutomatic* initialp : m_initialps) {
if (AstNode* const newp = initialp->stmtsp()) {
newp->unlinkFrBackWithNext();
if (!m_ctorp->stmtsp()) {
m_ctorp->addStmtsp(newp);
} else {
m_ctorp->stmtsp()->addHereThisAsNext(newp);
}
if (AstNode* const movep = initialp->stmtsp()) {
movep->unlinkFrBackWithNext();
// Next InitialAutomatic must go in order after what we inserted
insertp = AstNode::addNextNull(insertp, movep);
}
VL_DO_DANGLING(pushDeletep(initialp->unlinkFrBack()), initialp);
}
m_initialps.clear();
if (insertp) {
if (!m_ctorp->stmtsp()) {
m_ctorp->addStmtsp(insertp);
} else {
m_ctorp->stmtsp()->addHereThisAsNext(insertp);
}
}
}
void visit(AstInitialAutomatic* nodep) override {
m_initialps.push_back(nodep);

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()
test.execute()
test.passes()

View File

@ -0,0 +1,68 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`define checks(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got='%s' exp='%s'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
module t;
class uvm_coreservice;
static uvm_coreservice inst;
function new(string name);
endfunction
static function uvm_coreservice get();
if (inst == null) begin
inst = new("cs-base");
end
return inst;
endfunction
virtual function string get_factory();
return "factory";
endfunction
endclass
class uvm_test;
string m_name;
string s0 = {m_name, "0"}; // Before new(); this must get "0" not "name0"
function new(string name);
m_name = name;
endfunction
endclass
class test extends uvm_test;
string s1 = {s0, "1"};
string s2 = {s1, "2"};
uvm_coreservice cs = uvm_coreservice::get();
// Below assumes that the above 'cs' executes first.
// Most simulators require this ordering, but some allow arbitrary order
// This would require dataflow analysis, so for now Verilator requires user ordering
string factory = cs.get_factory();
function new(string name);
super.new(name);
endfunction
endclass
initial begin
test t;
string s;
t = new("test");
`checks(t.s0, "0");
`checks(t.s1, "01");
`checks(t.s2, "012");
s = t.factory;
`checks(s, "factory");
$finish;
end
endmodule