Commentary: Fix warning documentation, add consistency test.
This commit is contained in:
parent
f57d1255e9
commit
f8f5f8f84b
|
|
@ -130,8 +130,9 @@ same time slot.
|
|||
Rising/falling/turn-off delays are currently unsupported and cause the
|
||||
:option:`RISEFALLDLY` warning.
|
||||
|
||||
Minimum/typical/maximum delays are currently unsupported. The typical delay is
|
||||
always the one chosen. Such expressions cause the :option:`MINTYPMAX` warning.
|
||||
Minimum/typical/maximum delays are currently unsupported. The typical delay
|
||||
is always the one chosen. Such expressions cause the :option:`MINTYPMAXDLY`
|
||||
warning.
|
||||
|
||||
Another consequence of using :vlopt:`--timing` is that the :vlopt:`--main`
|
||||
option generates a main file with a proper timing eval loop, eliminating the
|
||||
|
|
|
|||
|
|
@ -683,7 +683,7 @@ List Of Warnings
|
|||
generated C++ code to add appropriate prints to see what is going on.
|
||||
|
||||
|
||||
.. option:: ENDCAPSULATED
|
||||
.. option:: ENCAPSULATED
|
||||
|
||||
Warns that a class member is declared :code:`local` or
|
||||
:code:`protected`, but is being accessed from outside that class (if
|
||||
|
|
@ -1166,7 +1166,7 @@ List Of Warnings
|
|||
backwards compatibility, new projects should use :option:`ASCRANGE`.
|
||||
|
||||
|
||||
.. option:: MINTYPMAX
|
||||
.. option:: MINTYPMAXDLY
|
||||
|
||||
.. code-block:: sv
|
||||
|
||||
|
|
@ -2209,6 +2209,14 @@ List Of Warnings
|
|||
:option:`UNUSEDSIGNAL`.
|
||||
|
||||
|
||||
.. option:: UNUSEDLOOP
|
||||
|
||||
.. TODO better example
|
||||
|
||||
Warns that a loop condition is always false, and so the body of the loop
|
||||
will never be executed.
|
||||
|
||||
|
||||
.. option:: UNUSEDPARAM
|
||||
|
||||
.. TODO better example
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Primitive C++ style checker
|
||||
#
|
||||
# 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('dist')
|
||||
|
||||
root = ".."
|
||||
|
||||
Waivers = [
|
||||
'Internal',
|
||||
'Unsupported',
|
||||
'DIDNOTCONVERGE', # Runtime
|
||||
]
|
||||
|
||||
src_filename = "src/V3Error.h"
|
||||
doc_filename = "docs/guide/warnings.rst"
|
||||
|
||||
|
||||
def get_src_warns(root):
|
||||
args = {}
|
||||
for filename in test.glob_some(root + "/" + src_filename):
|
||||
with open(filename, "r", encoding="latin-1") as fh:
|
||||
state = 0
|
||||
lineno = 0
|
||||
for line in fh:
|
||||
lineno += 1
|
||||
line = line.rstrip()
|
||||
line = re.sub(r'\s*//.*', '', line)
|
||||
# print("S: %s" % line)
|
||||
if state == 0 and re.search(r'class V3ErrorCode', line):
|
||||
state = 1
|
||||
elif state == 1 and re.search(r'const names', line):
|
||||
state = 2
|
||||
elif state == 2 and re.search(r' return ', line):
|
||||
state = 3
|
||||
elif state == 2:
|
||||
for opt in re.findall(r'"([A-Z0-9]+)"', line):
|
||||
opt = opt_clean(opt)
|
||||
if test.verbose:
|
||||
print("S '" + opt + "' " + line)
|
||||
args[opt] = filename + ":" + str(lineno)
|
||||
return args
|
||||
|
||||
|
||||
def get_docs_warns(root):
|
||||
args = {}
|
||||
for filename in test.glob_some(root + "/" + doc_filename):
|
||||
with open(filename, "r", encoding="latin-1") as fh:
|
||||
lineno = 0
|
||||
last_opt = None
|
||||
for line in fh:
|
||||
lineno += 1
|
||||
line = line.rstrip()
|
||||
|
||||
m = re.search(r' option:: ([A-Za-z0-9]+)', line)
|
||||
if m:
|
||||
opt = opt_clean(m.group(1))
|
||||
if test.verbose:
|
||||
print("D '" + opt + "' " + line)
|
||||
args[opt] = filename + ":" + str(lineno)
|
||||
last_opt = opt
|
||||
|
||||
if last_opt and re.search(r'Historical', line):
|
||||
Waivers.append(last_opt)
|
||||
|
||||
return args
|
||||
|
||||
|
||||
def opt_clean(opt):
|
||||
return opt
|
||||
|
||||
|
||||
if not os.path.exists(root + "/.git"):
|
||||
test.skip("Not in a git repository")
|
||||
|
||||
srcs = get_src_warns(root)
|
||||
docs = get_docs_warns(root)
|
||||
if len(srcs) < 10:
|
||||
test.error(src_filename + ": Too few warnings found; parse error?")
|
||||
if len(docs) < 10:
|
||||
test.error(doc_filename + ": Too few warnings found; parse error?")
|
||||
|
||||
both = {}
|
||||
both.update(srcs)
|
||||
both.update(docs)
|
||||
|
||||
waiver = {k: 1 for k in Waivers}
|
||||
|
||||
for opt in sorted(both.keys()):
|
||||
if opt in waiver:
|
||||
continue
|
||||
src_ok = opt in srcs
|
||||
docs_ok = opt in docs
|
||||
|
||||
if not src_ok:
|
||||
test.error_keep_going(docs[opt] + ": Warn code documented in " + doc_filename + " '" +
|
||||
opt + "' not found in " + src_filename + " sources")
|
||||
elif not docs_ok:
|
||||
test.error_keep_going(srcs[opt] + ": Warn code documented in " + src_filename + " '" +
|
||||
opt + "' not found in " + doc_filename + " documentation")
|
||||
elif test.verbose:
|
||||
print(": ok '" + opt)
|
||||
|
||||
test.passes()
|
||||
Loading…
Reference in New Issue