Fix class scope '::' reference through an inherited type parameter (#7844)
This commit is contained in:
parent
6b3e2ce971
commit
1ea10ba71c
|
|
@ -258,6 +258,7 @@ Samuel Riedel
|
|||
Sean Cross
|
||||
Sebastien Van Cauwenberghe
|
||||
Secturion
|
||||
Sergey Chusov
|
||||
Sergey Fedorov
|
||||
Sergi Granell
|
||||
Seth Pellegrino
|
||||
|
|
|
|||
|
|
@ -1013,18 +1013,23 @@ public:
|
|||
if (checkUnresolvedRef(VN_CAST(dtypep, RefDType))) return true;
|
||||
} else if (const AstParamTypeDType* const paramTypep
|
||||
= VN_CAST(symp->nodep(), ParamTypeDType)) {
|
||||
// ParamTypeDType child may be wrapped in RequireDType or unwrapped
|
||||
// Before V3Param the declared default is in childDTypep (possibly
|
||||
// wrapped in a RequireDType); after V3Param it is consumed and the
|
||||
// bound type is the resolved data type, e.g. a type parameter
|
||||
// inherited from a specialized base class (REQ #(Item) -> class Item).
|
||||
AstNode* childp = paramTypep->childDTypep();
|
||||
if (const AstRequireDType* const reqp = VN_CAST(childp, RequireDType)) {
|
||||
childp = reqp->lhsp();
|
||||
}
|
||||
if (isValidTypeNode(childp)) return true;
|
||||
if (checkUnresolvedRef(VN_CAST(childp, RefDType))) return true;
|
||||
const AstNode* const checkp = childp ? childp : paramTypep->skipRefp();
|
||||
if (isValidTypeNode(checkp)) return true;
|
||||
if (checkUnresolvedRef(VN_CAST(checkp, RefDType))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
VSymEnt* resolveClassOrPackage(VSymEnt* lookSymp, AstClassOrPackageRef* nodep, bool fallback,
|
||||
bool classOnly, const string& forWhat) {
|
||||
bool classOnly, const string& forWhat,
|
||||
bool deferIfUnresolved = false) {
|
||||
if (nodep->classOrPackageSkipp()) return getNodeSym(nodep->classOrPackageSkipp());
|
||||
VSymEnt* foundp;
|
||||
VSymEnt* searchSymp = lookSymp;
|
||||
|
|
@ -1050,6 +1055,7 @@ public:
|
|||
nodep->classOrPackageNodep(foundp->nodep());
|
||||
return foundp;
|
||||
}
|
||||
if (deferIfUnresolved) return nullptr;
|
||||
const string suggest
|
||||
= suggestSymFallback(lookSymp, nodep->name(), LinkNodeMatcherClassOrPackage{});
|
||||
nodep->v3error((classOnly ? "Class" : "Package/class")
|
||||
|
|
@ -4758,8 +4764,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_pinSymp);
|
||||
|
||||
if (!nodep->classOrPackageSkipp() && nodep->name() != "local::") {
|
||||
const bool deferIfUnresolved = m_statep->forPrimary() && m_insideClassExtParam;
|
||||
m_statep->resolveClassOrPackage(m_ds.m_dotSymp, nodep, m_ds.m_dotPos != DP_PACKAGE,
|
||||
false, ":: reference");
|
||||
false, ":: reference", deferIfUnresolved);
|
||||
}
|
||||
|
||||
// ClassRef's have pins, so track
|
||||
|
|
|
|||
|
|
@ -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: 2024 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()
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Sergey Chusov
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// A factory-like static method, as used by UVM's type_id::create().
|
||||
class registry #(type T = int);
|
||||
static function T create();
|
||||
T r = new;
|
||||
return r;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class item;
|
||||
int val;
|
||||
typedef registry#(item) type_id;
|
||||
function new();
|
||||
val = 42;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class seq_base #(type REQ = int, type RSP = REQ);
|
||||
REQ req;
|
||||
endclass
|
||||
|
||||
// Non-parameterized class extending a parameterized base.
|
||||
// REQ is a type parameter inherited from the (specialized) base class and is
|
||||
// here used as a '::' class scope: REQ::type_id::create(). Resolving REQ in
|
||||
// this position requires deferring until after V3Param has bound REQ to item.
|
||||
class seq extends seq_base #(item);
|
||||
function int make();
|
||||
REQ r;
|
||||
r = REQ::type_id::create();
|
||||
return r.val;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
seq s;
|
||||
initial begin
|
||||
s = new;
|
||||
if (s.make() != 42) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue