diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 002b980c5..a4126dad0 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -1144,9 +1144,7 @@ public: string name() const override VL_MT_STABLE { return itemp()->name(); } int instrCount() const override { return 0; } const char* broken() const override; - void cloneRelink() override { - if (m_itemp->clonep()) m_itemp = m_itemp->clonep(); - } + void cloneRelink() override; bool same(const AstNode* samep) const override { const AstEnumItemRef* const sp = static_cast(samep); return itemp() == sp->itemp(); diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 507bcfbbc..7ba41a926 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1614,6 +1614,12 @@ const char* AstEnumItemRef::broken() const { BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); return nullptr; } +void AstEnumItemRef::cloneRelink() { + if (m_itemp->clonep()) m_itemp = m_itemp->clonep(); + if (m_classOrPackagep && m_classOrPackagep->clonep()) { + m_classOrPackagep = m_classOrPackagep->clonep(); + } +} void AstIfaceRefDType::dump(std::ostream& str) const { this->AstNodeDType::dump(str); if (cellName() != "") str << " cell=" << cellName(); diff --git a/test_regress/t/t_enum_param_class.pl b/test_regress/t/t_enum_param_class.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_enum_param_class.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 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(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_enum_param_class.v b/test_regress/t/t_enum_param_class.v new file mode 100644 index 000000000..c59f4b523 --- /dev/null +++ b/test_regress/t/t_enum_param_class.v @@ -0,0 +1,37 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Anthony Donlon. +// SPDX-License-Identifier: CC0-1.0 + +/// (See bug4551) +/// Verilator creates an AstEnumItemRef for each reference. If the enum is inside a parameterizable class/module, it +/// should be handled properly. + +class ClsParam #( + int A = 0 +); + typedef enum int { + EN_A = A + 0, + EN_B = A + 1, + EN_C = A + 2 + } enums_t; + + int val = EN_C; + function int test(); + return EN_C; + endfunction +endclass; + +module t; + // localparam ENUM_VAL = ClsParam#(100)::EN_C; // TODO: Unsupported: dotted expressions in parameters + // $info("ENUM_VAL: %0d", ENUM_VAL); + + ClsParam#(100) cls = new; + initial begin + if (cls.test() != 102) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule