From 7f94fa1da7034ed992e83dd9a4890c59dae3ae14 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 26 Feb 2025 09:08:41 -0500 Subject: [PATCH] Add check for `let` misused in statement context (#5733). --- Changes | 1 + src/V3AstNodeOther.h | 2 +- src/V3LinkResolve.cpp | 3 +++ test_regress/t/t_let_stmt_bad.out | 4 ++++ test_regress/t/t_let_stmt_bad.py | 16 ++++++++++++++++ test_regress/t/t_let_stmt_bad.v | 19 +++++++++++++++++++ 6 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 test_regress/t/t_let_stmt_bad.out create mode 100755 test_regress/t/t_let_stmt_bad.py create mode 100644 test_regress/t/t_let_stmt_bad.v diff --git a/Changes b/Changes index 35571d7e1..7d169d203 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,7 @@ Verilator 5.035 devel * Change `--output-groups` to default to value of `--build-jobs` (#5751). Those using build farms may need to now use `--output-groups 0` or otherwise. +* Add check for `let` misused in statement context (#5733). * Add used language to `--preproc-resolve` output (#5795). [Kamil Rakoczy, Antmicro Ltd.] * Fix reset of automatic function variables (#5747). [Augustin Fabre] diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 684298ecb..f91c90632 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -2306,7 +2306,7 @@ public: class AstLet final : public AstNodeFTask { // Verilog "let" statement // Parents: MODULE - // stmtp is always a StmtExpr as Let always returns AstNodeExpr + // stmtp list first item is returned StmtExpr, as Let always returns AstNodeExpr public: AstLet(FileLine* fl, const string& name) : ASTGEN_SUPER_Let(fl, name, nullptr) {} diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 9d5630141..7b4074f19 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -189,6 +189,9 @@ class LinkResolveVisitor final : public VNVisitor { return; } letp->user2(true); + if (VN_IS(nodep->backp(), StmtExpr)) { + nodep->v3error("Expected statement, not let substitution " << letp->prettyNameQ()); + } // letp->dumpTree("-let-let "); // nodep->dumpTree("-let-ref "); AstStmtExpr* const letStmtp = VN_AS(letp->stmtsp(), StmtExpr); diff --git a/test_regress/t/t_let_stmt_bad.out b/test_regress/t/t_let_stmt_bad.out new file mode 100644 index 000000000..92c27e6b7 --- /dev/null +++ b/test_regress/t/t_let_stmt_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_let_stmt_bad.v:15:14: Expected statement, not let substitution 'letf' + 15 | 0: letf(0); + | ^~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_let_stmt_bad.py b/test_regress/t/t_let_stmt_bad.py new file mode 100755 index 000000000..55203b6c9 --- /dev/null +++ b/test_regress/t/t_let_stmt_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_let_stmt_bad.v b/test_regress/t/t_let_stmt_bad.v new file mode 100644 index 000000000..ca0e67010 --- /dev/null +++ b/test_regress/t/t_let_stmt_bad.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + + wire clk; + + let letf(x) = (x << 1); + + always @(posedge clk) begin + case (0) + 0: letf(0); // Bad, need a statement + endcase + end + +endmodule