diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 449a18c89..c9b036b80 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -3066,6 +3066,9 @@ class LinkDotResolveVisitor final : public VNVisitor { VL_RESTORER(m_ds); VL_RESTORER(m_pinSymp); + if (nodep->name() == "std" && !nodep->classOrPackagep()) { + nodep->classOrPackagep(v3Global.rootp()->stdPackagep()); + } // ClassRef's have pins, so track if (nodep->classOrPackagep()) { m_pinSymp = m_statep->getNodeSym(nodep->classOrPackagep()); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index e180141b6..d1e4a8b6b 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -45,7 +45,6 @@ class LinkParseVisitor final : public VNVisitor { using ImplTypedefMap = std::map, AstTypedef*>; // STATE - AstPackage* const m_stdPackagep; // SystemVerilog std package AstVar* m_varp = nullptr; // Variable we're under ImplTypedefMap m_implTypedef; // Created typedefs for each std::unordered_set m_filelines; // Filelines that have been seen @@ -192,9 +191,7 @@ class LinkParseVisitor final : public VNVisitor { if (!nodep->lifetime().isNone()) { m_lifetime = nodep->lifetime(); } else { - const AstClassOrPackageRef* const classPkgRefp - = VN_AS(nodep->classOrPackagep(), ClassOrPackageRef); - if (classPkgRefp && VN_IS(classPkgRefp->classOrPackageNodep(), Class)) { + if (nodep->classMethod()) { // Class methods are automatic by default m_lifetime = VLifetime::AUTOMATIC; } else if (nodep->dpiImport() || VN_IS(nodep, Property)) { @@ -841,10 +838,8 @@ class LinkParseVisitor final : public VNVisitor { VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } - void visit(AstClassOrPackageRef* nodep) override { - if (nodep->name() == "std" && !nodep->classOrPackagep()) { - nodep->classOrPackagep(m_stdPackagep); - } + void visit(AstClassOrPackageRef* nodep) override { // + iterateChildren(nodep); } void visit(AstClocking* nodep) override { cleanFileline(nodep); @@ -917,10 +912,7 @@ class LinkParseVisitor final : public VNVisitor { public: // CONSTRUCTORS - explicit LinkParseVisitor(AstNetlist* rootp) - : m_stdPackagep{rootp->stdPackagep()} { - iterate(rootp); - } + explicit LinkParseVisitor(AstNetlist* rootp) { iterate(rootp); } ~LinkParseVisitor() override { V3Stats::addStatSum(V3Stats::STAT_SOURCE_MODULES, m_statModules); } diff --git a/src/verilog.y b/src/verilog.y index 051893389..1be75e85f 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -4579,6 +4579,7 @@ taskId: | packageClassScope id { $$ = new AstTask{$$, *$2, nullptr}; $$->classOrPackagep($1); + $$->classMethod(true); SYMP->pushNewUnderNodeOrCurrent($$, $1); } ; @@ -4620,6 +4621,7 @@ funcIdNew: // IEEE: from class_constructor_declaration { $$ = new AstFunc{$2, "new", nullptr, nullptr}; $$->classOrPackagep($1); $$->isConstructor(true); + $$->classMethod(true); SYMP->pushNewUnderNodeOrCurrent($$, $1); } ; @@ -4640,6 +4642,7 @@ fIdScoped: // IEEE: part of function_body_declaration/task_ { $$ = $1; $$ = $1; $$ = new AstFunc{$$, *$2, nullptr, nullptr}; + $$->classMethod(true); $$->classOrPackagep($1); } ; diff --git a/test_regress/t/t_class_ref_bad.out b/test_regress/t/t_class_ref_bad.out new file mode 100644 index 000000000..d11276ec2 --- /dev/null +++ b/test_regress/t/t_class_ref_bad.out @@ -0,0 +1,4 @@ +%Error: Internal Error: t/t_class_ref_bad.v:15:11: ../V3LinkDot.cpp:#: Bad package link + 15 | s = ClsRigh::m_s; + | ^~~~~~~ + ... See the manual at https://verilator.org/verilator_doc.html for more assistance. diff --git a/test_regress/t/t_class_ref_bad.py b/test_regress/t/t_class_ref_bad.py new file mode 100755 index 000000000..31228c9a7 --- /dev/null +++ b/test_regress/t/t_class_ref_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_class_ref_bad.v b/test_regress/t/t_class_ref_bad.v new file mode 100644 index 000000000..ef22b6b6a --- /dev/null +++ b/test_regress/t/t_class_ref_bad.v @@ -0,0 +1,17 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class ClsRight; + string m_s; +endclass + +module t (/*AUTOARG*/); + string s; + initial begin + // verilator lint_off PKGNODECL + s = ClsRigh::m_s; // Bad typo + end +endmodule