Fix filename backslash escapes in C code (#5947).

This commit is contained in:
Wilson Snyder 2025-04-29 19:27:38 -04:00
parent d3016b62f5
commit 5ca62de167
14 changed files with 72 additions and 24 deletions

View File

@ -14,6 +14,7 @@ Verilator 5.037 devel
**Other:**
* Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu]
* Fix filename backslash escapes in C code (#5947).
* Fix sign extension of signed compared with unsigned case items (#5968).

View File

@ -355,8 +355,8 @@ public:
// Xml output
m_os << "<module_files>\n";
for (const FileLine* ifp : m_nodeModules) {
m_os << "<file id=\"" << ifp->filenameLetters() << "\" filename=\"" << ifp->filename()
<< "\" language=\"" << ifp->language().ascii() << "\"/>\n";
m_os << "<file id=\"" << ifp->filenameLetters() << "\" filename=\""
<< ifp->filenameEsc() << "\" language=\"" << ifp->language().ascii() << "\"/>\n";
}
m_os << "</module_files>\n";
}

View File

@ -268,6 +268,8 @@ public:
string asciiLineCol() const;
int filenameno() const VL_MT_SAFE { return m_filenameno; }
string filename() const VL_MT_SAFE { return singleton().numberToName(filenameno()); }
// Filename with C string escapes
string filenameEsc() const VL_MT_SAFE { return VString::quoteBackslash(filename()); }
bool filenameIsGlobal() const VL_MT_SAFE {
return (filename() == commandLineFilename() || filename() == builtInFilename());
}

View File

@ -237,7 +237,7 @@ bom [\357\273\277]
return VP_TEXT; }
<INITIAL,STRIFY>"`__FILE__" { FL_FWDC;
static string rtnfile;
rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filename();
rtnfile = '"'; rtnfile += LEXP->curFilelinep()->filenameEsc();
rtnfile += '"'; yytext = (char*)rtnfile.c_str(); yyleng = rtnfile.length();
return VP_STRING; }
<INITIAL,STRIFY>"`__LINE__" { FL_FWDC;

View File

@ -91,7 +91,7 @@ string VString::upcase(const string& str) VL_PURE {
return result;
}
string VString::quoteAny(const string& str, char tgt, char esc) {
string VString::quoteAny(const string& str, char tgt, char esc) VL_PURE {
string result;
for (const char c : str) {
if (c == tgt) result += esc;

View File

@ -94,11 +94,11 @@ public:
// Convert string to upper case (toupper)
static string upcase(const string& str) VL_PURE;
// Insert esc just before tgt
static string quoteAny(const string& str, char tgt, char esc);
static string quoteAny(const string& str, char tgt, char esc) VL_PURE;
// Replace any \'s with \\ (two consecutive backslashes)
static string quoteBackslash(const string& str) { return quoteAny(str, '\\', '\\'); }
static string quoteBackslash(const string& str) VL_PURE { return quoteAny(str, '\\', '\\'); }
// Replace any %'s with %%
static string quotePercent(const string& str) { return quoteAny(str, '%', '%'); }
static string quotePercent(const string& str) VL_PURE { return quoteAny(str, '%', '%'); }
// Replace any %%'s with %
static string dequotePercent(const string& str);
// Surround a raw string by double quote and escape if necessary

View File

@ -685,8 +685,8 @@ class TaskVisitor final : public VNVisitor {
UASSERT_OBJ(snp, refp, "Missing scoping context");
ccallp->addArgsp(snp);
// __Vfilenamep
ccallp->addArgsp(new AstCExpr{refp->fileline(),
"\"" + refp->fileline()->filename() + "\"", 64, true});
ccallp->addArgsp(new AstCExpr{
refp->fileline(), "\"" + refp->fileline()->filenameEsc() + "\"", 64, true});
// __Vlineno
ccallp->addArgsp(new AstConst(refp->fileline(), refp->fileline()->lineno()));
}

View File

@ -654,7 +654,7 @@ class TimingControlVisitor final : public VNVisitor {
void addDebugInfo(AstCMethodHard* const methodp) const {
if (v3Global.opt.protectIds()) return;
FileLine* const flp = methodp->fileline();
AstCExpr* const ap = new AstCExpr{flp, '"' + flp->filename() + '"', 0};
AstCExpr* const ap = new AstCExpr{flp, '"' + flp->filenameEsc() + '"', 0};
ap->dtypeSetString();
methodp->addPinsp(ap);
AstCExpr* const bp = new AstCExpr{flp, cvtToStr(flp->lineno()), 0};

View File

@ -70,8 +70,8 @@ void V3Waiver::addEntry(V3ErrorCode errorCode, const std::string& filename, cons
}
std::stringstream entry;
entry << "lint_off -rule " << errorCode.ascii() << " -file \"*" << filename << "\" -match \""
<< trimmsg << "\"";
entry << "lint_off -rule " << errorCode.ascii() << " -file \"*"
<< VString::quoteBackslash(filename) << "\" -match \"" << trimmsg << "\"";
s_waiverList.push_back(entry.str());
}

View File

@ -1,16 +1,20 @@
-Info: some file:100:1: aaaaaaaa
-Info: some file:100:1: aaaaaaaa file='some file'
: ... note: In instance 't'
100 | $info("aaaaaaaa");
100 | $info("aaaaaaaa file='%s'", "some file");
| ^~~~~
-Info: some file:101:1: bbbbbbbb
-Info: some file:101:1: bbbbbbbb file='some file'
: ... note: In instance 't'
101 | $info("bbbbbbbb");
101 | $info("bbbbbbbb file='%s'", "some file");
| ^~~~~
-Info: somefile.v:200:1: cccccccc
-Info: somefile.v:200:1: cccccccc file='somefile.v'
: ... note: In instance 't'
200 | $info("cccccccc");
200 | $info("cccccccc file='%s'", "somefile.v");
| ^~~~~
-Info: /a/somefile.v:300:1: dddddddd
-Info: /a/somefile.v:300:1: dddddddd file='/a/somefile.v'
: ... note: In instance 't'
300 | $info("dddddddd");
300 | $info("dddddddd file='%s'", "/a/somefile.v");
| ^~~~~
-Info: C:\a\somefile.v:400:1: eeeeeeee file='C:\a\somefile.v'
: ... note: In instance 't'
400 | $info("eeeeeeee file='%s'", "C:\\a\\somefile.v");
| ^~~~~

View File

@ -6,10 +6,12 @@
module t;
`line 100 "some file" 0
$info("aaaaaaaa");
$info("bbbbbbbb");
$info("aaaaaaaa file='%s'", `__FILE__);
$info("bbbbbbbb file='%s'", `__FILE__);
`line 200 "somefile.v" 0
$info("cccccccc");
$info("cccccccc file='%s'", `__FILE__);
`line 300 "/a/somefile.v" 0
$info("dddddddd");
$info("dddddddd file='%s'", `__FILE__);
`line 400 "C:\\a\\somefile.v" 0
$info("eeeeeeee file='%s'", `__FILE__);
endmodule

View File

@ -0,0 +1,4 @@
Intentional stop
Filename 'C:\some\windows\path\t_stop_winos_bad.v' Length = 39
%Error: C:\some\windows\path\t_stop_winos_bad.v:14: Verilog $stop
Aborting...

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 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('simulator')
test.compile(verilator_flags2=['-no-MMD'])
test.execute(fails=True, expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2019 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`line 7 "C:\\some\\windows\\path\\t_stop_winos_bad.v" 0
module t;
localparam string FILENAME = `__FILE__;
initial begin
$write("Intentional stop\n");
// Print length to make sure \\ counts as 1 character
$write("Filename '%s' Length = %0d\n", FILENAME, FILENAME.len());
$stop;
end
endmodule