Throw warning if static variable is declared in a loop (#4018)

Signed-off-by: Ryszard Rozak <rrozak@antmicro.com>
This commit is contained in:
Ryszard Rozak 2023-03-14 10:03:08 +01:00 committed by GitHub
parent 1d0a06438c
commit ed1a9309d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 79 additions and 3 deletions

View File

@ -65,6 +65,7 @@ private:
int m_genblkAbove = 0; // Begin block number of if/case/for above
int m_genblkNum = 0; // Begin block number, 0=none seen
VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime
bool m_insideLoop = false; // True if the node is inside a loop
// METHODS
void cleanFileline(AstNode* nodep) {
@ -222,6 +223,9 @@ private:
void visit(AstVar* nodep) override {
cleanFileline(nodep);
if (nodep->lifetime().isStatic() && m_insideLoop) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: Static variable inside a loop");
}
if (nodep->lifetime().isNone() && nodep->varType() != VVarType::PORT) {
nodep->lifetime(m_lifetime);
}
@ -459,6 +463,8 @@ private:
// 2. ASTSELBIT(first, var0))
// 3. ASTSELLOOPVARS(first, var0..var1))
// 4. DOT(DOT(first, second), ASTSELBIT(third, var0))
VL_RESTORER(m_insideLoop);
m_insideLoop = true;
AstNode* bracketp = nodep->arrayp();
while (AstDot* dotp = VN_CAST(bracketp, Dot)) bracketp = dotp->rhsp();
if (AstSelBit* const selp = VN_CAST(bracketp, SelBit)) {
@ -471,14 +477,34 @@ private:
} else if (VN_IS(bracketp, SelLoopVars)) {
// Ok
} else {
nodep->v3error(
"Syntax error; foreach missing bracketed loop variable (IEEE 1800-2017 12.7.3)");
nodep->v3error("Syntax error; foreach missing bracketed loop variable (IEEE "
"1800-2017 12.7.3)");
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
}
iterateChildren(nodep);
}
void visit(AstRepeat* nodep) override {
VL_RESTORER(m_insideLoop);
{
m_insideLoop = true;
iterateChildren(nodep);
}
}
void visit(AstDoWhile* nodep) override {
VL_RESTORER(m_insideLoop);
{
m_insideLoop = true;
iterateChildren(nodep);
}
}
void visit(AstWhile* nodep) override {
VL_RESTORER(m_insideLoop);
{
m_insideLoop = true;
iterateChildren(nodep);
}
}
void visit(AstNodeModule* nodep) override {
V3Config::applyModule(nodep);

View File

@ -0,0 +1,5 @@
%Error-UNSUPPORTED: t/t_static_in_loop_unsup.v:14:24: Unsupported: Static variable inside a loop
14 | static int a = 0;
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,26 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2023 by Antmicro Ltd.
// SPDX-License-Identifier: CC0-1.0
module t;
initial begin
int x = 0;
while (x < 10) begin : outer_loop
int y = 0;
while (y < x) begin : inner_loop
static int a = 0;
a++;
y++;
end
x++;
end
if (outer_loop.inner_loop.a != 45) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule