From 29ae520e69c23e648f0a242c76ebd7a309153e9b Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 8 Dec 2025 20:11:28 -0500 Subject: [PATCH] Fix class param static not found again error (#6768). --- Changes | 1 + src/V3AstInlines.h | 10 +++++++-- src/V3AstNodeExpr.h | 5 +++++ src/V3AstNodes.cpp | 7 +++++- src/V3Param.cpp | 2 ++ src/V3WidthCommit.cpp | 2 ++ test_regress/t/t_class_param_static.py | 18 +++++++++++++++ test_regress/t/t_class_param_static.v | 31 ++++++++++++++++++++++++++ 8 files changed, 73 insertions(+), 3 deletions(-) create mode 100755 test_regress/t/t_class_param_static.py create mode 100644 test_regress/t/t_class_param_static.v diff --git a/Changes b/Changes index a3756424d..9ed46cec9 100644 --- a/Changes +++ b/Changes @@ -82,6 +82,7 @@ Verilator 5.043 devel * Fix `--lib-create` with multi-bit clocks (#6759). [Geza Lore] * Fix DFG reusing volatile variables. [Geza Lore] * Fix DFG assertion on out-of-bounds selects. [Geza Lore] +* Fix class param static not found again error (#6768). * Fix crash when super.new() called without a base class (#6772). [Matthew Ballance] * Fix class-in-class extends with parameters (#6773). * Fix enum item references in class extends with parameters. diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 1043bf4cd..691503b59 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -160,7 +160,13 @@ bool AstVar::sameNode(const AstNode* samep) const { } AstVarRef::AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access) - : ASTGEN_SUPER_VarRef(fl, varp, access) {} + : ASTGEN_SUPER_VarRef(fl, varp, access) { + if (v3Global.assertDTypesResolved()) { + UASSERT_OBJ(varp, this, "Require non-null varp post resolution"); + } else if (varp) { + m_name = varp->name(); + } +} AstVarRef::AstVarRef(FileLine* fl, AstNodeModule* pkgp, AstVar* varp, const VAccess& access) : AstVarRef{fl, varp, access} { classOrPackagep(pkgp); @@ -171,7 +177,7 @@ AstVarRef::AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access) varScopep(varscp); } -string AstVarRef::name() const { return varp() ? varp()->name() : ""; } +string AstVarRef::name() const { return varp() ? varp()->name() : nameThis(); } bool AstVarRef::sameNode(const AstVarRef* samep) const { if (varScopep()) { diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index b268bb154..aff2f64e5 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -1299,6 +1299,7 @@ public: ASTGEN_MEMBERS_AstEnumItemRef; void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; + const char* broken() const; string name() const override VL_MT_STABLE { return itemp() ? itemp()->name() : m_name; } int instrCount() const override { return 0; } bool sameNode(const AstNode* samep) const override { @@ -5694,6 +5695,8 @@ public: // === AstNodeVarRef === class AstVarRef final : public AstNodeVarRef { // A reference to a variable (lvalue or rvalue) + std::string m_name; // Name of varref, though name() favors varp()->namep() + // if non-null pointer (e.g.: 'this') public: // This form only allowed post-link because output/wire compression may // lead to deletion of AstVar's @@ -5703,7 +5706,9 @@ public: // This form only allowed post-link (see above) inline AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access); ASTGEN_MEMBERS_AstVarRef; + std::string nameThis() const { return m_name; } inline string name() const override; // * = Var name + void name(const string& name) override { m_name = name; } void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; const char* broken() const override; diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index b24a43252..9fb36d740 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1921,6 +1921,10 @@ string AstEnumDType::prettyDTypeName(bool full) const { result += "}" + prettyName(); return result; } +const char* AstEnumItemRef::broken() const { + if (v3Global.assertDTypesResolved()) BROKEN_RTN(!itemp()); + return nullptr; +} void AstEnumItemRef::dump(std::ostream& str) const { this->AstNodeExpr::dump(str); str << " -> "; @@ -2743,7 +2747,8 @@ void AstVarRef::dump(std::ostream& str) const { } void AstVarRef::dumpJson(std::ostream& str) const { dumpJsonGen(str); } const char* AstVarRef::broken() const { - BROKEN_RTN(!varp()); + // Even after assertDTypesResolved(), V3Scope will set varp() to null, but name won't be "" + BROKEN_RTN(!varp() && name().empty()); return nullptr; } bool AstVarRef::sameNode(const AstNode* samep) const { return sameNode(VN_DBG_AS(samep, VarRef)); } diff --git a/src/V3Param.cpp b/src/V3Param.cpp index d06687883..175eb248d 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -2007,6 +2007,8 @@ public: resortNetlistModules(netlistp); + V3Global::dumpCheckGlobalTree("param-predel", 0, dumpTreeEitherLevel() >= 9); + // Remove defaulted classes // Unlike modules, which we keep around and mark dead() for later V3Dead std::unordered_set removedClassps; diff --git a/src/V3WidthCommit.cpp b/src/V3WidthCommit.cpp index b77899522..1b32c275f 100644 --- a/src/V3WidthCommit.cpp +++ b/src/V3WidthCommit.cpp @@ -391,6 +391,8 @@ private: editDType(nodep); classEncapCheck(nodep, nodep->varp(), VN_CAST(nodep->classOrPackagep(), Class)); if (nodep->access().isWriteOrRW()) varLifetimeCheck(nodep, nodep->varp()); + if (VN_IS(nodep, VarRef)) + nodep->name(""); // Clear to save memory; nodep->name() will work via nodep->varp() } void visit(AstAssign* nodep) override { iterateChildren(nodep); diff --git a/test_regress/t/t_class_param_static.py b/test_regress/t/t_class_param_static.py new file mode 100755 index 000000000..f989a35fb --- /dev/null +++ b/test_regress/t/t_class_param_static.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_class_param_static.v b/test_regress/t/t_class_param_static.v new file mode 100644 index 000000000..9b92e9ac6 --- /dev/null +++ b/test_regress/t/t_class_param_static.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + + class uvm_sequence_library #( + type REQ = int, + RSP = int + ); + int sequences[$]; + endclass + + class Cls extends uvm_sequence_library; + + static int m_typewide_sequences[$]; + + function void init_sequence_library(); + foreach (m_typewide_sequences[i]) sequences.push_back(m_typewide_sequences[i]); + endfunction + endclass + + initial begin + Cls c; + c = new; + $finish; + end + +endmodule