Show included-from filenames in warnings, bug1439.

This commit is contained in:
Wilson Snyder 2019-06-22 17:01:39 -04:00
parent 951521320a
commit 8e7559c6c9
20 changed files with 147 additions and 23 deletions

View File

@ -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]

View File

@ -1092,10 +1092,6 @@ void AstNode::v3errorEnd(std::ostringstream& str) const {
}
}
string AstNode::warnMore() const {
return fileline()->warnMore();
}
//======================================================================
// Data type conversion

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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());
}
}
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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() {

View File

@ -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 {

View File

@ -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());
}
}
}

View File

@ -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));
}

View 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

View 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;

View 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"

View 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"

View 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