diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 8bfa0fae8..7c6c601eb 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2347,9 +2347,11 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); return; } - if (m_ds.m_dotPos == DP_FINAL && VN_IS(m_ds.m_unlinkedScopep, LambdaArgRef) + if (m_ds.m_dotPos == DP_MEMBER && VN_IS(m_ds.m_dotp->lhsp(), LambdaArgRef) && nodep->name() == "index") { // 'with' statement's 'item.index' + // m_ds.dotp->lhsp() was checked to know if `index` is directly after lambda arg ref. + // If not, treat it as normal member select iterateChildren(nodep); const auto newp = new AstLambdaArgRef{ nodep->fileline(), m_ds.m_unlinkedScopep->name() + "__DOT__index", true}; @@ -2577,6 +2579,7 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); ok = true; + m_ds.m_dotPos = DP_MEMBER; m_ds.m_dotText = ""; } } diff --git a/test_regress/t/t_queue_method.v b/test_regress/t/t_queue_method.v index 0b7bd29b0..24c90e470 100644 --- a/test_regress/t/t_queue_method.v +++ b/test_regress/t/t_queue_method.v @@ -11,6 +11,8 @@ `define checkg(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='%g' exp='%g'\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); module t (/*AUTOARG*/); + typedef struct packed { int x, y; } point; + typedef struct packed { point p; int z; } point_3d; initial begin int q[$]; int qe[$]; // Empty @@ -19,6 +21,18 @@ module t (/*AUTOARG*/); int qi[$]; // Index returns int i; string v; + string string_q[$]; + string string_qv[$]; + point_3d points_q[$]; // Same as q and qv, but complex value type + point_3d points_qv[$]; + + points_q.push_back(point_3d'{point'{1, 2}, 3}); + points_q.push_back(point_3d'{point'{2, 3}, 5}); + points_q.push_back(point_3d'{point'{1, 4}, 5}); + + string_q.push_back("a"); + string_q.push_back("A"); + string_q.push_back("b"); q = '{1, 2, 2, 4, 3}; v = $sformatf("%p", q); `checks(v, "'{'h1, 'h2, 'h2, 'h4, 'h3} "); @@ -46,6 +60,8 @@ module t (/*AUTOARG*/); `checkh(qv.size(), 0); qv = q.unique(x) with (x % 2); `checkh(qv.size(), 2); + string_qv = string_q.unique(s) with (s.toupper); + `checkh(string_qv.size(), 2); qi = q.unique_index; qv.sort; // According to 7.12.1 of IEEE Std 1800-2017, it is not specified which index of duplicated value should be returned `checkh(qi.size(), 4); @@ -73,8 +89,14 @@ module t (/*AUTOARG*/); v = $sformatf("%p", qv); `checks(v, "'{'h1, 'h3} "); qv = q.find_first with (item == 2); v = $sformatf("%p", qv); `checks(v, "'{'h2} "); + points_qv = points_q.find_first with (item.z == 5); + `checkh(points_qv[0].p.y, 3); + points_qv = points_q.find_first with (item.p.x == 1); + `checkh(points_qv[0].p.y, 2); qv = q.find_last with (item == 2); v = $sformatf("%p", qv); `checks(v, "'{'h2} "); + string_qv = string_q.find_last(s) with (s.tolower() == "a"); + `checks(string_qv[0], "A"); qv = q.find with (item == 20); `checkh(qv.size, 0); diff --git a/test_regress/t/t_queue_method3_bad.out b/test_regress/t/t_queue_method3_bad.out new file mode 100644 index 000000000..4beb3e580 --- /dev/null +++ b/test_regress/t/t_queue_method3_bad.out @@ -0,0 +1,10 @@ +%Error-UNSUPPORTED: t/t_queue_method3_bad.v:16:52: Unsupported: Member call on object 'SEL' which is a 'BASICDTYPE 'int'' + : ... In instance t + 16 | points_qv = points_q.find_first(a) with (a.x.index == 0); + | ^~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Internal Error: t/t_queue_method3_bad.v:16:58: ../V3Width.cpp:#: Node has no type + : ... In instance t + 16 | points_qv = points_q.find_first(a) with (a.x.index == 0); + | ^~ + ... See the manual at https://verilator.org/verilator_doc.html for more assistance. diff --git a/test_regress/t/t_queue_method3_bad.pl b/test_regress/t/t_queue_method3_bad.pl new file mode 100755 index 000000000..fbdf9000e --- /dev/null +++ b/test_regress/t/t_queue_method3_bad.pl @@ -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 2022 by Antmicro Ltd. 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; diff --git a/test_regress/t/t_queue_method3_bad.v b/test_regress/t/t_queue_method3_bad.v new file mode 100644 index 000000000..274690022 --- /dev/null +++ b/test_regress/t/t_queue_method3_bad.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2022 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + typedef struct packed { int x, y; } point; + initial begin + point points_q[$]; + point points_qv[$]; + points_q.push_back(point'{1, 2}); + + // `index` should be treated as normal member select, + // but the member is not present in the struct + points_qv = points_q.find_first(a) with (a.x.index == 0); + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule