Add SUPERNFIRST error on super.new on non-first statement (#6784).
This commit is contained in:
parent
d467fda7c6
commit
075d624b29
1
Changes
1
Changes
|
|
@ -18,6 +18,7 @@ Verilator 5.043 devel
|
|||
* Add `-param`/`-port` options to `public_flat*` control directives (#6685). [Geza Lore, Fractile Ltd.]
|
||||
* Add `--top` specifying `config` name (#6710). [Dan Ruelas-Petrisko]
|
||||
* Add `sc_biguint` pragma (#6712). [Jakub Wasilewski, Antmicro Ltd.]
|
||||
* Add SUPERNFIRST error on super.new on non-first statement (#6784). [Artur Bieniek]
|
||||
* Support `std::randomize(){...}` (#4706) (#6573). [Yilou Wang]
|
||||
* Support `config` instance clauses (#5891 partial) (#6745). [Dan Ruelas-Petrisko]
|
||||
* Support unpacked struct in localparam (#6053 partial) (#6708). [Jonathan Drolet]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
.. comment: generated by t_class_new_supernfirst_bad
|
||||
.. code-block:: sv
|
||||
:linenos:
|
||||
:emphasize-lines: 3
|
||||
|
||||
function new();
|
||||
int x = $random();
|
||||
super.new(build_coverage(x), x); // <--- BAD, must be first statement
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
.. comment: generated by t_class_new_supernfirst_bad
|
||||
.. code-block::
|
||||
|
||||
%Error-SUPERNFIRST: example.v:1:11 'super.new' must be first statement in a 'function new' (IEEE 1800-2023 8.15)
|
||||
|
|
@ -2003,6 +2003,24 @@ List Of Warnings
|
|||
* Run Verilator with :vlopt:`--timing`.
|
||||
|
||||
|
||||
.. option:: SUPERNFIRST
|
||||
|
||||
An error that a `super.new` is not the first statement in a `function
|
||||
new`.
|
||||
|
||||
IEEE requires this error. Ignoring this warning may cause other errors
|
||||
or initialization ordering surprises, as described in IEEE 1800-2023
|
||||
8.15.
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. include:: ../../docs/gen/ex_SUPERNFIRST_faulty.rst
|
||||
|
||||
Results in:
|
||||
|
||||
.. include:: ../../docs/gen/ex_SUPERNFIRST_msg.rst
|
||||
|
||||
|
||||
.. option:: SYMRSVDWORD
|
||||
|
||||
Warning that a symbol matches a C++ reserved word, and using this as a
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ public:
|
|||
SPLITVAR, // Cannot split the variable
|
||||
STATICVAR, // Static variable declared in a loop with a declaration assignment
|
||||
STMTDLY, // Delayed statement
|
||||
SUPERNFIRST, // Super.new must be first statement
|
||||
SYMRSVDWORD, // Symbol is Reserved Word
|
||||
SYNCASYNCNET, // Mixed sync + async reset
|
||||
TICKCOUNT, // Too large tick count
|
||||
|
|
@ -224,11 +225,12 @@ public:
|
|||
"PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT",
|
||||
"PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED", "PROTOTYPEMIS", "RANDC", "REALCVT",
|
||||
"REDEFMACRO", "RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPECIFYIGN",
|
||||
"SPLITVAR", "STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT",
|
||||
"TIMESCALEMOD", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS", "UNPACKED",
|
||||
"UNSIGNED", "UNUSEDGENVAR", "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR",
|
||||
"USERFATAL", "USERINFO", "USERWARN", "VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT",
|
||||
"WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"};
|
||||
"SPLITVAR", "STATICVAR", "STMTDLY", "SUPERNFIRST", "SYMRSVDWORD", "SYNCASYNCNET",
|
||||
"TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
|
||||
"UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL",
|
||||
"USERERROR", "USERFATAL", "USERINFO", "USERWARN", "VARHIDDEN", "WAITCONST", "WIDTH",
|
||||
"WIDTHCONCAT", "WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL",
|
||||
" MAX"};
|
||||
return names[m_e];
|
||||
}
|
||||
// Warnings that default to off
|
||||
|
|
@ -258,8 +260,8 @@ public:
|
|||
|| m_e == ENDLABEL || m_e == ENUMITEMWIDTH || m_e == ENUMVALUE || m_e == HIERPARAM
|
||||
|| m_e == FUNCTIMECTL || m_e == IMPURE || m_e == MODMISSING
|
||||
|| m_e == PARAMNODEFAULT || m_e == PINNOTFOUND || m_e == PKGNODECL
|
||||
|| m_e == PROCASSWIRE || m_e == PROTOTYPEMIS || m_e == ZEROREPL // Says IEEE
|
||||
);
|
||||
|| m_e == PROCASSWIRE || m_e == PROTOTYPEMIS || m_e == SUPERNFIRST
|
||||
|| m_e == ZEROREPL);
|
||||
}
|
||||
// Warnings to mention manual
|
||||
bool mentionManual() const VL_MT_SAFE {
|
||||
|
|
|
|||
|
|
@ -6337,6 +6337,33 @@ class WidthVisitor final : public VNVisitor {
|
|||
nodep->v3error("class 'new()' cannot be virual (IEEE 1800-2023 18.3)");
|
||||
if (nodep->isStatic())
|
||||
nodep->v3error("class 'new()' cannot be static (IEEE 1800-2023 18.3)");
|
||||
AstNode* firstp = nullptr;
|
||||
for (AstNode* itemp = nodep->stmtsp(); itemp; itemp = itemp->nextp()) {
|
||||
if (AstStmtExpr* const sep = VN_CAST(itemp, StmtExpr)) {
|
||||
if (AstNew* const newp = VN_CAST(sep->exprp(), New)) {
|
||||
if (firstp) {
|
||||
UINFOTREE(1, firstp, "", "-earlier");
|
||||
newp->v3warn(SUPERNFIRST,
|
||||
"'super.new' must be first statement in a 'function "
|
||||
"new' (IEEE 1800-2023 8.15)\n"
|
||||
<< newp->warnContextPrimary() << '\n'
|
||||
<< firstp->warnOther()
|
||||
<< "... Location of earlier statement\n"
|
||||
<< firstp->warnContextSecondary());
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (AstVar* const varp = VN_CAST(itemp, Var)) {
|
||||
if (!varp->valuep() || VN_CAST(varp->valuep(), Const) || varp->isIO())
|
||||
continue;
|
||||
}
|
||||
if (AstAssign* const aitemp = VN_CAST(itemp, Assign)) {
|
||||
if (VN_IS(aitemp->rhsp(), Const)) continue;
|
||||
}
|
||||
firstp = itemp;
|
||||
}
|
||||
}
|
||||
// Function hasn't been widthed, so make it so.
|
||||
// Would use user1 etc, but V3Width called from too many places to spend a user
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
%Error-SUPERNFIRST: t/t_class_new_supernfirst_bad.v:20:11: 'super.new' must be first statement in a 'function new' (IEEE 1800-2023 8.15)
|
||||
: ... note: In instance 't'
|
||||
20 | super.new(build_coverage(x), x);
|
||||
| ^~~
|
||||
t/t_class_new_supernfirst_bad.v:19:13: ... Location of earlier statement
|
||||
19 | int x = $random();
|
||||
| ^~~~~~~
|
||||
... For error description see https://verilator.org/warn/SUPERNFIRST?v=latest
|
||||
%Error: Exiting due to
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2025 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
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('linter')
|
||||
|
||||
test.lint(verilator_flags2=['--timing'], fails=True, expect_filename=test.golden_filename)
|
||||
|
||||
test.extract(in_filename=test.top_filename,
|
||||
out_filename=test.root + "/docs/gen/ex_SUPERNFIRST_faulty.rst",
|
||||
lines="18-20")
|
||||
|
||||
test.extract(in_filename=test.golden_filename,
|
||||
out_filename=test.root + "/docs/gen/ex_SUPERNFIRST_msg.rst",
|
||||
regexp=r'SUPERNFIRST:')
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2025 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
class base_reg_block;
|
||||
function new(string name, int x);
|
||||
if (name == x) $finish;
|
||||
endfunction
|
||||
|
||||
function string build_coverage(int x);
|
||||
return $sformatf("%0d", x);
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class spi_reg_block extends base_reg_block;
|
||||
function new();
|
||||
int x = $random();
|
||||
super.new(build_coverage(x), x); // <--- BAD, must be first statement
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
initial begin
|
||||
spi_reg_block test = new;
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Loading…
Reference in New Issue