Add NOTREDOP error on reduction and negation operators (#7417) (#7623) (#7624)

This commit is contained in:
Cookie 2026-05-27 00:20:15 +08:00 committed by GitHub
parent 9e2fedee6f
commit 9460501221
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 126 additions and 2 deletions

View File

@ -0,0 +1,7 @@
.. comment: generated by t_lint_notredop_bad
.. code-block::
%Error-NOTREDOP: example.v:1:17 Logical not directly before reduction operator is illegal
: ... Suggest use parentheses, e.g. '!(|expr)'
12 | assign y[0] = !|v;
| ^

View File

@ -1559,6 +1559,25 @@ List Of Warnings
:vlopt:`--no-timing` option.
.. option:: NOTREDOP
Error that a logical not operator is directly followed by an
unparenthesized reduction operator, such as ``!|a``. The IEEE 1800-2023 Annex A
grammar requires the operand of ``!`` to be a primary expression, not an
unparenthesized reduction expression.
For example:
.. include:: ../../docs/gen/ex_NOTREDOP_msg.rst
Some simulators support this syntax as an extension, but it is recommended to fix
these to match IEEE. To do so, add parentheses around the reduction expression,
for example use ``!(|a)`` instead of ``!|a``.
Suppressing this error will suppress the error message check; it will simulate
correctly.
.. option:: NULLPORT
Warns that a null port was detected in the module definition port

View File

@ -140,6 +140,7 @@ public:
NOLATCH, // No latch detected in always_latch block
NONSTD, // Non-standard feature present in other sims
NORETURN, // Function with no return
NOTREDOP, // Error: Logical not before reduction operator
NULLPORT, // Null port detected in module definition
PARAMNODEFAULT, // Parameter without default
PINCONNECTEMPTY,// Cell pin connected by name with empty reference
@ -232,7 +233,7 @@ public:
"IMPLICITSTATIC", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY",
"INSECURE", "INSIDETRUE", "LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP",
"MODMISSING", "MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD",
"NORETURN", "NULLPORT", "PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING",
"NORETURN", "NOTREDOP", "NULLPORT", "PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING",
"PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT",
"PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED", "PROTOTYPEMIS", "RANDC", "REALCVT",
"REDEFMACRO", "RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPECIFYIGN",
@ -270,7 +271,7 @@ public:
|| m_e == BLKLOOPINIT || m_e == CONTASSREG || m_e == ENCAPSULATED
|| 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 == NOTREDOP || m_e == PARAMNODEFAULT || m_e == PINNOTFOUND || m_e == PKGNODECL
|| m_e == PROCASSWIRE || m_e == PROTOTYPEMIS || m_e == SUPERNFIRST
|| m_e == ZEROREPL);
}

View File

@ -844,6 +844,15 @@ int V3ParseImp::tokenToBison() {
// Called as global since bison doesn't have our pointer
tokenPipelineSym(); // sets yylval
m_bisonLastFileline = yylval.fl;
if (m_tokenLastBison.token == '!'
&& (yylval.token == '&' || yylval.token == '|' || yylval.token == '^'
|| yylval.token == yP_NAND || yylval.token == yP_NOR || yylval.token == yP_XNOR)) {
m_tokenLastBison.fl->v3warn(
NOTREDOP,
"Logical not directly before reduction operator is illegal\n"
<< m_tokenLastBison.fl->warnMore()
<< "... Suggest use parentheses, e.g. '!(|expr)'");
}
m_tokenLastBison = yylval;
if (debug() >= 6 || debugFlex() >= 6

View File

@ -70,6 +70,7 @@ module t;
// verilator lint_off NOLATCH
// verilator lint_off NONSTD
// verilator lint_off NORETURN
// verilator lint_off NOTREDOP
// verilator lint_off NULLPORT
// verilator lint_off PARAMNODEFAULT
// verilator lint_off PINCONNECTEMPTY

View File

@ -0,0 +1,17 @@
#!/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('vlt')
test.lint(top_filename="t/t_lint_notredop_bad.v",
verilator_flags2=["-Wno-NOTREDOP"])
test.passes()

View File

@ -0,0 +1,30 @@
%Error-NOTREDOP: t/t_lint_notredop_bad.v:12:17: Logical not directly before reduction operator is illegal
: ... Suggest use parentheses, e.g. '!(|expr)'
12 | assign y[0] = !|v;
| ^
... For error description see https://verilator.org/warn/NOTREDOP?v=latest
%Error-NOTREDOP: t/t_lint_notredop_bad.v:13:17: Logical not directly before reduction operator is illegal
: ... Suggest use parentheses, e.g. '!(|expr)'
13 | assign y[1] = !&v;
| ^
%Error-NOTREDOP: t/t_lint_notredop_bad.v:14:17: Logical not directly before reduction operator is illegal
: ... Suggest use parentheses, e.g. '!(|expr)'
14 | assign y[2] = !^v;
| ^
%Error-NOTREDOP: t/t_lint_notredop_bad.v:15:17: Logical not directly before reduction operator is illegal
: ... Suggest use parentheses, e.g. '!(|expr)'
15 | assign y[3] = !~^v;
| ^
%Error-NOTREDOP: t/t_lint_notredop_bad.v:16:17: Logical not directly before reduction operator is illegal
: ... Suggest use parentheses, e.g. '!(|expr)'
16 | assign y[4] = !^~v;
| ^
%Error-NOTREDOP: t/t_lint_notredop_bad.v:17:17: Logical not directly before reduction operator is illegal
: ... Suggest use parentheses, e.g. '!(|expr)'
17 | assign y[5] = !~&v;
| ^
%Error-NOTREDOP: t/t_lint_notredop_bad.v:18:17: Logical not directly before reduction operator is illegal
: ... Suggest use parentheses, e.g. '!(|expr)'
18 | assign y[6] = !~|v;
| ^
%Error: Exiting due to

View File

@ -0,0 +1,20 @@
#!/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('vlt')
test.lint(fails=True, expect_filename=test.golden_filename)
test.extract(in_filename=test.golden_filename,
out_filename=test.root + "/docs/gen/ex_NOTREDOP_msg.rst",
lines="1-4")
test.passes()

View File

@ -0,0 +1,20 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Zhi QU
// SPDX-License-Identifier: CC0-1.0
module t (
input logic [3:0] v,
output logic [6:0] y
);
assign y[0] = !|v;
assign y[1] = !&v;
assign y[2] = !^v;
assign y[3] = !~^v;
assign y[4] = !^~v;
assign y[5] = !~&v;
assign y[6] = !~|v;
endmodule