Fix memory leaks in assignment pattern processing (#6437).

This commit is contained in:
Geza Lore 2025-09-16 18:31:16 +02:00 committed by GitHub
parent 9187b4d552
commit ef458be855
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 36 additions and 43 deletions

View File

@ -4744,25 +4744,30 @@ class WidthVisitor final : public VNVisitor {
userIterate(dtypep, WidthVP{SELF, BOTH}.p()); userIterate(dtypep, WidthVP{SELF, BOTH}.p());
if (auto* const vdtypep = VN_CAST(dtypep, NodeUOrStructDType)) { if (auto* const vdtypep = VN_CAST(dtypep, NodeUOrStructDType)) {
VL_DO_DANGLING(patternUOrStruct(nodep, vdtypep, defaultp), nodep); patternUOrStruct(nodep, vdtypep, defaultp);
} else if (auto* const vdtypep = VN_CAST(dtypep, NodeArrayDType)) { } else if (auto* const vdtypep = VN_CAST(dtypep, NodeArrayDType)) {
VL_DO_DANGLING(patternArray(nodep, vdtypep, defaultp), nodep); patternArray(nodep, vdtypep, defaultp);
} else if (auto* const vdtypep = VN_CAST(dtypep, AssocArrayDType)) { } else if (auto* const vdtypep = VN_CAST(dtypep, AssocArrayDType)) {
VL_DO_DANGLING(patternAssoc(nodep, vdtypep, defaultp), nodep); patternAssoc(nodep, vdtypep, defaultp);
} else if (auto* const vdtypep = VN_CAST(dtypep, WildcardArrayDType)) { } else if (auto* const vdtypep = VN_CAST(dtypep, WildcardArrayDType)) {
VL_DO_DANGLING(patternWildcard(nodep, vdtypep, defaultp), nodep); patternWildcard(nodep, vdtypep, defaultp);
} else if (auto* const vdtypep = VN_CAST(dtypep, DynArrayDType)) { } else if (auto* const vdtypep = VN_CAST(dtypep, DynArrayDType)) {
VL_DO_DANGLING(patternDynArray(nodep, vdtypep, defaultp), nodep); patternDynArray(nodep, vdtypep, defaultp);
} else if (auto* const vdtypep = VN_CAST(dtypep, QueueDType)) { } else if (auto* const vdtypep = VN_CAST(dtypep, QueueDType)) {
VL_DO_DANGLING(patternQueue(nodep, vdtypep, defaultp), nodep); patternQueue(nodep, vdtypep, defaultp);
} else if (VN_IS(dtypep, BasicDType) && VN_AS(dtypep, BasicDType)->isRanged()) { } else if (VN_IS(dtypep, BasicDType) && VN_AS(dtypep, BasicDType)->isRanged()) {
VL_DO_DANGLING(patternBasic(nodep, dtypep, defaultp), nodep); patternBasic(nodep, dtypep, defaultp);
} else { } else {
nodep->v3warn( nodep->v3warn(
E_UNSUPPORTED, E_UNSUPPORTED,
"Unsupported: Assignment pattern applies against non struct/union data type: " "Unsupported: Assignment pattern applies against non struct/union data type: "
<< dtypep->prettyDTypeNameQ()); << dtypep->prettyDTypeNameQ());
nodep->unlinkFrBack();
} }
// Done with the Pattern
VL_DO_DANGLING(pushDeletep(nodep), nodep);
if (defaultp) VL_DO_DANGLING(pushDeletep(defaultp), defaultp);
} }
} }
void patternUOrStruct(AstPattern* nodep, AstNodeUOrStructDType* vdtypep, void patternUOrStruct(AstPattern* nodep, AstNodeUOrStructDType* vdtypep,
@ -4802,11 +4807,8 @@ class WidthVisitor final : public VNVisitor {
// data_type: default_value // data_type: default_value
userIterate(nodedtypep, WidthVP{SELF, BOTH}.p()); userIterate(nodedtypep, WidthVP{SELF, BOTH}.p());
const string dtype = nodedtypep->dtypep()->prettyDTypeName(true); const string dtype = nodedtypep->dtypep()->prettyDTypeName(true);
const auto pair = dtypemap.emplace(dtype, patp); // Override stored default_value
if (!pair.second) { dtypemap[dtype] = patp;
// Override stored default_value
pair.first->second = patp->cloneTree(false);
}
} else { } else {
// Undefined pattern // Undefined pattern
patp->keyp()->v3error( patp->keyp()->v3error(
@ -4836,20 +4838,19 @@ class WidthVisitor final : public VNVisitor {
for (AstMemberDType* memp = vdtypep->membersp(); memp; for (AstMemberDType* memp = vdtypep->membersp(); memp;
memp = VN_AS(memp->nextp(), MemberDType)) { memp = VN_AS(memp->nextp(), MemberDType)) {
const auto it = patmap.find(memp); const auto it = patmap.find(memp);
AstPatMember* patp = nullptr;
if (it == patmap.end()) { // default or default_type assignment if (it == patmap.end()) { // default or default_type assignment
if (AstNodeUOrStructDType* const memp_nested_vdtypep if (AstNodeUOrStructDType* const memp_nested_vdtypep
= VN_CAST(memp->virtRefDTypep(), NodeUOrStructDType)) { = VN_CAST(memp->virtRefDTypep(), NodeUOrStructDType)) {
newp = nestedvalueConcat_patternUOrStruct(memp_nested_vdtypep, defaultp, newp = nestedvalueConcat_patternUOrStruct(memp_nested_vdtypep, defaultp,
newp, nodep, dtypemap); newp, nodep, dtypemap);
} else { } else {
patp = defaultPatp_patternUOrStruct(nodep, memp, patp, vdtypep, defaultp, AstPatMember* const patp = defaultPatp_patternUOrStruct(
dtypemap); nodep, memp, vdtypep, defaultp, dtypemap);
newp = valueConcat_patternUOrStruct(patp, newp, memp, nodep); newp = valueConcat_patternUOrStruct(patp, newp, memp, nodep);
if (patp) VL_DO_DANGLING(pushDeletep(patp), patp);
} }
} else { // member assignment } else { // member assignment
patp = it->second; newp = valueConcat_patternUOrStruct(it->second, newp, memp, nodep);
newp = valueConcat_patternUOrStruct(patp, newp, memp, nodep);
} }
} }
} else { // Unpacked } else { // Unpacked
@ -4859,8 +4860,8 @@ class WidthVisitor final : public VNVisitor {
const auto it = patmap.find(memp); const auto it = patmap.find(memp);
AstPatMember* patp = nullptr; AstPatMember* patp = nullptr;
if (it == patmap.end()) { // Default or default_type assignment if (it == patmap.end()) { // Default or default_type assignment
patp = defaultPatp_patternUOrStruct(nodep, memp, patp, vdtypep, defaultp, patp = defaultPatp_patternUOrStruct(nodep, memp, vdtypep, defaultp, dtypemap);
dtypemap); pushDeletep(patp);
} else { } else {
patp = it->second; // Member assignment patp = it->second; // Member assignment
} }
@ -4877,13 +4878,11 @@ class WidthVisitor final : public VNVisitor {
} else { } else {
nodep->v3error("Assignment pattern with no members"); nodep->v3error("Assignment pattern with no members");
} }
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }
AstNodeExpr* nestedvalueConcat_patternUOrStruct(AstNodeUOrStructDType* memp_vdtypep, AstNodeExpr* nestedvalueConcat_patternUOrStruct(AstNodeUOrStructDType* memp_vdtypep,
AstPatMember* defaultp, AstNodeExpr* newp, AstPatMember* defaultp, AstNodeExpr* newp,
AstPattern* nodep, const DTypeMap& dtypemap) { AstPattern* nodep, const DTypeMap& dtypemap) {
AstPatMember* patp = nullptr;
for (AstMemberDType* memp_nested = memp_vdtypep->membersp(); memp_nested; for (AstMemberDType* memp_nested = memp_vdtypep->membersp(); memp_nested;
memp_nested = VN_AS(memp_nested->nextp(), MemberDType)) { memp_nested = VN_AS(memp_nested->nextp(), MemberDType)) {
if (AstNodeUOrStructDType* const memp_multinested_vdtypep if (AstNodeUOrStructDType* const memp_multinested_vdtypep
@ -4893,34 +4892,34 @@ class WidthVisitor final : public VNVisitor {
newp = nestedvalueConcat_patternUOrStruct(memp_multinested_vdtypep, defaultp, newp, newp = nestedvalueConcat_patternUOrStruct(memp_multinested_vdtypep, defaultp, newp,
nodep, dtypemap); nodep, dtypemap);
} else { } else {
patp = defaultPatp_patternUOrStruct(nodep, memp_nested, patp, memp_vdtypep, AstPatMember* const patp = defaultPatp_patternUOrStruct(
defaultp, dtypemap); nodep, memp_nested, memp_vdtypep, defaultp, dtypemap);
newp = valueConcat_patternUOrStruct(patp, newp, memp_nested, nodep); newp = valueConcat_patternUOrStruct(patp, newp, memp_nested, nodep);
if (patp) VL_DO_DANGLING(pushDeletep(patp), patp);
} }
} }
return newp; return newp;
} }
AstPatMember* defaultPatp_patternUOrStruct(AstPattern* nodep, AstMemberDType* memp, AstPatMember* defaultPatp_patternUOrStruct(AstPattern* nodep, AstMemberDType* memp,
AstPatMember* patp,
AstNodeUOrStructDType* memp_vdtypep, AstNodeUOrStructDType* memp_vdtypep,
AstPatMember* defaultp, const DTypeMap& dtypemap) { AstPatMember* defaultp, const DTypeMap& dtypemap) {
const string memp_DType = memp->virtRefDTypep()->prettyDTypeName(true); const string memp_DType = memp->virtRefDTypep()->prettyDTypeName(true);
const auto it = dtypemap.find(memp_DType); const auto it = dtypemap.find(memp_DType);
if (it != dtypemap.end()) { if (it != dtypemap.end()) {
// default_value for data_type // default_value for data_type
patp = it->second->cloneTree(false); return it->second->cloneTree(false);
} else if (defaultp) {
// default_value for any unmatched member yet
patp = defaultp->cloneTree(false);
} else {
if (!VN_IS(memp_vdtypep, UnionDType)) {
nodep->v3error("Assignment pattern missed initializing elements: "
<< memp->virtRefDTypep()->prettyDTypeNameQ() << " "
<< memp->prettyNameQ());
}
} }
return patp; if (defaultp) {
// default_value for any unmatched member yet
return defaultp->cloneTree(false);
}
if (!VN_IS(memp_vdtypep, UnionDType)) {
nodep->v3error("Assignment pattern missed initializing elements: "
<< memp->virtRefDTypep()->prettyDTypeNameQ() << " "
<< memp->prettyNameQ());
}
return nullptr;
} }
AstNodeExpr* valueConcat_patternUOrStruct(AstPatMember* patp, AstNodeExpr* newp, AstNodeExpr* valueConcat_patternUOrStruct(AstPatMember* patp, AstNodeExpr* newp,
@ -5004,7 +5003,6 @@ class WidthVisitor final : public VNVisitor {
nodep->v3error("Assignment pattern with no members"); nodep->v3error("Assignment pattern with no members");
} }
// UINFOTREE(9, newp, "", "apat-out"); // UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }
void patternAssoc(AstPattern* nodep, AstAssocArrayDType* arrayDtp, AstPatMember* defaultp) { void patternAssoc(AstPattern* nodep, AstAssocArrayDType* arrayDtp, AstPatMember* defaultp) {
AstNode* defaultValuep = nullptr; AstNode* defaultValuep = nullptr;
@ -5033,7 +5031,6 @@ class WidthVisitor final : public VNVisitor {
} }
nodep->replaceWith(newp); nodep->replaceWith(newp);
// UINFOTREE(9, newp, "", "apat-out"); // UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }
void patternWildcard(AstPattern* nodep, AstWildcardArrayDType* arrayDtp, void patternWildcard(AstPattern* nodep, AstWildcardArrayDType* arrayDtp,
AstPatMember* defaultp) { AstPatMember* defaultp) {
@ -5053,9 +5050,8 @@ class WidthVisitor final : public VNVisitor {
} }
nodep->replaceWith(newp); nodep->replaceWith(newp);
// UINFOTREE(9, newp, "", "apat-out"); // UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }
void patternDynArray(AstPattern* nodep, AstDynArrayDType* arrayp, AstPatMember*) { void patternDynArray(AstPattern* nodep, AstDynArrayDType* arrayp, AstPatMember* defaultp) {
AstNode* newp = new AstConsDynArray{nodep->fileline()}; AstNode* newp = new AstConsDynArray{nodep->fileline()};
newp->dtypeFrom(arrayp); newp->dtypeFrom(arrayp);
for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp; for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;
@ -5072,9 +5068,8 @@ class WidthVisitor final : public VNVisitor {
} }
nodep->replaceWith(newp); nodep->replaceWith(newp);
// UINFOTREE(9, newp, "", "apat-out"); // UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }
void patternQueue(AstPattern* nodep, AstQueueDType* arrayp, AstPatMember*) { void patternQueue(AstPattern* nodep, AstQueueDType* arrayp, AstPatMember* defaultp) {
AstNode* newp = new AstConsQueue{nodep->fileline()}; AstNode* newp = new AstConsQueue{nodep->fileline()};
newp->dtypeFrom(arrayp); newp->dtypeFrom(arrayp);
for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp; for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;
@ -5093,7 +5088,6 @@ class WidthVisitor final : public VNVisitor {
} }
nodep->replaceWith(newp); nodep->replaceWith(newp);
// UINFOTREE(9, newp, "", "apat-out"); // UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }
void patternBasic(AstPattern* nodep, AstNodeDType* vdtypep, AstPatMember* defaultp) { void patternBasic(AstPattern* nodep, AstNodeDType* vdtypep, AstPatMember* defaultp) {
const AstBasicDType* bdtypep = VN_AS(vdtypep, BasicDType); const AstBasicDType* bdtypep = VN_AS(vdtypep, BasicDType);
@ -5142,7 +5136,6 @@ class WidthVisitor final : public VNVisitor {
nodep->v3error("Assignment pattern with no members"); nodep->v3error("Assignment pattern with no members");
} }
// UINFOTREE(9, newp, "", "apat-out"); // UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep);
} }
AstNodeExpr* patternMemberValueIterate(AstPatMember* patp) { AstNodeExpr* patternMemberValueIterate(AstPatMember* patp) {
// Determine values - might be another InitArray // Determine values - might be another InitArray