Fix crash on forward-referencing parameters (#8175)

This commit is contained in:
Geza Lore
2026-08-21 17:47:10 +02:00
committed by GitHub
parent 99c26d3994
commit a7ecba4f4e
3 changed files with 524 additions and 27 deletions
+36 -27
View File
@@ -1893,36 +1893,45 @@ class ParamProcessor final {
}
}
// For each missing parameter, get its pin from dependency or direct default
for (size_t paramIdx = 0; paramIdx < m_classTypeParams.size(); paramIdx++) {
if (pinsByIndex[paramIdx]) continue;
const int sourceParamIdx = m_classTypeParams[paramIdx].second;
// For each missing parameter, get its pin from dependency or direct default.
// A dependent default can reference a parameter declared later (not IEEE, but
// we support it here), so repeat until no further parameter can be resolved.
for (bool resolvedSome = true; resolvedSome;) {
resolvedSome = false;
for (size_t paramIdx = 0; paramIdx < m_classTypeParams.size(); paramIdx++) {
if (pinsByIndex[paramIdx]) continue;
const int sourceParamIdx = m_classTypeParams[paramIdx].second;
AstPin* newPinp = nullptr;
AstPin* newPinp = nullptr;
// Case 1: Dependent default -> clone the source pin's type
if (sourceParamIdx >= 0) newPinp = pinsByIndex[sourceParamIdx]->cloneTree(false);
// Case 2: Direct default type (e.g., int), create a new pin with that dtype
if (!newPinp && defaultTypeNodes[paramIdx]) {
AstNodeDType* const dtypep = defaultTypeNodes[paramIdx];
newPinp = new AstPin{dtypep->fileline(), static_cast<int>(paramIdx) + 1,
"__paramNumber" + cvtToStr(paramIdx + 1),
dtypep->cloneTree(false)};
}
if (newPinp) {
newPinp->name("__paramNumber" + cvtToStr(paramIdx + 1));
newPinp->param(true);
newPinp->modPTypep(m_classTypeParams[paramIdx].first);
if (classOrPackageRef) {
classOrPackageRef->addParamsp(newPinp);
} else if (classRefDType) {
classRefDType->addParamsp(newPinp);
// Case 1: Dependent default -> clone the source pin's type, but only once
// the source parameter itself has been resolved (it might be listed later)
if (sourceParamIdx >= 0 && pinsByIndex[sourceParamIdx]) {
newPinp = pinsByIndex[sourceParamIdx]->cloneTree(false);
}
// Case 2: Direct default type (e.g., int), create a new pin with that dtype
if (!newPinp && defaultTypeNodes[paramIdx]) {
AstNodeDType* const dtypep = defaultTypeNodes[paramIdx];
newPinp = new AstPin{dtypep->fileline(), static_cast<int>(paramIdx) + 1,
"__paramNumber" + cvtToStr(paramIdx + 1),
dtypep->cloneTree(false)};
}
if (newPinp) {
newPinp->name("__paramNumber" + cvtToStr(paramIdx + 1));
newPinp->param(true);
newPinp->modPTypep(m_classTypeParams[paramIdx].first);
if (classOrPackageRef) {
classOrPackageRef->addParamsp(newPinp);
} else if (classRefDType) {
classRefDType->addParamsp(newPinp);
}
// Update local tracking so future dependent defaults can find it
pinsByIndex[paramIdx] = newPinp;
if (!paramsp) paramsp = newPinp;
resolvedSome = true;
}
// Update local tracking so future dependent defaults can find it
pinsByIndex[paramIdx] = newPinp;
if (!paramsp) paramsp = newPinp;
}
}
}