diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 1b39283f8..a654141b8 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -779,14 +779,51 @@ public: if (!foundp) baddot = dotname; return foundp; } + static bool checkIfClassOrPackage(const VSymEnt* const symp) { + if (VN_IS(symp->nodep(), Class) || VN_IS(symp->nodep(), Package)) return true; + const AstRefDType* refDTypep = nullptr; + if (const AstTypedef* const typedefp = VN_CAST(symp->nodep(), Typedef)) { + if (VN_IS(typedefp->childDTypep(), ClassRefDType)) return true; + if (const AstRefDType* const refp = VN_CAST(typedefp->childDTypep(), RefDType)) { + refDTypep = refp; + } + } else if (const AstParamTypeDType* const paramTypep + = VN_CAST(symp->nodep(), ParamTypeDType)) { + if (const AstRequireDType* const requireDTypep + = VN_CAST(paramTypep->childDTypep(), RequireDType)) { + if (const AstRefDType* const refp = VN_CAST(requireDTypep->lhsp(), RefDType)) { + refDTypep = refp; + } else if (VN_IS(requireDTypep->lhsp(), VoidDType) + || VN_IS(requireDTypep->lhsp(), BasicDType) + || VN_IS(requireDTypep->lhsp(), ClassRefDType)) { + return true; + } + } + } + // TODO: this should be handled properly - case when it is known what type is + // referenced by AstRefDType (refDTypep->typeofp() is null or + // refDTypep->classOrPackageOpp() is null) + if (refDTypep && !refDTypep->typeofp() && !refDTypep->classOrPackageOpp()) { + // When still unknown - return because it may be a class, classes may not be + // linked at this point. Return in case it gets resolved to a class in the future + return true; + } + return false; + } VSymEnt* resolveClassOrPackage(VSymEnt* lookSymp, AstClassOrPackageRef* nodep, bool fallback, bool classOnly, const string& forWhat) { if (nodep->classOrPackageSkipp()) return getNodeSym(nodep->classOrPackageSkipp()); VSymEnt* foundp; if (fallback) { - foundp = lookSymp->findIdFallback(nodep->name()); + VSymEnt* currentLookSymp = lookSymp; + do { + foundp = currentLookSymp->findIdFlat(nodep->name()); + if (foundp && !checkIfClassOrPackage(foundp)) foundp = nullptr; + if (!foundp) currentLookSymp = currentLookSymp->fallbackp(); + } while (!foundp && currentLookSymp); } else { foundp = lookSymp->findIdFlat(nodep->name()); + if (foundp && !checkIfClassOrPackage(foundp)) foundp = nullptr; } if (!foundp && v3Global.rootp()->stdPackagep()) { // Look under implied std:: foundp = getNodeSym(v3Global.rootp()->stdPackagep())->findIdFlat(nodep->name()); diff --git a/test_regress/t/t_class_reference_name_colision.py b/test_regress/t/t_class_reference_name_colision.py new file mode 100755 index 000000000..147fe6faf --- /dev/null +++ b/test_regress/t/t_class_reference_name_colision.py @@ -0,0 +1,16 @@ +#!/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.passes() diff --git a/test_regress/t/t_class_reference_name_colision.v b/test_regress/t/t_class_reference_name_colision.v new file mode 100644 index 000000000..6ddd27f78 --- /dev/null +++ b/test_regress/t/t_class_reference_name_colision.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, 2025 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +class setup_coefficients; + static function int create(); + return 1; + endfunction +endclass + +class biquad_vseq; + int c_setup = setup_coefficients::create(); + function void setup_coefficients(); + endfunction +endclass: biquad_vseq