Fix untyped dtype error on sampling functions with property arguments (#8060)

Signed-off-by: Artur Bieniek <[email protected]>
This commit is contained in:
Artur Bieniek
2026-08-12 05:16:48 -04:00
committed by GitHub
parent 0b51926fff
commit e962efca12
11 changed files with 218 additions and 26 deletions
+29 -13
View File
@@ -1519,7 +1519,8 @@ class WidthVisitor final : public VNVisitor {
void visit(AstFell* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
userIterate(nodep->sentreep(), nullptr);
nodep->dtypeSetBit();
}
@@ -1527,14 +1528,16 @@ class WidthVisitor final : public VNVisitor {
void visit(AstFalling* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
nodep->dtypeSetBit();
}
}
void visit(AstFuture* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
userIterate(nodep->sentreep(), nullptr);
nodep->dtypeFrom(nodep->exprp());
}
@@ -1542,10 +1545,12 @@ class WidthVisitor final : public VNVisitor {
void visit(AstPast* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
nodep->dtypeFrom(nodep->exprp());
if (nodep->ticksp()) {
iterateCheckSizedSelf(nodep, "Ticks", nodep->ticksp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "Ticks", nodep->ticksp(), SELF, BOTH,
/* deferUntyped */ true);
V3Const::constifyParamsEdit(nodep->ticksp()); // ticksp may change
const AstConst* const constp = VN_CAST(nodep->ticksp(), Const);
if (!constp) {
@@ -1670,14 +1675,16 @@ class WidthVisitor final : public VNVisitor {
void visit(AstRising* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
nodep->dtypeSetBit();
}
}
void visit(AstRose* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
userIterate(nodep->sentreep(), nullptr);
nodep->dtypeSetBit();
}
@@ -1686,7 +1693,8 @@ class WidthVisitor final : public VNVisitor {
void visit(AstSampled* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
nodep->dtypeFrom(nodep->exprp());
}
}
@@ -1743,7 +1751,8 @@ class WidthVisitor final : public VNVisitor {
void visit(AstStable* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
userIterate(nodep->sentreep(), nullptr);
nodep->dtypeSetBit();
}
@@ -1751,7 +1760,8 @@ class WidthVisitor final : public VNVisitor {
void visit(AstSteady* nodep) override {
assertAtExpr(nodep);
if (m_vup->prelim()) {
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH);
iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH,
/* deferUntyped */ true);
nodep->dtypeSetBit();
}
}
@@ -7532,7 +7542,10 @@ class WidthVisitor final : public VNVisitor {
<< pinDTypep->prettyDTypeNameQ());
continue;
}
if (!portp->basicp() || portp->basicp()->isOpaque()) {
// An untyped formal preserves the actual argument's self-determined type.
if (portp->basicp() && portp->basicp()->untyped()) {
iterateCheckSelf(nodep, "Function Argument", pinp, SELF, FINAL);
} else if (!portp->basicp() || portp->basicp()->isOpaque()) {
// Output args: at return caller = callee, reverse direction.
checkClassAssign(nodep, "Function Argument", pinp, portDTypep,
portp->direction() == VDirection::OUTPUT);
@@ -9081,7 +9094,7 @@ class WidthVisitor final : public VNVisitor {
(void)underp; // cppcheck
}
void iterateCheckSizedSelf(AstNode* parentp, const char* side, AstNode* underp, Determ determ,
Stage stage) {
Stage stage, bool deferUntyped = false) {
// Coerce child to any sized-number data type; child is self-determined
// i.e. isolated from expected type.
// e.g. parentp=CONCAT, underp=lhs in CONCAT(lhs,rhs)
@@ -9095,7 +9108,10 @@ class WidthVisitor final : public VNVisitor {
AstNodeDType* const expDTypep = underp->dtypep();
underp = iterateCheck(parentp, side, underp, SELF, FINAL, expDTypep, EXTEND_EXP);
AstNodeDType* const checkDtp = expDTypep->skipRefToEnump();
if (!checkDtp->isIntegralOrPacked()) {
// Sampling functions may still reference an untyped property formal here.
// V3AssertPre checks the actual type after property argument substitution.
if (!checkDtp->isIntegralOrPacked()
&& !(deferUntyped && checkDtp->basicp() && checkDtp->basicp()->untyped())) {
parentp->v3error("Expected numeric type, but got a " << checkDtp->prettyDTypeNameQ()
<< " data type");
}