Fix inside operator crash with impure expression and unsized range literals (#7063) (#7067)

This commit is contained in:
Yilou Wang 2026-02-17 04:03:31 +01:00 committed by GitHub
parent 994ef82e76
commit 5173f7e42f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 12 deletions

View File

@ -781,6 +781,11 @@ public:
AstNodeDType* findVoidDType() const;
AstNodeDType* findBitDType(int width, int widthMin, VSigning numeric) const;
AstNodeDType* findLogicDType(int width, int widthMin, VSigning numeric) const;
AstNodeDType* findBitOrLogicDType(int width, int widthMin, VSigning numeric,
bool isFourstate) const {
return isFourstate ? findLogicDType(width, widthMin, numeric)
: findBitDType(width, widthMin, numeric);
}
AstNodeDType* findLogicRangeDType(const VNumRange& range, int widthMin,
VSigning numeric) const VL_MT_STABLE;
AstNodeDType* findBitRangeDType(const VNumRange& range, int widthMin,

View File

@ -2517,10 +2517,8 @@ class WidthVisitor final : public VNVisitor {
// So two steps, first do the calculation's width (max of the two widths)
{
const int calcWidth = std::max(width, underDtp->width());
AstNodeDType* const calcDtp
= (underDtp->isFourstate()
? nodep->findLogicDType(calcWidth, calcWidth, underDtp->numeric())
: nodep->findBitDType(calcWidth, calcWidth, underDtp->numeric()));
AstNodeDType* const calcDtp = nodep->findBitOrLogicDType(
calcWidth, calcWidth, underDtp->numeric(), underDtp->isFourstate());
nodep->dtypep(calcDtp);
// We ignore warnings as that is sort of the point of a cast
iterateCheck(nodep, "Cast expr", underp, CONTEXT_DET, FINAL, calcDtp, EXTEND_EXP,
@ -2531,10 +2529,8 @@ class WidthVisitor final : public VNVisitor {
// UINFOTREE(1, nodep, "", "CastSizeClc");
// Next step, make the proper output width
{
AstNodeDType* const outDtp
= (underDtp->isFourstate()
? nodep->findLogicDType(width, width, underDtp->numeric())
: nodep->findBitDType(width, width, underDtp->numeric()));
AstNodeDType* const outDtp = nodep->findBitOrLogicDType(
width, width, underDtp->numeric(), underDtp->isFourstate());
nodep->dtypep(outDtp);
// We ignore warnings as that is sort of the point of a cast
widthCheckSized(nodep, "Cast expr", VN_AS(underp, NodeExpr), outDtp, EXTEND_EXP,
@ -3140,8 +3136,7 @@ class WidthVisitor final : public VNVisitor {
}
nodep->dtypeSetBit();
const VSigning numeric = nodep->exprp()->dtypep()->numeric();
expDTypep = isFourstate ? nodep->findLogicDType(width, mwidth, numeric)
: nodep->findBitDType(width, mwidth, numeric);
expDTypep = nodep->findBitOrLogicDType(width, mwidth, numeric, isFourstate);
}
iterateCheck(nodep, "Inside expression", nodep->exprp(), CONTEXT_DET, FINAL, expDTypep,
@ -3160,8 +3155,15 @@ class WidthVisitor final : public VNVisitor {
// executed so, there is no need for purification since they cannot generate sideeffects.
if (!m_constraintp && !nodep->exprp()->isPure()) {
FileLine* const fl = nodep->exprp()->fileline();
AstVar* const varp = new AstVar{fl, VVarType::XTEMP, m_insideTempNames.get(nodep),
nodep->exprp()->dtypep()};
// Ensure sized dtype for temp variable
AstNodeDType* const exprDtp = nodep->exprp()->dtypep();
const int w = exprDtp->width();
AstNodeDType* const tempDTypep
= exprDtp->widthSized() ? exprDtp
: nodep->findBitOrLogicDType(w, w, exprDtp->numeric(),
exprDtp->isFourstate());
AstVar* const varp
= new AstVar{fl, VVarType::XTEMP, m_insideTempNames.get(nodep), tempDTypep};
exprp = new AstVarRef{fl, varp, VAccess::READ};
exprStmtp = new AstExprStmt{fl,
new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of either the GNU Lesser General Public License Version 3
# or the Perl Artistic License Version 2.0.
# SPDX-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile()
test.execute()
test.passes()

View File

@ -0,0 +1,37 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 PlanV GmbH
// SPDX-License-Identifier: CC0-1.0
module t;
bit [7:0] str_arr[string];
string str_key;
bit [7:0] int_arr[int];
int int_key;
int counter = 0;
function bit [7:0] get_val();
counter++;
return 25;
endfunction
initial begin
str_arr["test"] = 25;
str_key = "test";
if (!(str_arr[str_key] inside {[10:50]})) $stop;
if (str_arr[str_key] inside {[100:200]}) $stop;
int_arr[0] = 25;
int_key = 0;
if (!(int_arr[int_key] inside {[10:50]})) $stop;
if (int_arr[int_key] inside {[100:200]}) $stop;
if (!(get_val() inside {[10:50]})) $stop;
if (get_val() inside {[100:200]}) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule