forked from github/verilator
Show included-from filenames in warnings, bug1439.
This commit is contained in:
parent
951521320a
commit
8e7559c6c9
2
Changes
2
Changes
@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
* Verilator 4.017 devel
|
||||
|
||||
**** Show included-from filenames in warnings, bug1439. [Todd Strader]
|
||||
|
||||
**** Fix not reporting some duplicate signals/ports, bug1462. [Peter Gerst]
|
||||
|
||||
|
||||
|
@ -1092,10 +1092,6 @@ void AstNode::v3errorEnd(std::ostringstream& str) const {
|
||||
}
|
||||
}
|
||||
|
||||
string AstNode::warnMore() const {
|
||||
return fileline()->warnMore();
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
// Data type conversion
|
||||
|
||||
|
@ -1408,7 +1408,10 @@ public:
|
||||
// METHODS - dump and error
|
||||
void v3errorEnd(std::ostringstream& str) const;
|
||||
void v3errorEndFatal(std::ostringstream& str) const VL_ATTR_NORETURN;
|
||||
string warnMore() const;
|
||||
string warnContextPrimary() const { return fileline()->warnContextPrimary(); }
|
||||
string warnContextSecondary() const { return fileline()->warnContextSecondary(); }
|
||||
string warnMore() const { return fileline()->warnMore(); }
|
||||
|
||||
virtual void dump(std::ostream& str=std::cout);
|
||||
void dumpGdb(); // For GDB only
|
||||
void dumpGdbHeader() const;
|
||||
|
@ -166,7 +166,10 @@ private:
|
||||
MULTIDRIVEN, "Signal has multiple driving blocks with different clocking: "
|
||||
<<varrefp->varp()->prettyName()<<endl
|
||||
<<varrefp->warnMore()<<"... Location of first driving block"<<endl
|
||||
<<oldactivep->warnMore()<<"... Location of other driving block");
|
||||
<<varrefp->varp()->warnContextPrimary()<<endl
|
||||
<<oldactivep->warnMore()<<"... Location of other driving block"<<endl
|
||||
<<oldactivep->warnContextSecondary()
|
||||
);
|
||||
varrefp->varp()->user2(true);
|
||||
}
|
||||
UINFO(4,"AssignDupDlyVar: "<<varrefp<<endl);
|
||||
|
@ -38,6 +38,7 @@ bool V3Error::s_warnFatal = true;
|
||||
int V3Error::s_tellManual = 0;
|
||||
std::ostringstream V3Error::s_errorStr; // Error string being formed
|
||||
V3ErrorCode V3Error::s_errorCode = V3ErrorCode::EC_FATAL;
|
||||
bool V3Error::s_errorContexted = false;
|
||||
bool V3Error::s_errorSuppressed = false;
|
||||
bool V3Error::s_describedEachWarn[V3ErrorCode::_ENUM_MAX];
|
||||
bool V3Error::s_describedWarnings = false;
|
||||
|
@ -225,6 +225,7 @@ class V3Error {
|
||||
static int s_tellManual; // Tell user to see manual, 0=not yet, 1=doit, 2=disable
|
||||
static std::ostringstream s_errorStr; // Error string being formed
|
||||
static V3ErrorCode s_errorCode; // Error string being formed will abort
|
||||
static bool s_errorContexted; // Error being formed got context
|
||||
static bool s_errorSuppressed; // Error being formed should be suppressed
|
||||
static MessagesSet s_messages; // What errors we've outputted
|
||||
static ErrorExitCb s_errorExitCb; // Callback when error occurs for dumping
|
||||
@ -246,6 +247,8 @@ class V3Error {
|
||||
static int errorCount() { return s_errCount; }
|
||||
static int warnCount() { return s_warnCount; }
|
||||
static int errorOrWarnCount() { return errorCount()+warnCount(); }
|
||||
static bool errorContexted() { return s_errorContexted; }
|
||||
static void errorContexted(bool flag) { s_errorContexted = flag; }
|
||||
// METHODS
|
||||
static void incErrors();
|
||||
static void incWarnings() { s_warnCount++; }
|
||||
@ -257,7 +260,7 @@ class V3Error {
|
||||
static bool isError(V3ErrorCode code, bool supp);
|
||||
static string lineStr(const char* filename, int lineno);
|
||||
static V3ErrorCode errorCode() { return s_errorCode; }
|
||||
static void errorExitCb(ErrorExitCb cb) { s_errorExitCb = cb; }
|
||||
static void errorExitCb(ErrorExitCb cb) { s_errorExitCb = cb; }
|
||||
|
||||
// When printing an error/warning, print prefix for multiline message
|
||||
static string warnMore();
|
||||
@ -265,7 +268,8 @@ class V3Error {
|
||||
// Internals for v3error()/v3fatal() macros only
|
||||
// Error end takes the string stream to output, be careful to seek() as needed
|
||||
static void v3errorPrep(V3ErrorCode code) {
|
||||
s_errorStr.str(""); s_errorCode = code; s_errorSuppressed = false; }
|
||||
s_errorStr.str(""); s_errorCode = code;
|
||||
s_errorContexted = false; s_errorSuppressed = false; }
|
||||
static std::ostringstream& v3errorStr() { return s_errorStr; }
|
||||
static void vlAbort();
|
||||
static void v3errorEnd(std::ostringstream& sstr); // static, but often overridden in classes.
|
||||
|
@ -87,6 +87,7 @@ FileLine::FileLine(FileLine::EmptySecret) {
|
||||
// Sort of a singleton
|
||||
m_lineno = 0;
|
||||
m_filenameno = singleton().nameToNumber("AstRoot");
|
||||
m_parent = NULL;
|
||||
|
||||
m_warnOn = 0;
|
||||
for (int codei=V3ErrorCode::EC_MIN; codei<V3ErrorCode::_ENUM_MAX; codei++) {
|
||||
@ -239,7 +240,9 @@ void FileLine::v3errorEnd(std::ostringstream& str) {
|
||||
std::ostringstream nsstr;
|
||||
if (m_lineno) nsstr<<this;
|
||||
nsstr<<str.str();
|
||||
nsstr<<endl;
|
||||
if (warnIsOff(V3Error::errorCode())) V3Error::suppressThisWarning();
|
||||
else if (!V3Error::errorContexted()) nsstr<<warnContextPrimary();
|
||||
V3Error::v3errorEnd(nsstr);
|
||||
}
|
||||
|
||||
@ -251,6 +254,20 @@ string FileLine::warnMore() const {
|
||||
}
|
||||
}
|
||||
|
||||
string FileLine::warnContext(bool secondary) const {
|
||||
V3Error::errorContexted(true);
|
||||
string out = "";
|
||||
// TODO: Eventually print the original source code here
|
||||
if (!secondary) { // Avoid printing long paths on informational part of error
|
||||
for (FileLine* parentFl = parent(); parentFl; parentFl = parentFl->parent()) {
|
||||
if (parentFl->filenameIsGlobal()) break;
|
||||
out += parentFl->warnMore()+"... note: In file included from "
|
||||
+parentFl->filebasename()+"\n";
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
#ifdef VL_LEAK_CHECKS
|
||||
typedef vl_unordered_set<FileLine*> FileLineCheckSet;
|
||||
FileLineCheckSet fileLineLeakChecks;
|
||||
|
@ -72,6 +72,7 @@ protected:
|
||||
class FileLine {
|
||||
int m_lineno;
|
||||
int m_filenameno;
|
||||
FileLine* m_parent; // Parent line that included this line
|
||||
std::bitset<V3ErrorCode::_ENUM_MAX> m_warnOn;
|
||||
|
||||
private:
|
||||
@ -95,6 +96,7 @@ protected:
|
||||
void lineno(int num) { m_lineno = num; }
|
||||
void language(V3LangCode lang) { singleton().numberToLang(m_filenameno, lang); }
|
||||
void filename(const string& name) { m_filenameno = singleton().nameToNumber(name); }
|
||||
void parent(FileLine* fileline) { m_parent = fileline; }
|
||||
void lineDirective(const char* textp, int& enterExitRef);
|
||||
void linenoInc() { m_lineno++; }
|
||||
void linenoIncInPlace() { m_lineno++; }
|
||||
@ -103,11 +105,13 @@ public:
|
||||
FileLine(const string& filename, int lineno) {
|
||||
m_lineno = lineno;
|
||||
m_filenameno = singleton().nameToNumber(filename);
|
||||
m_parent = NULL;
|
||||
m_warnOn = defaultFileLine().m_warnOn;
|
||||
}
|
||||
explicit FileLine(FileLine* fromp) {
|
||||
m_lineno = fromp->m_lineno;
|
||||
m_filenameno = fromp->m_filenameno;
|
||||
m_parent = fromp->m_parent;
|
||||
m_warnOn = fromp->m_warnOn;
|
||||
}
|
||||
explicit FileLine(EmptySecret);
|
||||
@ -121,6 +125,7 @@ public:
|
||||
#endif
|
||||
|
||||
int lineno() const { return m_lineno; }
|
||||
FileLine* parent() const { return m_parent; }
|
||||
V3LangCode language() const { return singleton().numberToLang(m_filenameno); }
|
||||
string ascii() const;
|
||||
const string filename() const { return singleton().numberToName(m_filenameno); }
|
||||
@ -132,6 +137,7 @@ public:
|
||||
const string profileFuncname() const;
|
||||
const string xml() const { return "fl=\""+filenameLetters()+cvtToStr(lineno())+"\""; }
|
||||
string lineDirectiveStrg(int enterExit) const;
|
||||
|
||||
// Turn on/off warning messages on this line.
|
||||
void warnOn(V3ErrorCode code, bool flag) { m_warnOn.set(code, flag); }
|
||||
void warnOff(V3ErrorCode code, bool flag) { warnOn(code, !flag); }
|
||||
@ -173,13 +179,21 @@ public:
|
||||
// OPERATORS
|
||||
void v3errorEnd(std::ostringstream& str);
|
||||
void v3errorEndFatal(std::ostringstream& str);
|
||||
/// When building an error, prefix for printing continuation lines
|
||||
string warnMore() const;
|
||||
/// When building an error, current location in include etc
|
||||
/// If not used in a given error, automatically pasted at end of error
|
||||
string warnContextPrimary() const { return warnContext(false); }
|
||||
/// When building an error, additional location for additional references
|
||||
/// Simplified information vs warnContextPrimary() to make dump clearer
|
||||
string warnContextSecondary() const { return warnContext(true); }
|
||||
inline bool operator==(FileLine rhs) const {
|
||||
return (m_lineno==rhs.m_lineno && m_filenameno==rhs.m_filenameno
|
||||
&& m_warnOn==rhs.m_warnOn);
|
||||
}
|
||||
private:
|
||||
void v3errorEndFatalGuts(std::ostringstream& str);
|
||||
string warnContext(bool secondary) const;
|
||||
};
|
||||
std::ostream& operator<<(std::ostream& os, FileLine* fileline);
|
||||
|
||||
|
@ -824,7 +824,9 @@ void GateVisitor::warnSignals() {
|
||||
vscp->v3warn(SYNCASYNCNET, "Signal flopped as both synchronous and async: "
|
||||
<<vscp->prettyName()<<endl
|
||||
<<ap->warnMore()<<"... Location of async usage"<<endl
|
||||
<<sp->warnMore()<<"... Location of sync usage"<<endl);
|
||||
<<ap->warnContextPrimary()<<endl
|
||||
<<sp->warnMore()<<"... Location of sync usage"<<endl
|
||||
<<sp->warnContextSecondary());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -464,7 +464,9 @@ private:
|
||||
|| nodep->fileline()->warnIsOff(V3ErrorCode::MODDUP))) {
|
||||
nodep->v3warn(MODDUP, "Duplicate declaration of module: "
|
||||
<<nodep->prettyName()<<endl
|
||||
<<foundp->warnMore()<<"... Location of original declaration");
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<foundp->warnMore()<<"... Location of original declaration"<<endl
|
||||
<<foundp->warnContextSecondary());
|
||||
}
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep); VL_DANGLING(nodep);
|
||||
|
@ -227,12 +227,16 @@ public:
|
||||
if (nodep->type() == fnodep->type()) {
|
||||
nodep->v3error("Duplicate declaration of "<<nodeTextType(fnodep)
|
||||
<<": "<<nodep->prettyName()<<endl
|
||||
<<fnodep->warnMore()<<"... Location of original declaration");
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<fnodep->warnMore()<<"... Location of original declaration\n"
|
||||
<<fnodep->warnContextSecondary());
|
||||
} else {
|
||||
nodep->v3error("Unsupported in C: "<<ucfirst(nodeTextType(nodep))
|
||||
<<" has the same name as "
|
||||
<<nodeTextType(fnodep)<<": "<<nodep->prettyName()<<endl
|
||||
<<fnodep->warnMore()<<"... Location of original declaration");
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<fnodep->warnMore()<<"... Location of original declaration\n"
|
||||
<<fnodep->warnContextSecondary());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -945,7 +949,9 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
<<(ansiWarn
|
||||
? findvarp->warnMore()+"... note: ANSI ports must have type declared with the I/O (IEEE 2017 23.2.2.2)\n"
|
||||
: "")
|
||||
<<findvarp->warnMore()<<"... Location of original declaration");
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<findvarp->warnMore()<<"... Location of original declaration"<<endl
|
||||
<<findvarp->warnContextSecondary());
|
||||
// Combining most likely reduce other errors
|
||||
findvarp->combineType(nodep);
|
||||
findvarp->fileline()->modifyStateInherit(nodep->fileline());
|
||||
@ -972,8 +978,10 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
&& !foundp->nodep()->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) {
|
||||
nodep->v3warn(VARHIDDEN, "Declaration of signal hides declaration in upper scope: "
|
||||
<<nodep->prettyName()<<endl
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<foundp->nodep()->warnMore()
|
||||
<<"... Location of original declaration");
|
||||
<<"... Location of original declaration\n"
|
||||
<<foundp->nodep()->warnContextSecondary());
|
||||
}
|
||||
ins = true;
|
||||
}
|
||||
@ -1047,15 +1055,19 @@ class LinkDotFindVisitor : public AstNVisitor {
|
||||
if (foundp && foundp->parentp() == m_curSymp // Only when on same level
|
||||
&& !foundp->imported()) { // and not from package
|
||||
nodep->v3error("Duplicate declaration of enum value: "<<nodep->prettyName()<<endl
|
||||
<<findvarp->warnMore()<<"... Location of original declaration");
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<findvarp->warnMore()<<"... Location of original declaration\n"
|
||||
<<findvarp->warnContextSecondary());
|
||||
} else {
|
||||
// User can disable the message at either point
|
||||
if (!nodep->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)
|
||||
&& !foundp->nodep()->fileline()->warnIsOff(V3ErrorCode::VARHIDDEN)) {
|
||||
nodep->v3warn(VARHIDDEN, "Declaration of enum value hides declaration in upper scope: "
|
||||
<<nodep->prettyName()<<endl
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<foundp->nodep()->warnMore()
|
||||
<<"... Location of original declaration");
|
||||
<<"... Location of original declaration\n"
|
||||
<<nodep->warnContextSecondary());
|
||||
}
|
||||
ins = true;
|
||||
}
|
||||
@ -1229,7 +1241,9 @@ private:
|
||||
} else {
|
||||
if (refp->user4()) {
|
||||
nodep->v3error("Duplicate declaration of port: "<<nodep->prettyName()<<endl
|
||||
<<refp->warnMore()<<"... Location of original declaration");
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<refp->warnMore()<<"... Location of original declaration\n"
|
||||
<<refp->warnContextSecondary());
|
||||
}
|
||||
refp->user4(true);
|
||||
VSymEnt* symp = m_statep->insertSym(m_statep->getNodeSym(m_modp),
|
||||
@ -1655,8 +1669,10 @@ private:
|
||||
void markAndCheckPinDup(AstNode* nodep, AstNode* refp, const char* whatp) {
|
||||
if (refp->user5p() && refp->user5p()!=nodep) {
|
||||
nodep->v3error("Duplicate "<<whatp<<" connection: "<<nodep->prettyName()<<endl
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<refp->user5p()->warnMore()
|
||||
<<"... Location of original "<<whatp<<" connection");
|
||||
<<"... Location of original "<<whatp<<" connection\n"
|
||||
<<nodep->warnContextSecondary());
|
||||
} else {
|
||||
refp->user5p(nodep);
|
||||
}
|
||||
|
@ -74,8 +74,16 @@ V3ParseImp::~V3ParseImp() {
|
||||
|
||||
void V3ParseImp::ppline(const char* textp) {
|
||||
// Handle `line directive
|
||||
FileLine* prevFl = copyOrSameFileLine();
|
||||
int enterExit;
|
||||
fileline()->lineDirective(textp, enterExit/*ref*/);
|
||||
if (enterExit == 1) { // Enter
|
||||
fileline()->parent(prevFl);
|
||||
} else if (enterExit == 2) { // Exit
|
||||
FileLine* upFl = fileline()->parent();
|
||||
if (upFl) upFl = upFl->parent();
|
||||
if (upFl) fileline()->parent(upFl);
|
||||
}
|
||||
}
|
||||
|
||||
void V3ParseImp::verilatorCmtLintSave() {
|
||||
|
@ -145,8 +145,10 @@ public:
|
||||
if (!vxp->pure()) {
|
||||
nodep->v3warn(IMPURE, "Unsupported: External variable referenced by non-inlined function/task: "
|
||||
<<nodep->prettyName()<<endl
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<vxp->impureNode()->warnMore()<<"... Location of the external reference: "
|
||||
<<vxp->impureNode()->prettyName());
|
||||
<<vxp->impureNode()->prettyName()<<endl
|
||||
<<vxp->impureNode()->warnContextSecondary());
|
||||
}
|
||||
// And, we need to check all tasks this task calls
|
||||
for (V3GraphEdge* edgep = vxp->outBeginp(); edgep; edgep=edgep->outNextp()) {
|
||||
@ -840,9 +842,11 @@ private:
|
||||
else if (iter->second.second != dpiproto) {
|
||||
nodep->v3error("Duplicate declaration of DPI function with different formal arguments: "
|
||||
<<nodep->prettyName()<<endl
|
||||
<<nodep->warnContextPrimary()<<endl
|
||||
<<nodep->warnMore()<<"... New prototype: "<<dpiproto<<endl
|
||||
<<iter->second.first->warnMore()<<"... Original prototype: "
|
||||
<<iter->second.second);
|
||||
<<iter->second.second<<endl
|
||||
<<iter->second.first->warnContextSecondary());
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
@ -456,7 +456,9 @@ class TristateVisitor : public TristateBaseVisitor {
|
||||
} else {
|
||||
if (oldpullp->direction() != pullp->direction()) {
|
||||
pullp->v3error("Unsupported: Conflicting pull directions.\n"
|
||||
<<oldpullp->warnMore()<<"... Location of conflicting pull.");
|
||||
<<pullp->warnContextPrimary()<<endl
|
||||
<<oldpullp->warnMore()<<"... Location of conflicting pull.\n"
|
||||
<<oldpullp->warnContextSecondary());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1382,9 +1382,12 @@ private:
|
||||
num.opAssign(VN_CAST(itemp->valuep(), Const)->num());
|
||||
// Look for duplicates
|
||||
if (inits.find(num) != inits.end()) { // IEEE says illegal
|
||||
AstNode* otherp = inits.find(num)->second;
|
||||
itemp->v3error("Overlapping enumeration value: "<<itemp->prettyName()<<endl
|
||||
<<inits.find(num)->second->warnMore()
|
||||
<<"... Location of original declaration");
|
||||
<<itemp->warnContextPrimary()<<endl
|
||||
<<otherp->warnMore()
|
||||
<<"... Location of original declaration\n"
|
||||
<<otherp->warnContextSecondary());
|
||||
} else {
|
||||
inits.insert(make_pair(num, itemp));
|
||||
}
|
||||
|
4
test_regress/t/t_lint_in_inc_bad.out
Normal file
4
test_regress/t/t_lint_in_inc_bad.out
Normal file
@ -0,0 +1,4 @@
|
||||
%Error: t/t_lint_in_inc_bad_2.vh:8: syntax error, unexpected if, expecting '('
|
||||
t/t_lint_in_inc_bad_1.vh:6: ... note: In file included from t_lint_in_inc_bad_1.vh
|
||||
t/t_lint_in_inc_bad.v:6: ... note: In file included from t_lint_in_inc_bad.v
|
||||
%Error: Exiting due to
|
22
test_regress/t/t_lint_in_inc_bad.pl
Executable file
22
test_regress/t/t_lint_in_inc_bad.pl
Executable file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2008 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.
|
||||
|
||||
scenarios(vlt_all => 1);
|
||||
|
||||
compile(
|
||||
v_flags2 => ["--lint-only -Wall -Wno-DECLFILENAME --if-depth 10"],
|
||||
fails => 1,
|
||||
verilator_make_gcc => 0,
|
||||
make_top_shell => 0,
|
||||
make_main => 0,
|
||||
expect_filename => $Self->{golden_filename},
|
||||
);
|
||||
|
||||
ok(1);
|
||||
1;
|
6
test_regress/t/t_lint_in_inc_bad.v
Normal file
6
test_regress/t/t_lint_in_inc_bad.v
Normal file
@ -0,0 +1,6 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
`include "t_lint_in_inc_bad_1.vh"
|
6
test_regress/t/t_lint_in_inc_bad_1.vh
Normal file
6
test_regress/t/t_lint_in_inc_bad_1.vh
Normal file
@ -0,0 +1,6 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
`include "t_lint_in_inc_bad_2.vh"
|
9
test_regress/t/t_lint_in_inc_bad_2.vh
Normal file
9
test_regress/t/t_lint_in_inc_bad_2.vh
Normal file
@ -0,0 +1,9 @@
|
||||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2019 by Wilson Snyder.
|
||||
|
||||
module x;
|
||||
// Syntax error
|
||||
if if if;
|
||||
endmodule
|
Loading…
Reference in New Issue
Block a user