Fix errors on using string in incorrect format (#5340).
This commit is contained in:
parent
c383f4868f
commit
fe0b210a0c
1
Changes
1
Changes
|
|
@ -1532,6 +1532,7 @@ Verilator 4.026 2020-01-11
|
||||||
* Fix expand optimization slowing --lint-only. Closes #2091. [Thomas Watts]
|
* Fix expand optimization slowing --lint-only. Closes #2091. [Thomas Watts]
|
||||||
* Fix %{number}s with strings. #2093. [agrobman]
|
* Fix %{number}s with strings. #2093. [agrobman]
|
||||||
* Fix shebang breaking some shells. Closes #2067. [zdave]
|
* Fix shebang breaking some shells. Closes #2067. [zdave]
|
||||||
|
* Fix errors on using string in incorrect format (#5340). [John Demme]
|
||||||
|
|
||||||
|
|
||||||
Verilator 4.024 2019-12-08
|
Verilator 4.024 2019-12-08
|
||||||
|
|
|
||||||
|
|
@ -5033,6 +5033,13 @@ class WidthVisitor final : public VNVisitor {
|
||||||
UASSERT_OBJ(nodep->lhsp()->dtypep()->widthSized(), nodep, "How can LValue be unsized?");
|
UASSERT_OBJ(nodep->lhsp()->dtypep()->widthSized(), nodep, "How can LValue be unsized?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void formatNoStringArg(AstNode* argp, char ch) {
|
||||||
|
if (argp && argp->isString()) {
|
||||||
|
argp->v3error("$display-line format of '%"s + ch + "' illegal with string argument\n"
|
||||||
|
<< argp->warnMore() << "... Suggest use '%s'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void visit(AstSFormatF* nodep) override {
|
void visit(AstSFormatF* nodep) override {
|
||||||
// Excludes NodeDisplay, see below
|
// Excludes NodeDisplay, see below
|
||||||
if (m_vup && !m_vup->prelim()) return; // Can be called as statement or function
|
if (m_vup && !m_vup->prelim()) return; // Can be called as statement or function
|
||||||
|
|
@ -5056,6 +5063,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
bool added = false;
|
bool added = false;
|
||||||
const AstNodeDType* const dtypep = argp ? argp->dtypep()->skipRefp() : nullptr;
|
const AstNodeDType* const dtypep = argp ? argp->dtypep()->skipRefp() : nullptr;
|
||||||
const AstBasicDType* const basicp = dtypep ? dtypep->basicp() : nullptr;
|
const AstBasicDType* const basicp = dtypep ? dtypep->basicp() : nullptr;
|
||||||
|
ch = std::tolower(ch);
|
||||||
if (ch == '?') { // Unspecified by user, guess
|
if (ch == '?') { // Unspecified by user, guess
|
||||||
if (argp && argp->isDouble()) {
|
if (argp && argp->isDouble()) {
|
||||||
ch = 'g';
|
ch = 'g';
|
||||||
|
|
@ -5069,13 +5077,14 @@ class WidthVisitor final : public VNVisitor {
|
||||||
ch = 'p';
|
ch = 'p';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (std::tolower(ch)) {
|
switch (ch) {
|
||||||
case '%': break; // %% - just output a %
|
case '%': break; // %% - just output a %
|
||||||
case 'm': break; // %m - auto insert "name"
|
case 'm': break; // %m - auto insert "name"
|
||||||
case 'l': break; // %m - auto insert "library"
|
case 'l': break; // %m - auto insert "library"
|
||||||
case 'd': { // Convert decimal to either 'd' or '#'
|
case 'd': { // Convert decimal to either 'd' or '#'
|
||||||
if (argp) {
|
if (argp) {
|
||||||
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
|
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
|
||||||
|
formatNoStringArg(argp, ch);
|
||||||
if (argp->isDouble()) {
|
if (argp->isDouble()) {
|
||||||
spliceCvtS(argp, true, 64);
|
spliceCvtS(argp, true, 64);
|
||||||
ch = '~';
|
ch = '~';
|
||||||
|
|
@ -5091,6 +5100,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
case 'x': {
|
case 'x': {
|
||||||
if (argp) {
|
if (argp) {
|
||||||
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
|
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
|
||||||
|
formatNoStringArg(argp, ch);
|
||||||
if (argp->isDouble()) spliceCvtS(argp, true, 64);
|
if (argp->isDouble()) spliceCvtS(argp, true, 64);
|
||||||
argp = nextp;
|
argp = nextp;
|
||||||
}
|
}
|
||||||
|
|
@ -5148,6 +5158,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
case 't': { // Convert decimal time to realtime
|
case 't': { // Convert decimal time to realtime
|
||||||
if (argp) {
|
if (argp) {
|
||||||
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
|
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
|
||||||
|
formatNoStringArg(argp, ch);
|
||||||
if (argp->isDouble()) ch = '^'; // Convert it
|
if (argp->isDouble()) ch = '^'; // Convert it
|
||||||
UASSERT_OBJ(!nodep->timeunit().isNone(), nodep,
|
UASSERT_OBJ(!nodep->timeunit().isNone(), nodep,
|
||||||
"display %t has no time units");
|
"display %t has no time units");
|
||||||
|
|
@ -5160,6 +5171,7 @@ class WidthVisitor final : public VNVisitor {
|
||||||
case 'g': {
|
case 'g': {
|
||||||
if (argp) {
|
if (argp) {
|
||||||
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
|
AstNodeExpr* const nextp = VN_AS(argp->nextp(), NodeExpr);
|
||||||
|
formatNoStringArg(argp, ch);
|
||||||
if (!argp->isDouble()) {
|
if (!argp->isDouble()) {
|
||||||
iterateCheckReal(nodep, "Display argument", argp, BOTH);
|
iterateCheckReal(nodep, "Display argument", argp, BOTH);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
%Error: t/t_display_type_bad.v:10:31: $display-line format of '%d' illegal with string argument
|
||||||
|
: ... note: In instance 't'
|
||||||
|
: ... Suggest use '%s'
|
||||||
|
10 | $display("%d %x %f %t", s, s, s, s);
|
||||||
|
| ^
|
||||||
|
%Error: t/t_display_type_bad.v:10:34: $display-line format of '%x' illegal with string argument
|
||||||
|
: ... note: In instance 't'
|
||||||
|
: ... Suggest use '%s'
|
||||||
|
10 | $display("%d %x %f %t", s, s, s, s);
|
||||||
|
| ^
|
||||||
|
%Error: t/t_display_type_bad.v:10:37: $display-line format of '%f' illegal with string argument
|
||||||
|
: ... note: In instance 't'
|
||||||
|
: ... Suggest use '%s'
|
||||||
|
10 | $display("%d %x %f %t", s, s, s, s);
|
||||||
|
| ^
|
||||||
|
%Error: t/t_display_type_bad.v:10:40: $display-line format of '%t' illegal with string argument
|
||||||
|
: ... note: In instance 't'
|
||||||
|
: ... Suggest use '%s'
|
||||||
|
10 | $display("%d %x %f %t", s, s, s, s);
|
||||||
|
| ^
|
||||||
|
%Error: Exiting due to
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2003 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
|
||||||
|
|
||||||
|
scenarios(vlt => 1);
|
||||||
|
|
||||||
|
lint(
|
||||||
|
fails => 1,
|
||||||
|
expect_filename => $Self->{golden_filename},
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t;
|
||||||
|
string s = "a string";
|
||||||
|
initial begin
|
||||||
|
$display("%d %x %f %t", s, s, s, s);
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue