From f149dd304c8ed3cdd1bfa34b6f31fca664440420 Mon Sep 17 00:00:00 2001 From: Pawel Klopotek Date: Wed, 22 Jul 2026 13:54:58 +0200 Subject: [PATCH] Add error when scalar is passed to array task argument (#7948) --- src/V3Width.cpp | 8 +++++ test_regress/t/t_dpi_unpack_bad.out | 7 ++-- .../t/t_invalid_task_arguments_bad.out | 18 +++++++++++ .../t/t_invalid_task_arguments_bad.py | 16 ++++++++++ test_regress/t/t_invalid_task_arguments_bad.v | 32 +++++++++++++++++++ 5 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 test_regress/t/t_invalid_task_arguments_bad.out create mode 100755 test_regress/t/t_invalid_task_arguments_bad.py create mode 100644 test_regress/t/t_invalid_task_arguments_bad.v diff --git a/src/V3Width.cpp b/src/V3Width.cpp index e6f2d5108..84d66c260 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -7507,6 +7507,14 @@ class WidthVisitor final : public VNVisitor { relinkHandle.relink(newp); } if (portp->isWritable()) V3LinkLValue::linkLValueSet(pinp); + if (VN_IS(pinDTypep, BasicDType) && portp->direction() != VDirection::REF + && (VN_IS(portDTypep, UnpackArrayDType) || VN_IS(portDTypep, DynArrayDType) + || VN_IS(portDTypep, QueueDType) || VN_IS(portDTypep, AssocArrayDType))) { + pinp->v3error("Function Argument expects " << portDTypep->prettyDTypeNameQ() + << ", got " + << pinDTypep->prettyDTypeNameQ()); + continue; + } if (!portp->basicp() || portp->basicp()->isOpaque()) { // Output args: at return caller = callee, reverse direction. checkClassAssign(nodep, "Function Argument", pinp, portDTypep, diff --git a/test_regress/t/t_dpi_unpack_bad.out b/test_regress/t/t_dpi_unpack_bad.out index 7474ee54c..7699278d9 100644 --- a/test_regress/t/t_dpi_unpack_bad.out +++ b/test_regress/t/t_dpi_unpack_bad.out @@ -25,8 +25,9 @@ : ... note: In instance 't' 29 | import_func0(sig0[1]); | ^ -%Warning-WIDTHEXPAND: t/t_dpi_unpack_bad.v:29:5: Operator TASKREF 'import_func0' expects 4 bits on the Function Argument, but Function Argument's ARRAYSEL generates 3 bits. - : ... note: In instance 't' +%Error: t/t_dpi_unpack_bad.v:29:22: Function Argument expects 'logic[3:0]$[0:2]', got 'logic[2:0]' + : ... note: In instance 't' 29 | import_func0(sig0[1]); - | ^~~~~~~~~~~~ + | ^ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. %Error: Exiting due to diff --git a/test_regress/t/t_invalid_task_arguments_bad.out b/test_regress/t/t_invalid_task_arguments_bad.out new file mode 100644 index 000000000..a81ca08f8 --- /dev/null +++ b/test_regress/t/t_invalid_task_arguments_bad.out @@ -0,0 +1,18 @@ +%Error: t/t_invalid_task_arguments_bad.v:25:20: Function Argument expects 'logic[30:0]$[]', got 'IData' + : ... note: In instance 't' + 25 | dyn_task(.data($urandom)); + | ^~~~~~~~ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: t/t_invalid_task_arguments_bad.v:26:25: Function Argument expects 'logic[30:0]$[3:0]', got 'IData' + : ... note: In instance 't' + 26 | unpacked_task(.data($urandom)); + | ^~~~~~~~ +%Error: t/t_invalid_task_arguments_bad.v:27:22: Function Argument expects 'logic[30:0]$[$]', got 'IData' + : ... note: In instance 't' + 27 | queue_task(.data($urandom)); + | ^~~~~~~~ +%Error: t/t_invalid_task_arguments_bad.v:28:22: Function Argument expects 'logic[30:0]$[int]', got 'IData' + : ... note: In instance 't' + 28 | assoc_task(.data($urandom)); + | ^~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_invalid_task_arguments_bad.py b/test_regress/t/t_invalid_task_arguments_bad.py new file mode 100755 index 000000000..d6136ca75 --- /dev/null +++ b/test_regress/t/t_invalid_task_arguments_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2026 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios("vlt") + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_invalid_task_arguments_bad.v b/test_regress/t/t_invalid_task_arguments_bad.v new file mode 100644 index 000000000..7ff217662 --- /dev/null +++ b/test_regress/t/t_invalid_task_arguments_bad.v @@ -0,0 +1,32 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +task dyn_task(input logic [30:0] data []); + $display("%p", data); +endtask + +task unpacked_task(input logic [30:0] data [3:0]); + $display("%p", data); +endtask + +task queue_task(input logic [30:0] data [$]); + $display("%p", data); +endtask + +task assoc_task(input logic [30:0] data [int]); + $display("%p", data); +endtask + +module t; + initial begin + dyn_task(.data($urandom)); + unpacked_task(.data($urandom)); + queue_task(.data($urandom)); + assoc_task(.data($urandom)); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule