Fix randomize() on null object handle crashing instead of returning 0 (#7059) (#7066)

This commit is contained in:
Yilou Wang
2026-02-16 22:43:57 -05:00
committed by GitHub
parent 5173f7e42f
commit 4357aee09a
3 changed files with 78 additions and 0 deletions
+20
View File
@@ -3135,6 +3135,24 @@ class RandomizeVisitor final : public VNVisitor {
}
};
// Wrap obj.randomize() with null guard: (obj != null) ? obj.randomize() : 0
// IEEE 1800 requires randomize() on null handle to return 0.
// Uses user4() to prevent re-wrapping during iterateChildren.
void wrapRandomizeCallWithNullGuard(AstNodeFTaskRef* nodep) {
AstMethodCall* const callp = VN_CAST(nodep, MethodCall);
if (!callp) return;
if (callp->user4()) return;
callp->user4(true);
FileLine* const fl = callp->fileline();
AstNodeExpr* const checkp
= new AstNeq{fl, callp->fromp()->cloneTree(false), new AstConst{fl, AstConst::Null{}}};
VNRelinker relinker;
callp->unlinkFrBack(&relinker);
AstCond* const condp = new AstCond{fl, checkp, callp, new AstConst{fl, 0}};
condp->dtypeFrom(callp);
relinker.relink(condp);
}
// Handle inline random variable control. After this, the randomize() call has no args
void handleRandomizeArgs(AstNodeFTaskRef* const nodep) {
if (!nodep->pinsp()) return;
@@ -3593,6 +3611,7 @@ class RandomizeVisitor final : public VNVisitor {
AstWith* const withp = VN_CAST(nodep->pinsp(), With);
if (!withp) {
iterateChildren(nodep);
wrapRandomizeCallWithNullGuard(nodep);
return;
}
withp->unlinkFrBack();
@@ -3730,6 +3749,7 @@ class RandomizeVisitor final : public VNVisitor {
nodep->dtypeFrom(randomizeFuncp->dtypep());
nodep->classOrPackagep(classp);
UINFO(9, "Added `%s` randomization procedure");
wrapRandomizeCallWithNullGuard(nodep);
VL_DO_DANGLING(withp->deleteTree(), withp);
}
void visit(AstConstraint* nodep) override {