From f2e55c1cdf4694298bb240a9315c9b2f82d988e4 Mon Sep 17 00:00:00 2001 From: Pawel Klopotek Date: Fri, 3 Jul 2026 14:06:56 +0200 Subject: [PATCH] Fix type resolution when a local name shadows a type name Co-Authored-By: Adam Kostrzewski Signed-off-by: Pawel Klopotek --- src/V3LinkDot.cpp | 10 ++++--- ...dow_type.py => t_function_shadow_class.py} | 0 test_regress/t/t_function_shadow_class.v | 27 +++++++++++++++++++ test_regress/t/t_variable_shadow_type.py | 18 +++++++++++++ ...shadow_type.v => t_variable_shadow_type.v} | 4 +++ 5 files changed, 56 insertions(+), 3 deletions(-) rename test_regress/t/{t_class_member_shadow_type.py => t_function_shadow_class.py} (100%) create mode 100644 test_regress/t/t_function_shadow_class.v create mode 100755 test_regress/t/t_variable_shadow_type.py rename test_regress/t/{t_class_member_shadow_type.v => t_variable_shadow_type.v} (97%) diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 0bb78f8e8..905b9f616 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -3572,9 +3572,13 @@ class LinkDotResolveVisitor final : public VNVisitor { while (lookp) { VSymEnt* const foundp = lookp->findIdFlat(name); if (foundp && !VN_IS(foundp->nodep(), MemberDType)) { - // A variable is not a type candidate (IEEE 1800-2023 6.18); skip it so an - // enclosing type is found, but keep it to preserve the "found: VAR" error. - if (!VN_IS(foundp->nodep(), Var)) return foundp; + // Non-type entries are not type candidates + // (IEEE 1800-2023 6.18); skip them so an enclosing + // type is found, but keep one to preserve the "found: ..." error. + if (VN_IS(foundp->nodep(), Typedef) || VN_IS(foundp->nodep(), ParamTypeDType) + || VN_IS(foundp->nodep(), Class)) { + return foundp; + } if (!shadowEntp) shadowEntp = foundp; } lookp = lookp->fallbackp(); diff --git a/test_regress/t/t_class_member_shadow_type.py b/test_regress/t/t_function_shadow_class.py similarity index 100% rename from test_regress/t/t_class_member_shadow_type.py rename to test_regress/t/t_function_shadow_class.py diff --git a/test_regress/t/t_function_shadow_class.v b/test_regress/t/t_function_shadow_class.v new file mode 100644 index 000000000..8fe00d830 --- /dev/null +++ b/test_regress/t/t_function_shadow_class.v @@ -0,0 +1,27 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +module t; + class B; + function void B(); + endfunction + endclass + + class A; + B b = B::new(); + + function void B(); + b.B(); + $write("*-* All Finished *-*\n"); + $finish; + endfunction + endclass + + initial begin + static A a = A::new(); + a.B(); + end +endmodule diff --git a/test_regress/t/t_variable_shadow_type.py b/test_regress/t/t_variable_shadow_type.py new file mode 100755 index 000000000..8a938befd --- /dev/null +++ b/test_regress/t/t_variable_shadow_type.py @@ -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() diff --git a/test_regress/t/t_class_member_shadow_type.v b/test_regress/t/t_variable_shadow_type.v similarity index 97% rename from test_regress/t/t_class_member_shadow_type.v rename to test_regress/t/t_variable_shadow_type.v index 3e56ba5cd..961b5b8b3 100644 --- a/test_regress/t/t_class_member_shadow_type.v +++ b/test_regress/t/t_variable_shadow_type.v @@ -34,12 +34,16 @@ class parent; rand my_blk my_blk; endclass +class Cls; +endclass + module t; my_t my_t; // also legal at module scope initial begin static C c = new; static parent p = new; + static Cls Cls = new; c.my_t = 8'hAB; p.my_blk = new; p.my_blk.x = 5;