Internals: Refactor V3Error, and handle UNDRIVEN/UNSUPPORTED/WIDTH consistently (#6874)

This commit is contained in:
Wilson Snyder 2025-12-30 07:08:25 -05:00 committed by GitHub
parent aa94219531
commit 2025b81614
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 120 additions and 134 deletions

View File

@ -2301,6 +2301,8 @@ List Of Warnings
make the design simulate incorrectly and is only intended for lint
usage; see the details under :vlopt:`--bbox-unsup`.
Disabling this error also disables :option:`COVERIGN` and
:option:`SPECIFYIGN`.
.. option:: UNUSED

View File

@ -166,9 +166,9 @@ void V3ErrorGuarded::v3errorEndGuts(const std::ostringstream& sstr, const string
if (m_errorSuppressed) {
// On debug, show only non default-off warning to prevent pages of warnings
if (m_message.code().defaultsOff()) return;
if (!debug() || debug() < 3 || (debug() < 9 && m_showedSuppressed[m_message.code()]))
if (!debug() || debug() < 3 || (debug() < 9 && m_showedSuppressed.test(m_message.code())))
return;
m_showedSuppressed[m_message.code()] = true;
m_showedSuppressed.set(m_message.code(), true);
}
string msg
= V3Error::warnContextBegin() + msgPrefix() + V3Error::warnContextEnd() + sstr.str();
@ -223,8 +223,8 @@ void V3ErrorGuarded::v3errorEndGuts(const std::ostringstream& sstr, const string
const bool anError = isError(m_message.code(), m_errorSuppressed);
if (m_message.code()
!= V3ErrorCode::EC_FATALMANY // Not verbose on final too-many-errors error
&& !m_describedEachWarn[m_message.code()]) {
m_describedEachWarn[m_message.code()] = true;
&& !m_describedEachWarn.test(m_message.code())) {
m_describedEachWarn.set(m_message.code(), true);
if (m_message.code() >= V3ErrorCode::EC_FIRST_NAMED) {
text += warnMoreSpaces() + "... For " + (anError ? "error" : "warning")
+ " description see " + m_message.code().url() + '\n';
@ -238,7 +238,7 @@ void V3ErrorGuarded::v3errorEndGuts(const std::ostringstream& sstr, const string
text += warnMoreSpaces() + "... See the manual at " + m_message.code().url()
+ " for more assistance.\n";
}
if (!m_pretendError[m_message.code()] && !m_message.code().hardError()) {
if (!m_pretendError.test(m_message.code()) && !m_message.code().hardError()) {
text += warnMoreSpaces() + "... Use \"/* verilator lint_off "
+ m_message.code().ascii()
+ " */\" and lint_on around source to disable this message.\n";

View File

@ -20,6 +20,7 @@
#include "config_build.h"
#include "verilatedos.h"
#include "V3Hash.h"
#include "V3Mutex.h"
// Limited V3 headers here - this is a base class for Vlc etc
@ -56,9 +57,9 @@ public:
I_COVERAGE, // Coverage is on/off from /*verilator coverage_on/off*/
I_DEF_NETTYPE_WIRE, // `default_nettype is WIRE (false=NONE)
I_LINT, // All lint messages
I_STYLE, // All style messages
I_TIMING, // Enable timing from /*verilator timing_on/off*/
I_TRACING, // Tracing is on/off from /*verilator tracing_on/off*/
I_UNUSED, // Unused genvar, parameter or signal message (Backward Compatibility)
// Error codes:
E_CONSTWRITTEN, // Error: Const variable being written.
E_LIFETIME, // Error: Reference to a variable might outlive the variable.
@ -169,6 +170,7 @@ public:
UNOPTTHREADS, // Thread partitioner unable to fill all requested threads
UNPACKED, // Unsupported unpacked
UNSIGNED, // Comparison is constant due to unsigned arithmetic
UNUSED, // Unused genvar, parameter or signal message (Backward Compatibility)
UNUSEDGENVAR, // No receivers for genvar
UNUSEDLOOP, // Loop is unused
UNUSEDPARAM, // No receivers for parameters
@ -207,8 +209,8 @@ public:
// Leading spaces indicate it can't be disabled.
" MIN", " INFO", " FATAL", " FATALMANY", " FATALSRC", " ERROR", " FIRST_NAMED",
// Boolean
" I_CELLDEFINE", " I_COVERAGE", " I_DEF_NETTYPE_WIRE", " I_LINT", " I_TIMING",
" I_TRACING", " I_UNUSED",
" I_CELLDEFINE", " I_COVERAGE", " I_DEF_NETTYPE_WIRE", " I_LINT", " I_STYLE",
" I_TIMING", " I_TRACING",
// Errors
"CONSTWRITTEN", "LIFETIME", "NEEDTIMINGOPT", "NOTIMING", "PORTSHORT", "TASKNSVAR",
"UNSUPPORTED",
@ -229,10 +231,10 @@ public:
"REDEFMACRO", "RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPECIFYIGN",
"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"};
"UNPACKED", "UNSIGNED", "UNUSED", "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
@ -267,8 +269,8 @@ public:
}
// Warnings to mention manual
bool mentionManual() const VL_MT_SAFE {
return (m_e == EC_FATALSRC || m_e == SIDEEFFECT || m_e == SYMRSVDWORD || m_e == ZERODLY
|| pretendError());
return (pretendError() || m_e == EC_FATALSRC || m_e == SIDEEFFECT || m_e == SYMRSVDWORD
|| m_e == ZERODLY);
}
// Warnings that are lint only
bool lintError() const VL_MT_SAFE {
@ -290,33 +292,56 @@ public:
|| m_e == UNUSEDLOOP || m_e == UNUSEDPARAM || m_e == UNUSEDSIGNAL
|| m_e == VARHIDDEN);
}
// Warnings that are unused only
bool unusedError() const VL_MT_SAFE {
return (m_e == UNUSEDGENVAR || m_e == UNUSEDLOOP || m_e == UNUSEDPARAM
|| m_e == UNUSEDSIGNAL);
}
bool isNamed() const { return m_e >= EC_FIRST_NAMED; }
private:
V3ErrorCode renamedTo() const {
// Return a new error this error has been renamed to
if (m_e == LITENDIAN) return V3ErrorCode{ASCRANGE};
return V3ErrorCode{EC_MIN}; // Not renamed; see isRenamed()
}
bool isNamed() const { return m_e >= EC_FIRST_NAMED; }
bool isRenamed() const { return renamedTo() != V3ErrorCode{EC_MIN}; }
bool isUnder(V3ErrorCode other) {
// backwards compatibility inheritance-like warnings
if (m_e == other) return true;
if (other == V3ErrorCode::WIDTH) {
return (m_e == WIDTHEXPAND || m_e == WIDTHTRUNC || m_e == WIDTHXZEXPAND);
public:
// Call given callable on all error codes that result from given code.
// Deals with codes which imply disabling multiple other codes.
void forDelegateCodes(std::function<void(V3ErrorCode code)> action) const {
// If add to this switch, also update isUnder()
switch (m_e) {
case V3ErrorCode::E_UNSUPPORTED:
action(V3ErrorCode{E_UNSUPPORTED});
action(V3ErrorCode{COVERIGN});
action(V3ErrorCode{SPECIFYIGN});
return;
case V3ErrorCode::UNUSED:
action(V3ErrorCode{UNUSEDGENVAR});
action(V3ErrorCode{UNUSEDLOOP});
action(V3ErrorCode{UNUSEDPARAM});
action(V3ErrorCode{UNUSEDSIGNAL});
return;
case V3ErrorCode::WIDTH:
action(V3ErrorCode{WIDTHEXPAND});
action(V3ErrorCode{WIDTHTRUNC});
action(V3ErrorCode{WIDTHXZEXPAND});
return;
default: action(*this);
}
if (other == V3ErrorCode::I_UNUSED) {
return (m_e == UNUSEDGENVAR || m_e == UNUSEDLOOP || m_e == UNUSEDPARAM
|| m_e == UNUSEDSIGNAL);
}
bool isUnder(V3ErrorCode other) const {
// Reverse of forDelegateCodes, return true if this' code is under another
if (VL_LIKELY(other == m_e)) return true;
switch (other) {
case V3ErrorCode::E_UNSUPPORTED:
return m_e == E_UNSUPPORTED || m_e == COVERIGN || m_e == SPECIFYIGN;
case V3ErrorCode::UNUSED:
return m_e == UNUSEDGENVAR || m_e == UNUSEDLOOP || m_e == UNUSEDPARAM
|| m_e == UNUSEDSIGNAL;
case V3ErrorCode::WIDTH:
return m_e == WIDTHEXPAND || m_e == WIDTHTRUNC || m_e == WIDTHXZEXPAND;
default: return false;
}
return false;
}
string url() const;
static bool unusedMsg(const char* msgp) { return 0 == VL_STRCASECMP(msgp, "UNUSED"); }
};
constexpr bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) {
return lhs.m_e == rhs.m_e;
@ -329,6 +354,27 @@ inline std::ostream& operator<<(std::ostream& os, const V3ErrorCode& rhs) {
// ######################################################################
// Store a single bit for each error code
class VErrorBitSet final {
std::bitset<V3ErrorCode::_ENUM_MAX> m_bitset; // Enable for each code
VErrorBitSet(const VErrorBitSet& lhs, const VErrorBitSet& rhs)
: m_bitset{lhs.m_bitset & rhs.m_bitset} {}
public:
VErrorBitSet() {}
~VErrorBitSet() = default;
bool test(V3ErrorCode code) const { return m_bitset[code]; }
void set(V3ErrorCode code, bool flag) { m_bitset[code] = flag; }
V3Hash hash() const {
const size_t hashCode = std::hash<std::bitset<V3ErrorCode::_ENUM_MAX>>()(m_bitset);
return V3Hash{static_cast<uint64_t>(hashCode)};
}
VErrorBitSet operator&(const VErrorBitSet& rhs) const { return VErrorBitSet{*this, rhs}; }
bool operator==(const VErrorBitSet& rhs) const { return m_bitset == rhs.m_bitset; }
};
// ######################################################################
class VErrorMessage final {
// TYPES
using FileLines = std::deque<const FileLine*>;
@ -391,11 +437,11 @@ private:
int m_warnCount VL_GUARDED_BY(m_mutex) = 0; // Warning count
int m_errCount VL_GUARDED_BY(m_mutex) = 0; // Error count
// Pretend this warning is an error
std::array<bool, V3ErrorCode::_ENUM_MAX> m_pretendError VL_GUARDED_BY(m_mutex);
VErrorBitSet m_pretendError VL_GUARDED_BY(m_mutex);
// Told user specifics about this warning
std::array<bool, V3ErrorCode::_ENUM_MAX> m_describedEachWarn VL_GUARDED_BY(m_mutex);
VErrorBitSet m_describedEachWarn VL_GUARDED_BY(m_mutex);
// Debug about suppressed this warning
std::array<bool, V3ErrorCode::_ENUM_MAX> m_showedSuppressed VL_GUARDED_BY(m_mutex);
VErrorBitSet m_showedSuppressed VL_GUARDED_BY(m_mutex);
int m_debugDefault = 0; // Option: --debugi Default debugging level
int m_errorLimit VL_GUARDED_BY(m_mutex)
= MAX_ERRORS; // Option: --error-limit Number of errors before exit
@ -429,14 +475,10 @@ public:
bool isErrorOrWarn() VL_REQUIRES(m_mutex) {
return errorCount() || (warnFatal() && warnCount());
}
bool pretendError(V3ErrorCode code) VL_REQUIRES(m_mutex) { return m_pretendError[code]; }
bool pretendError(V3ErrorCode code) VL_REQUIRES(m_mutex) { return m_pretendError.test(code); }
void pretendError(V3ErrorCode code, bool flag) VL_REQUIRES(m_mutex) {
if (code == V3ErrorCode::WIDTH) {
m_pretendError[V3ErrorCode::WIDTHTRUNC] = flag;
m_pretendError[V3ErrorCode::WIDTHEXPAND] = flag;
m_pretendError[V3ErrorCode::WIDTHXZEXPAND] = flag;
}
m_pretendError[code] = flag;
code.forDelegateCodes([this, flag](V3ErrorCode subcode)
VL_REQUIRES(m_mutex) { m_pretendError.set(subcode, flag); });
}
int debugDefault() VL_MT_SAFE { return m_debugDefault; }
void debugDefault(int level) VL_MT_UNSAFE { m_debugDefault = level; }
@ -450,10 +492,10 @@ public:
bool errorSuppressed() VL_REQUIRES(m_mutex) { return m_errorSuppressed; }
void errorSuppressed(bool flag) VL_REQUIRES(m_mutex) { m_errorSuppressed = flag; }
bool describedEachWarn(V3ErrorCode code) VL_REQUIRES(m_mutex) {
return m_describedEachWarn[code];
return m_describedEachWarn.test(code);
}
void describedEachWarn(V3ErrorCode code, bool flag) VL_REQUIRES(m_mutex) {
m_describedEachWarn[code] = flag;
m_describedEachWarn.set(code, flag);
}
void suppressThisWarning() VL_REQUIRES(m_mutex);
string warnRelated(const FileLine* fl) VL_REQUIRES(m_mutex) {

View File

@ -126,21 +126,28 @@ FileLineSingleton::msgEnSetIdx_t FileLineSingleton::addMsgEnBitSet(const MsgEnBi
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::defaultMsgEnIndex() VL_MT_SAFE {
MsgEnBitSet msgEnBitSet;
for (int i = V3ErrorCode::EC_MIN; i < V3ErrorCode::_ENUM_MAX; ++i) {
const V3ErrorCode code{i};
// "-Wall" and the like only adjust the code subset, so use default enablement there
msgEnBitSet.set(MsgEnBitSet::Subset::CODE, i, !V3ErrorCode{i}.defaultsOff());
msgEnBitSet.set(MsgEnBitSet::Subset::CODE, code, !code.defaultsOff());
// The control file subset is only adjusted by the control files, everything enabled by
// default
msgEnBitSet.set(MsgEnBitSet::Subset::CTRL, i, true);
msgEnBitSet.set(MsgEnBitSet::Subset::CTRL, code, true);
}
return addMsgEnBitSet(msgEnBitSet);
}
FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnSetBit(msgEnSetIdx_t setIdx,
MsgEnBitSet::Subset subset,
size_t bitIdx, bool value) {
if (msgEn(setIdx).test(subset, bitIdx) == value) return setIdx;
V3ErrorCode code, bool value) {
// See if state matches existing
bool same = true;
code.forDelegateCodes([&](V3ErrorCode subcode) {
if (msgEn(setIdx).test(subset, subcode) != value) same = false;
});
if (same) return setIdx;
// Make new mask of all delegated codes at once (to avoid extra indicies if looped above this)
MsgEnBitSet msgEnBitSet{msgEn(setIdx)};
msgEnBitSet.set(subset, bitIdx, value);
code.forDelegateCodes([&](V3ErrorCode subcode) { msgEnBitSet.set(subset, subcode, value); });
return addMsgEnBitSet(msgEnBitSet);
}
@ -377,24 +384,13 @@ std::ostream& operator<<(std::ostream& os, FileLine* fileline) {
string FileLine::warnOffParse(const string& msgs, bool turnOff) {
string result;
for (const string& msg : VString::split(msgs, ',')) {
const char* cmsg = msg.c_str();
// Backward compatibility with msg="UNUSED"
if (V3ErrorCode::unusedMsg(cmsg)) {
warnOff(V3ErrorCode::UNUSEDGENVAR, turnOff);
warnOff(V3ErrorCode::UNUSEDLOOP, turnOff);
warnOff(V3ErrorCode::UNUSEDPARAM, turnOff);
warnOff(V3ErrorCode::UNUSEDSIGNAL, turnOff);
continue;
}
const V3ErrorCode code{msg};
if (!code.hardError()) {
warnOff(code, turnOff);
continue;
}
// Error if not suppressed
if (!v3Global.opt.isFuture(msg)) result = VString::dot(result, ",", cmsg);
if (!v3Global.opt.isFuture(msg)) result = VString::dot(result, ",", msg);
}
return result;
}
@ -413,20 +409,12 @@ void FileLine::warnStyleOff(bool turnOff) {
}
}
void FileLine::warnUnusedOff(bool turnOff) {
warnOff(V3ErrorCode::UNUSEDGENVAR, turnOff);
warnOff(V3ErrorCode::UNUSEDLOOP, turnOff);
warnOff(V3ErrorCode::UNUSEDPARAM, turnOff);
warnOff(V3ErrorCode::UNUSEDSIGNAL, turnOff);
}
bool FileLine::warnIsOff(V3ErrorCode code) const {
if (!msgEn().enabled(code)) return true;
if (!defaultFileLine().msgEn().enabled(code)) return true; // Global overrides local
if ((code.lintError() || code.styleError()) && !msgEn().enabled(V3ErrorCode::I_LINT)) {
return true;
}
if ((code.unusedError()) && !msgEn().enabled(V3ErrorCode::I_UNUSED)) return true;
return false;
}

View File

@ -26,7 +26,6 @@
#include "V3Mutex.h"
#include <atomic>
#include <bitset>
#include <deque>
#include <map>
#include <memory>
@ -50,8 +49,8 @@ class FileLineSingleton final {
using fileNameIdx_t = uint16_t; // Increase width if 64K input files are not enough
using msgEnSetIdx_t = uint16_t; // Increase width if 64K unique message sets are not enough
class MsgEnBitSet final {
std::bitset<V3ErrorCode::_ENUM_MAX> m_codeEn; // Enabeld by code directives/metacomments
std::bitset<V3ErrorCode::_ENUM_MAX> m_ctrlEn; // Enabled by control file
VErrorBitSet m_codeEn; // Enabled by code directives/metacomments
VErrorBitSet m_ctrlEn; // Enabled by control file
public:
enum class Subset {
@ -68,12 +67,8 @@ class FileLineSingleton final {
struct Hash final {
size_t operator()(const MsgEnBitSet& item) const {
const size_t hashCode
= std::hash<std::bitset<V3ErrorCode::_ENUM_MAX>>()(item.m_codeEn);
const size_t hashCtrl
= std::hash<std::bitset<V3ErrorCode::_ENUM_MAX>>()(item.m_ctrlEn);
V3Hash hash{static_cast<uint64_t>(hashCode)};
hash += static_cast<uint64_t>(hashCtrl);
V3Hash hash{item.m_codeEn.hash()};
hash += item.m_ctrlEn.hash();
return hash.value();
}
};
@ -86,11 +81,10 @@ class FileLineSingleton final {
return m_codeEn == other.m_codeEn && m_ctrlEn == other.m_ctrlEn;
}
bool test(Subset subset, size_t code) const {
bool test(Subset subset, V3ErrorCode code) const {
return subset == Subset::CODE ? m_codeEn.test(code) : m_ctrlEn.test(code);
}
void set(Subset subset, size_t code, bool value) {
void set(Subset subset, V3ErrorCode code, bool value) {
if (subset == Subset::CODE) {
m_codeEn.set(code, value);
} else {
@ -139,8 +133,8 @@ class FileLineSingleton final {
msgEnSetIdx_t addMsgEnBitSet(const MsgEnBitSet& bitSet) VL_MT_SAFE_EXCLUDES(m_mutex);
// Add index of default bitset
msgEnSetIdx_t defaultMsgEnIndex() VL_MT_SAFE;
// Set bitIdx to value in bitset at interned index setIdx, return interned index of result
msgEnSetIdx_t msgEnSetBit(msgEnSetIdx_t setIdx, MsgEnBitSet::Subset subset, size_t bitIdx,
// Set code to value in bitset at interned index setIdx, return interned index of result
msgEnSetIdx_t msgEnSetBit(msgEnSetIdx_t setIdx, MsgEnBitSet::Subset subset, V3ErrorCode code,
bool value);
// Return index to intersection set
msgEnSetIdx_t msgEnAnd(msgEnSetIdx_t lhsIdx, msgEnSetIdx_t rhsIdx);
@ -368,12 +362,6 @@ public:
// Turn on/off warning messages on this line.
private:
void warnSet(MsgEnBitSet::Subset subset, V3ErrorCode code, bool flag) {
if (code == V3ErrorCode::WIDTH) {
warnSet(subset, V3ErrorCode::WIDTHTRUNC, flag);
warnSet(subset, V3ErrorCode::WIDTHEXPAND, flag);
warnSet(subset, V3ErrorCode::WIDTHXZEXPAND, flag);
}
if (code == V3ErrorCode::E_UNSUPPORTED) warnSet(subset, V3ErrorCode::COVERIGN, flag);
m_msgEnIdx = singleton().msgEnSetBit(m_msgEnIdx, subset, code, flag);
}
@ -387,7 +375,6 @@ public:
bool warnIsOff(V3ErrorCode code) const VL_MT_SAFE;
void warnLintOff(bool turnOff);
void warnStyleOff(bool turnOff);
void warnUnusedOff(bool turnOff);
void warnStateFrom(const FileLine& from) { m_msgEnIdx = from.m_msgEnIdx; }
void warnResetDefault() { warnStateFrom(defaultFileLine()); }
@ -407,7 +394,6 @@ public:
static string builtInFilename() VL_MT_SAFE { return "<built-in>"; }
static void globalWarnLintOff(bool turnOff) { defaultFileLine().warnLintOff(turnOff); }
static void globalWarnStyleOff(bool turnOff) { defaultFileLine().warnStyleOff(turnOff); }
static void globalWarnUnusedOff(bool turnOff) { defaultFileLine().warnUnusedOff(turnOff); }
static void globalWarnOff(V3ErrorCode code, bool turnOff) {
defaultFileLine().warnOff(code, turnOff);
}

View File

@ -1863,12 +1863,6 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
FileLine::globalWarnLintOff(false);
FileLine::globalWarnStyleOff(false);
});
DECL_OPTION("-Werror-UNUSED", CbCall, []() {
V3Error::pretendError(V3ErrorCode::UNUSEDGENVAR, true);
V3Error::pretendError(V3ErrorCode::UNUSEDLOOP, true);
V3Error::pretendError(V3ErrorCode::UNUSEDPARAM, true);
V3Error::pretendError(V3ErrorCode::UNUSEDSIGNAL, true);
});
DECL_OPTION("-Werror-", CbPartialMatch, [this, fl](const char* optp) {
const V3ErrorCode code{optp};
if (code == V3ErrorCode::EC_ERROR) {
@ -1901,8 +1895,6 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
FileLine::globalWarnStyleOff(true);
});
DECL_OPTION("-Wno-style", CbCall, []() { FileLine::globalWarnStyleOff(true); });
DECL_OPTION("-Wno-UNUSED", CbCall, []() { FileLine::globalWarnUnusedOff(true); });
DECL_OPTION("-Wno-WIDTH", CbCall, []() { FileLine::globalWarnOff(V3ErrorCode::WIDTH, true); });
DECL_OPTION("-work", Set, &m_work);
DECL_OPTION("-Wpedantic", CbCall, [this]() {
m_pedantic = true;
@ -1923,25 +1915,6 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc,
});
DECL_OPTION("-Wwarn-lint", CbCall, []() { FileLine::globalWarnLintOff(false); });
DECL_OPTION("-Wwarn-style", CbCall, []() { FileLine::globalWarnStyleOff(false); });
DECL_OPTION("-Wwarn-UNUSED", CbCall, []() {
FileLine::globalWarnUnusedOff(false);
V3Error::pretendError(V3ErrorCode::UNUSEDGENVAR, false);
V3Error::pretendError(V3ErrorCode::UNUSEDLOOP, false);
V3Error::pretendError(V3ErrorCode::UNUSEDSIGNAL, false);
V3Error::pretendError(V3ErrorCode::UNUSEDPARAM, false);
});
DECL_OPTION("-Wwarn-UNSUPPORTED", CbCall, []() {
FileLine::globalWarnOff(V3ErrorCode::E_UNSUPPORTED, false);
FileLine::globalWarnOff(V3ErrorCode::COVERIGN, false);
FileLine::globalWarnOff(V3ErrorCode::SPECIFYIGN, false);
V3Error::pretendError(V3ErrorCode::E_UNSUPPORTED, false);
V3Error::pretendError(V3ErrorCode::COVERIGN, false);
V3Error::pretendError(V3ErrorCode::SPECIFYIGN, false);
});
DECL_OPTION("-Wwarn-WIDTH", CbCall, []() {
FileLine::globalWarnOff(V3ErrorCode::WIDTH, false);
V3Error::pretendError(V3ErrorCode::WIDTH, false);
});
DECL_OPTION("-waiver-multiline", OnOff, &m_waiverMultiline);
DECL_OPTION("-waiver-output", Set, &m_waiverOutput);

View File

@ -8129,10 +8129,8 @@ vltOffFront<errcodeen>:
| yVLT_TRACING_OFF { $$ = V3ErrorCode::I_TRACING; }
| yVLT_LINT_OFF { $$ = V3ErrorCode::I_LINT; }
| yVLT_LINT_OFF yVLT_D_RULE idAny
{ const char *codemsg = (*$3).c_str();
if (V3ErrorCode::unusedMsg(codemsg)) $$ = V3ErrorCode::I_UNUSED;
else {$$ = V3ErrorCode{codemsg}; }
if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown error code: '" << *$3 << "'"); } }
{ $$ = V3ErrorCode{*$3};
if ($$ == V3ErrorCode::EC_ERROR) $1->v3error("Unknown error code: '" << *$3 << "'"); }
;
vltOnFront<errcodeen>:
@ -8141,10 +8139,8 @@ vltOnFront<errcodeen>:
| yVLT_TRACING_ON { $$ = V3ErrorCode::I_TRACING; }
| yVLT_LINT_ON { $$ = V3ErrorCode::I_LINT; }
| yVLT_LINT_ON yVLT_D_RULE idAny
{ const char *codemsg = (*$3).c_str();
if (V3ErrorCode::unusedMsg(codemsg)) $$ = V3ErrorCode::I_UNUSED;
else {$$ = V3ErrorCode{codemsg}; }
if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown error code: '" << *$3 << "'"); } }
{ $$ = V3ErrorCode{*$3};
if ($$ == V3ErrorCode::EC_ERROR) $1->v3error("Unknown error code: '" << *$3 << "'"); }
;
vltDBlock<strp>: // --block <arg>

View File

@ -11,6 +11,8 @@ import vltest_bootstrap
test.scenarios('linter')
test.lint(verilator_flags2=["-Wwarn-lint"], fails=True, expect_filename=test.golden_filename)
test.lint(verilator_flags2=["-Wwarn-lint -Wno-style"],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -14,7 +14,6 @@
module t;
reg width_warn_var_line18 = 2'b11; // Width warning - must be line 18
reg width_warn2_var_line19 = 2'b11; // Width warning - must be line 19

View File

@ -8,12 +8,12 @@
lint_off -rule DEPRECATED -file "t/t_vlt_warn.vlt" -lines 14
lint_off -rule CASEINCOMPLETE -file "t/t_vlt_warn.v"
lint_off -rule WIDTH -file "t/t_vlt_warn.v" -lines 19
lint_off -rule WIDTH -file "t/t_vlt_warn.v" -lines 18
lint_off -rule DECLFILENAME -file "*/t_vlt_warn.v"
// Test wildcard filenames
lint_off -rule WIDTH -file "*/t_vlt_warn.v" -lines 20-20
// Test wildcard filenames, and WIDTH delegating to WIDTHTRUNC
lint_off -rule WIDTH -file "*/t_vlt_warn.v" -lines 19-19
// Test global disables
lint_off -file "*/t_vlt_warn.v" -lines 21-21
lint_off -file "*/t_vlt_warn.v" -lines 20-20
// Test match
lint_off -rule UNUSED -file "*/t_vlt_warn.v" -match "Signal is not used: 'width_warn*'"

View File

@ -1,6 +1,6 @@
%Warning-WIDTHTRUNC: t/t_vlt_warn.v:21:33: Operator ASSIGN expects 1 bits on the Assign RHS, but Assign RHS's CONST '2'h3' generates 2 bits.
%Warning-WIDTHTRUNC: t/t_vlt_warn.v:20:33: Operator ASSIGN expects 1 bits on the Assign RHS, but Assign RHS's CONST '2'h3' generates 2 bits.
: ... note: In instance 't'
21 | reg width_warn3_var_line20 = 2'b11;
20 | reg width_warn3_var_line20 = 2'b11;
| ^~~~~
... For warning description see https://verilator.org/warn/WIDTHTRUNC?v=latest
... Use "/* verilator lint_off WIDTHTRUNC */" and lint_on around source to disable this message.

View File

@ -10,8 +10,6 @@ lint_off -rule CASEINCOMPLETE -file "t/t_vlt_warn.v"
lint_off -rule WIDTH -file "t/t_vlt_warn.v" -lines 18
// Test wildcard filenames
lint_off -rule WIDTH -file "*/t_vlt_warn.v" -lines 19-19
// Test global disables
lint_off -file "*/t_vlt_warn.v" -lines 20-20
coverage_off -file "t/t_vlt_warn.v"
// Test --flag is also accepted