From 1c2fa7234da7e43d2e4e464364354badb24d7b4e Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 31 Aug 2026 18:04:58 -0400 Subject: [PATCH] Fix removing extra width warnings after another error --- src/V3AssertPre.cpp | 4 ++-- src/V3AstNodeExpr.h | 10 ++++++++++ src/V3AstNodes.cpp | 1 + src/V3Error.h | 7 ++++--- src/V3FileLine.h | 2 ++ src/V3LinkDot.cpp | 2 +- src/V3LinkResolve.cpp | 2 +- src/V3Width.cpp | 20 +++++++++++++------- 8 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 62da90812..ec6b0f35c 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -979,7 +979,7 @@ private: nodep->v3error("Repetition count is not an elaboration-time constant" " (IEEE 1800-2023 16.9.2)"); VL_DO_DANGLING(pushDeletep(countp), countp); - nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalse{}}); + nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}); VL_DO_DANGLING(pushDeletep(nodep), nodep); return nullptr; } @@ -987,7 +987,7 @@ private: nodep->v3error("Repetition count must be non-negative" " (IEEE 1800-2023 16.9.2)"); VL_DO_DANGLING(pushDeletep(countp), countp); - nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalse{}}); + nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}); VL_DO_DANGLING(pushDeletep(nodep), nodep); return nullptr; } diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 50fc7269e..82eb67dc1 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -1159,6 +1159,16 @@ public: , m_num(this, 1, 0) { // Need () constructor dtypeSetBit(); } + // False but created due to reporting earlier error; suppress some later errors + class BitFalseErroring {}; + AstConst(FileLine* fl, BitFalseErroring) + : ASTGEN_SUPER_Const(fl) + , m_num(this, 1, 0) { // Need () constructor + dtypeSetBit(); + FileLine* const newfl = new FileLine{fileline()}; + newfl->erroringOn(true); + fileline(newfl); + } // Shorthand const 1 (or with argument 0/1), dtype should be a bit of size 1 class BitTrue {}; AstConst(FileLine* fl, BitTrue, bool on = true) diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 1dbe4e31d..706fd07bd 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -1878,6 +1878,7 @@ void AstNode::dump(std::ostream& str) const { } else { // V3Broken will throw an error if (dtypep()) str << " %Error-dtype-exp=null,got=" << nodeAddr(dtypep()); } + if (fileline()->erroringOn()) str << " [ERRORING]"; if (name() != "") { if (VN_IS(this, Const)) { str << " " << name(); // Already quoted diff --git a/src/V3Error.h b/src/V3Error.h index eb5398442..f88ecd77f 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -55,6 +55,7 @@ public: // Boolean information we track per-line, but aren't errors I_CELLDEFINE, // Inside cell define from `celldefine/`endcelldefine I_COVERAGE, // Coverage is on/off from /*verilator coverage_on/off*/ + I_ERRORING, // Node created to handle earlier error; suppress new errors I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE) I_LINT, // All lint messages I_STYLE, // All style messages @@ -220,8 +221,8 @@ public: // Leading spaces indicate it can't be disabled. " MIN", " INFO", " FATAL", " FATALMANY", " FATALSRC", " ERROR", " FIRST_NAMED", // Boolean - " I_CELLDEFINE", " I_COVERAGE", " I_DEF_NETTYPE_WIRE", " I_LINT", " I_STYLE", - " I_TIMING", " I_TRACING", + " I_CELLDEFINE", " I_COVERAGE", " I_ERRORING", " I_DEF_NETTYPE_WIRE", " I_LINT", + " I_STYLE", " I_TIMING", " I_TRACING", // Errors "CONTASSINIT", "CONSTWRITTEN", "LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR", "UNSUPPORTED", @@ -252,7 +253,7 @@ public: } // Warnings that default to off bool defaultsOff() const VL_MT_SAFE { - return (m_e == IMPERFECTSCH || m_e == I_CELLDEFINE || styleError()); + return (m_e == IMPERFECTSCH || m_e == I_CELLDEFINE || m_e == I_ERRORING || styleError()); } // Warnings that warn about nasty side effects bool dangerous() const VL_MT_SAFE { return (m_e == COMBDLY); } diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 4c75f3c96..7c5a020ba 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -393,6 +393,8 @@ public: void celldefineOn(bool flag) { warnOn(V3ErrorCode::I_CELLDEFINE, flag); } bool coverageOn() const { return msgEn().enabled(V3ErrorCode::I_COVERAGE); } void coverageOn(bool flag) { warnOn(V3ErrorCode::I_COVERAGE, flag); } + bool erroringOn() const { return msgEn().enabled(V3ErrorCode::I_ERRORING); } + void erroringOn(bool flag) { warnOn(V3ErrorCode::I_ERRORING, flag); } bool tracingOn() const { return msgEn().enabled(V3ErrorCode::I_TRACING); } void tracingOn(bool flag) { warnOn(V3ErrorCode::I_TRACING, flag); } bool timingOn() const { return msgEn().enabled(V3ErrorCode::I_TIMING); } diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 55f369ec6..5d1283764 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -3590,7 +3590,7 @@ class LinkDotResolveVisitor final : public VNVisitor { if (oldp->wouldBreak(newp)) { newp->v3error( "Data type used where a non-data type is expected: " << newp->prettyNameQ()); - oldp->replaceWith(new AstConst{newp->fileline(), AstConst::BitFalse{}}); + oldp->replaceWith(new AstConst{newp->fileline(), AstConst::BitFalseErroring{}}); } else { oldp->replaceWith(newp); } diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 110203633..636965aa9 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -157,7 +157,7 @@ class LinkResolveVisitor final : public VNVisitor { UINFO(7, "letSubstitute() " << nodep << " <- " << letp); if (letp->user2()) { nodep->v3error("Recursive let substitution " << letp->prettyNameQ()); - nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalse{}}); + nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}); VL_DO_DANGLING(pushDeletep(nodep), nodep); return; } diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 1ebe42565..e90dc6b46 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -3033,7 +3033,7 @@ class WidthVisitor final : public VNVisitor { UASSERT_OBJ(nodep->valuep(), nodep, "circular, but without value"); nodep->v3error("Variable's initial value is circular: " << nodep->prettyNameQ()); pushDeletep(nodep->valuep()->unlinkFrBack()); - nodep->valuep(new AstConst{nodep->fileline(), AstConst::BitTrue{}}); + nodep->valuep(new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}); nodep->dtypeFrom(nodep->valuep()); nodep->didWidth(true); return; @@ -4330,7 +4330,8 @@ class WidthVisitor final : public VNVisitor { // Adjust to required argument counts, very bogus, but avoids core dump for (; narg < minArg; ++narg) { nodep->addArgsp( - new AstArg{nodep->fileline(), "", new AstConst(nodep->fileline(), 0)}); + new AstArg{nodep->fileline(), "", + new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}}); } for (; narg > maxArg; --narg) { AstArg* argp = nodep->argsp(); @@ -5223,7 +5224,7 @@ class WidthVisitor final : public VNVisitor { v3Global.useRandomizeMethods(true); } else { nodep->v3error("No such constraint method " << nodep->prettyNameQ()); - nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalse{}}); + nodep->replaceWith(new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}); VL_DO_DANGLING(pushDeletep(nodep), nodep); } } @@ -8097,7 +8098,8 @@ class WidthVisitor final : public VNVisitor { // The parser distinguishes the two via AstLogNot::fromProperty(). if (m_underSExpr && nodep->fromProperty()) { nodep->v3error("Unexpected 'not' in sequence expression context"); - AstConst* const newp = new AstConst{nodep->fileline(), 0}; + AstConst* const newp + = new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}; newp->dtypeFrom(nodep); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); @@ -8288,7 +8290,8 @@ class WidthVisitor final : public VNVisitor { << lhsDType->prettyDTypeNameQ() << "\n" << nodep->warnMore() << "... Right-hand data type: " << rhsDType->prettyDTypeNameQ()); - AstNode* const newp = new AstConst{nodep->fileline(), AstConst::BitFalse{}}; + AstNode* const newp + = new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}; nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); return; @@ -8296,7 +8299,8 @@ class WidthVisitor final : public VNVisitor { } else if (nodep->lhsp()->isDouble() || nodep->rhsp()->isDouble()) { if (!realok) { nodep->v3error("Real is illegal operand to ?== operator"); - AstNode* const newp = new AstConst{nodep->fileline(), AstConst::BitFalse{}}; + AstNode* const newp + = new AstConst{nodep->fileline(), AstConst::BitFalseErroring{}}; nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); return; @@ -9292,7 +9296,7 @@ class WidthVisitor final : public VNVisitor { parentp->v3error("Logical operator " << parentp->prettyTypeName() << " expects a non-complex data type on the " << side << "."); - underp->replaceWith(new AstConst{parentp->fileline(), AstConst::BitFalse{}}); + underp->replaceWith(new AstConst{parentp->fileline(), AstConst::BitFalseErroring{}}); VL_DO_DANGLING(pushDeletep(underp), underp); } else { const bool bad = widthBad(underp, parentp->findBitDType()); @@ -9484,6 +9488,8 @@ class WidthVisitor final : public VNVisitor { // If user has a sizing cast, assume they know what they are doing // (for better or worse) if (VN_IS(parentp->backp(), CastSize)) warnOn = false; + if (parentp->fileline()->erroringOn() || underp->fileline()->erroringOn()) + warnOn = false; if (VN_IS(underp, Const) && VN_AS(underp, Const)->num().isFromString() && expWidth > underp->width() && (((expWidth - underp->width()) % 8) == 0)) { // At least it's character sized