mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +02:00
This commit is contained in:
@@ -2367,6 +2367,22 @@ class ParamClassRefDTypeRelinkVisitor final : public VNVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
// A class's name before specialization (e.g. "holder" for "holder__Tz1").
|
||||
static string classOrigName(const AstClass* classp) {
|
||||
return classp->origName().empty() ? classp->name() : classp->origName();
|
||||
}
|
||||
|
||||
// Find 'name' in classp or any base class (findTypedefInModule() searches
|
||||
// only the class itself).
|
||||
static AstTypedef* findTypedefWithBases(AstClass* classp, const string& name) {
|
||||
for (AstClass* cp = classp; cp; cp = cp->extendsp() ? cp->extendsp()->classp() : nullptr) {
|
||||
if (AstTypedef* const tdp = V3LinkDotIfaceCapture::findTypedefInModule(cp, name)) {
|
||||
if (tdp->subDTypep()) return tdp;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Re-resolve REFDTYPE.typedefp/refDTypep using the containing module's
|
||||
// own resolved typedef chain. The eager retargeting in deepCloneModule
|
||||
// blindly retargets every captured entry to whichever sibling clone is
|
||||
@@ -2377,10 +2393,46 @@ class ParamClassRefDTypeRelinkVisitor final : public VNVisitor {
|
||||
// those local typedefs as ground truth.
|
||||
void retargetRefDType(AstRefDType* refp) {
|
||||
if (!m_ownerModp) return;
|
||||
|
||||
// IEEE 1800-2023 8.25.1: a bare class-qualified reference to the class
|
||||
// being compiled means the current specialization, but V3LinkDot binds
|
||||
// it to the default instance, so a typedef reached through it widens
|
||||
// with the template's defaults (#8348). Rebind it to the
|
||||
// specialization's own typedef.
|
||||
if (AstClass* const ownerClassp = VN_CAST(m_ownerModp, Class)) {
|
||||
if (!ownerClassp->hasGParam() && !refp->paramsp()) {
|
||||
// What the reference resolves to: its typedef's owner if
|
||||
// linked, else the class it is qualified by.
|
||||
const AstClass* refClassp = nullptr;
|
||||
if (AstTypedef* const tdp = refp->typedefp()) {
|
||||
refClassp = VN_CAST(V3LinkDotIfaceCapture::findOwnerModule(tdp), Class);
|
||||
} else if (const AstClassOrPackageRef* const classRefp
|
||||
= VN_CAST(refp->classOrPackageOpp(), ClassOrPackageRef)) {
|
||||
refClassp = VN_CAST(classRefp->classOrPackageSkipp(), Class);
|
||||
}
|
||||
// Same originating class => bare self reference (another
|
||||
// specialization would carry #(), rejected above).
|
||||
if (refClassp && refClassp != ownerClassp
|
||||
&& classOrigName(refClassp) == classOrigName(ownerClassp)) {
|
||||
AstTypedef* const selfTdp = findTypedefWithBases(ownerClassp, refp->name());
|
||||
if (selfTdp) {
|
||||
UINFO(9, "post-param REFDTYPE self-reference retarget: "
|
||||
<< refp << " from " << refClassp->name() << " to "
|
||||
<< ownerClassp->name());
|
||||
refp->typedefp(selfTdp);
|
||||
refp->classOrPackagep(V3LinkDotIfaceCapture::findOwnerModule(selfTdp));
|
||||
refp->refDTypep(selfTdp->subDTypep());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AstTypedef* const oldTdp = refp->typedefp();
|
||||
if (!oldTdp) return;
|
||||
AstClass* const oldOwnerp = VN_CAST(V3LinkDotIfaceCapture::findOwnerModule(oldTdp), Class);
|
||||
if (!oldOwnerp) return;
|
||||
|
||||
ensureOwnerMap();
|
||||
if (m_origNameToClone.empty()) return;
|
||||
const std::string origName
|
||||
|
||||
Reference in New Issue
Block a user