Fix invalid typedef linkdot (#8106)

Signed-off-by: Adam Kostrzewski <akostrzewski@internships.antmicro.com>
This commit is contained in:
Adam Kostrzewski 2026-08-14 18:28:35 +02:00 committed by GitHub
parent 743e0f4a82
commit 75a776c516
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 80 additions and 9 deletions

View File

@ -905,7 +905,7 @@ public:
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
// There's no classOrPackagep(); use classOrPackageNodep() to get Node,
// or iterating to package with classOrPackageSkipp()
AstNodeModule* classOrPackageSkipp() const;
AstNodeModule* classOrPackageSkipp(const bool doRefs = true) const;
AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; }
void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; }
void classOrPackagep(AstNodeModule* nodep) {

View File

@ -3460,7 +3460,7 @@ void AstClassOrPackageRef::dump(std::ostream& str) const {
}
}
void AstClassOrPackageRef::dumpJson(std::ostream& str) const { dumpJsonGen(str); }
AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp() const {
AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp(const bool doRefs) const {
AstNode* foundp = m_classOrPackageNodep;
AstNode* lastp = nullptr;
while (foundp != lastp) {
@ -3468,11 +3468,12 @@ AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp() const {
if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) {
foundp = anodep->skipRefOrNullp();
}
if (const AstTypedef* const anodep = VN_CAST(foundp, Typedef)) {
foundp = anodep->subDTypep();
}
if (const AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType)) {
foundp = anodep->classp();
if (doRefs) {
if (const AstTypedef* const anodep = VN_CAST(foundp, Typedef)) {
foundp = anodep->subDTypep();
} else if (const AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType)) {
foundp = anodep->classp();
}
}
}
return VN_CAST(foundp, NodeModule);

View File

@ -3173,6 +3173,7 @@ class LinkDotResolveVisitor final : public VNVisitor {
bool m_replaceWithAlias
= true; // Replace VarScope with an alias. Used in the handling of AstAlias
bool m_isParam = false; // Specifies whether currently visiting param variable
bool m_resolvingTypedef = false; // Currently traversing a Typedef tree
struct DotStates final {
DotPosition m_dotPos; // Scope part of dotted resolution
@ -6063,12 +6064,14 @@ class LinkDotResolveVisitor final : public VNVisitor {
iterate(cpackagep);
return;
}
if (!cpackagerefp->classOrPackageSkipp()) {
const bool doDefaultTypedef = !(m_resolvingTypedef && m_statep->forPrimary());
if (!cpackagerefp->classOrPackageSkipp(doDefaultTypedef)) {
VSymEnt* const foundp = m_statep->resolveClassOrPackage(
m_ds.m_dotSymp, cpackagerefp, true, false, "class/package reference");
if (!foundp) return;
}
nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp());
nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp(doDefaultTypedef));
if (!VN_IS(nodep->classOrPackagep(), Class)
&& !VN_IS(nodep->classOrPackagep(), Package)) {
if (m_statep->forPrimary()) {
@ -6358,6 +6361,12 @@ class LinkDotResolveVisitor final : public VNVisitor {
iterateChildren(nodep);
}
void visit(AstTypedef* nodep) override {
VL_RESTORER(m_resolvingTypedef)
m_resolvingTypedef = true;
iterateChildren(nodep);
}
void visit(AstNode* nodep) override {
VL_RESTORER(m_inPackedArray);
if (VN_IS(nodep, PackArrayDType)) {

View File

@ -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()

View File

@ -0,0 +1,43 @@
// 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
// verilog_format: off
`define stop $stop
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
// verilog_format: on
class class_a;
typedef logic [31:0] type_1;
endclass
class class_b;
typedef logic [31:0] type_1;
typedef logic [63:0] type_2;
endclass
module top #(
parameter type class_t = class_a
) (
input logic in_val
);
typedef class_t::type_2 local_type_2;
local_type_2 internal_sig;
endmodule
module t;
top #(.class_t(class_b)) dut (.in_val('0));
initial begin
dut.internal_sig = $c(1);
`checkd(dut.internal_sig, 1);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule