From 726e78fdda2f6d8122ee1a643a1f70e9edb841ed Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 31 Oct 2020 10:33:36 -0400 Subject: [PATCH] Add 'with' syntax checks. --- src/V3LinkDot.cpp | 2 +- src/V3Width.cpp | 1 - src/verilog.y | 2 +- test_regress/t/t_assoc_meth_bad.out | 53 ------------------- test_regress/t/t_assoc_method_bad.out | 53 +++++++++++++++++++ ...ssoc_meth_bad.pl => t_assoc_method_bad.pl} | 0 ..._assoc_meth_bad.v => t_assoc_method_bad.v} | 0 test_regress/t/t_queue_method2_bad.out | 7 +++ test_regress/t/t_queue_method2_bad.pl | 19 +++++++ test_regress/t/t_queue_method2_bad.v | 22 ++++++++ test_regress/t/t_with.out | 41 +++++++++++++- 11 files changed, 142 insertions(+), 58 deletions(-) delete mode 100644 test_regress/t/t_assoc_meth_bad.out create mode 100644 test_regress/t/t_assoc_method_bad.out rename test_regress/t/{t_assoc_meth_bad.pl => t_assoc_method_bad.pl} (100%) rename test_regress/t/{t_assoc_meth_bad.v => t_assoc_method_bad.v} (100%) create mode 100755 test_regress/t/t_queue_method2_bad.out create mode 100755 test_regress/t/t_queue_method2_bad.pl create mode 100644 test_regress/t/t_queue_method2_bad.v diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index f77316d14..c73104f5a 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1267,7 +1267,7 @@ class LinkDotFindVisitor : public AstNVisitor { } if (argp->nextp()) argp->nextp()->v3error("'with' function expects only up to one argument"); - VL_DO_DANGLING(argp->unlinkFrBack()->deleteTree(), argp); + VL_DO_DANGLING(argp->unlinkFrBackWithNext()->deleteTree(), argp); } // Type depends on the method used, let V3Width figure it out later auto* varp = new AstVar(argFl, AstVarType::WITH, name, VFlagChildDType(), diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 15d41ad2d..f41ba25a1 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -4117,7 +4117,6 @@ private: virtual void visit(AstWith* nodep) override { // Should otherwise be underneath a method call nodep->v3warn(E_UNSUPPORTED, "Unsupported: with statements in this context"); - VL_DO_DANGLING(nodep->deleteTree(), nodep); } virtual void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. That's faster diff --git a/src/verilog.y b/src/verilog.y index e6c018af2..ef4e4a045 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -4030,7 +4030,7 @@ array_methodWith: | array_methodNoRoot parenE yWITH__PAREN '(' expr ')' { $$ = new AstWithParse($3, false, $1, $5); } | array_methodNoRoot '(' expr ')' yWITH__PAREN '(' expr ')' - { $$ = new AstWithParse($5, false, $1, $7); $1->addPinsp($3); } + { $$ = new AstWithParse($5, false, $1, $7); $1->addPinsp(new AstArg($3, "", $3)); } ; dpi_import_export: // ==IEEE: dpi_import_export diff --git a/test_regress/t/t_assoc_meth_bad.out b/test_regress/t/t_assoc_meth_bad.out deleted file mode 100644 index 496ecfee9..000000000 --- a/test_regress/t/t_assoc_meth_bad.out +++ /dev/null @@ -1,53 +0,0 @@ -%Error: t/t_assoc_meth_bad.v:14:13: The 1 arguments passed to .num method does not match its requiring 0 arguments - : ... In instance t - 14 | v = a.num("badarg"); - | ^~~ -%Error: t/t_assoc_meth_bad.v:15:13: The 1 arguments passed to .size method does not match its requiring 0 arguments - : ... In instance t - 15 | v = a.size("badarg"); - | ^~~~ -%Error: t/t_assoc_meth_bad.v:16:13: The 0 arguments passed to .exists method does not match its requiring 1 arguments - : ... In instance t - 16 | v = a.exists(); - | ^~~~~~ -%Error: t/t_assoc_meth_bad.v:17:13: The 2 arguments passed to .exists method does not match its requiring 1 arguments - : ... In instance t - 17 | v = a.exists(k, "bad2"); - | ^~~~~~ -%Error: t/t_assoc_meth_bad.v:18:13: The 0 arguments passed to .first method does not match its requiring 1 arguments - : ... In instance t - 18 | v = a.first(); - | ^~~~~ -%Error: t/t_assoc_meth_bad.v:19:13: The 2 arguments passed to .next method does not match its requiring 1 arguments - : ... In instance t - 19 | v = a.next(k, "bad2"); - | ^~~~ -%Error: t/t_assoc_meth_bad.v:20:13: The 0 arguments passed to .last method does not match its requiring 1 arguments - : ... In instance t - 20 | v = a.last(); - | ^~~~ -%Error: t/t_assoc_meth_bad.v:21:13: The 2 arguments passed to .prev method does not match its requiring 1 arguments - : ... In instance t - 21 | v = a.prev(k, "bad2"); - | ^~~~ -%Error: t/t_assoc_meth_bad.v:22:9: The 2 arguments passed to .delete method does not match its requiring 0 to 1 arguments - : ... In instance t - 22 | a.delete(k, "bad2"); - | ^~~~~~ -%Error: t/t_assoc_meth_bad.v:24:9: Array method 'sort' not legal on associative arrays - : ... In instance t - 24 | a.sort; - | ^~~~ -%Error: t/t_assoc_meth_bad.v:25:9: Array method 'rsort' not legal on associative arrays - : ... In instance t - 25 | a.rsort; - | ^~~~~ -%Error: t/t_assoc_meth_bad.v:26:9: Array method 'reverse' not legal on associative arrays - : ... In instance t - 26 | a.reverse; - | ^~~~~~~ -%Error: t/t_assoc_meth_bad.v:27:9: Array method 'shuffle' not legal on associative arrays - : ... In instance t - 27 | a.shuffle; - | ^~~~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_assoc_method_bad.out b/test_regress/t/t_assoc_method_bad.out new file mode 100644 index 000000000..6c0ff94cc --- /dev/null +++ b/test_regress/t/t_assoc_method_bad.out @@ -0,0 +1,53 @@ +%Error: t/t_assoc_method_bad.v:14:13: The 1 arguments passed to .num method does not match its requiring 0 arguments + : ... In instance t + 14 | v = a.num("badarg"); + | ^~~ +%Error: t/t_assoc_method_bad.v:15:13: The 1 arguments passed to .size method does not match its requiring 0 arguments + : ... In instance t + 15 | v = a.size("badarg"); + | ^~~~ +%Error: t/t_assoc_method_bad.v:16:13: The 0 arguments passed to .exists method does not match its requiring 1 arguments + : ... In instance t + 16 | v = a.exists(); + | ^~~~~~ +%Error: t/t_assoc_method_bad.v:17:13: The 2 arguments passed to .exists method does not match its requiring 1 arguments + : ... In instance t + 17 | v = a.exists(k, "bad2"); + | ^~~~~~ +%Error: t/t_assoc_method_bad.v:18:13: The 0 arguments passed to .first method does not match its requiring 1 arguments + : ... In instance t + 18 | v = a.first(); + | ^~~~~ +%Error: t/t_assoc_method_bad.v:19:13: The 2 arguments passed to .next method does not match its requiring 1 arguments + : ... In instance t + 19 | v = a.next(k, "bad2"); + | ^~~~ +%Error: t/t_assoc_method_bad.v:20:13: The 0 arguments passed to .last method does not match its requiring 1 arguments + : ... In instance t + 20 | v = a.last(); + | ^~~~ +%Error: t/t_assoc_method_bad.v:21:13: The 2 arguments passed to .prev method does not match its requiring 1 arguments + : ... In instance t + 21 | v = a.prev(k, "bad2"); + | ^~~~ +%Error: t/t_assoc_method_bad.v:22:9: The 2 arguments passed to .delete method does not match its requiring 0 to 1 arguments + : ... In instance t + 22 | a.delete(k, "bad2"); + | ^~~~~~ +%Error: t/t_assoc_method_bad.v:24:9: Array method 'sort' not legal on associative arrays + : ... In instance t + 24 | a.sort; + | ^~~~ +%Error: t/t_assoc_method_bad.v:25:9: Array method 'rsort' not legal on associative arrays + : ... In instance t + 25 | a.rsort; + | ^~~~~ +%Error: t/t_assoc_method_bad.v:26:9: Array method 'reverse' not legal on associative arrays + : ... In instance t + 26 | a.reverse; + | ^~~~~~~ +%Error: t/t_assoc_method_bad.v:27:9: Array method 'shuffle' not legal on associative arrays + : ... In instance t + 27 | a.shuffle; + | ^~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_assoc_meth_bad.pl b/test_regress/t/t_assoc_method_bad.pl similarity index 100% rename from test_regress/t/t_assoc_meth_bad.pl rename to test_regress/t/t_assoc_method_bad.pl diff --git a/test_regress/t/t_assoc_meth_bad.v b/test_regress/t/t_assoc_method_bad.v similarity index 100% rename from test_regress/t/t_assoc_meth_bad.v rename to test_regress/t/t_assoc_method_bad.v diff --git a/test_regress/t/t_queue_method2_bad.out b/test_regress/t/t_queue_method2_bad.out new file mode 100755 index 000000000..5d2900d8e --- /dev/null +++ b/test_regress/t/t_queue_method2_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_queue_method2_bad.v:16:21: 'with' function expects only up to one argument + 16 | qi = q.find(a,b) with (0); + | ^ +%Error: t/t_queue_method2_bad.v:17:19: 'with' function expects simple variable name + 17 | qi = q.find(1) with (0); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_queue_method2_bad.pl b/test_regress/t/t_queue_method2_bad.pl new file mode 100755 index 000000000..a5846c699 --- /dev/null +++ b/test_regress/t/t_queue_method2_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 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; diff --git a/test_regress/t/t_queue_method2_bad.v b/test_regress/t/t_queue_method2_bad.v new file mode 100644 index 000000000..b6ce89d8c --- /dev/null +++ b/test_regress/t/t_queue_method2_bad.v @@ -0,0 +1,22 @@ +// 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 + +module t (/*AUTOARG*/); + initial begin + int q[$]; + int qe[$]; // Empty + int qv[$]; // Value returns + int qi[$]; // Index returns + + q = '{2, 2, 4, 1, 3}; + + qi = q.find(a,b) with (0); // b is extra + qi = q.find(1) with (0); // 1 is illegal + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_with.out b/test_regress/t/t_with.out index 347d054c6..4b4dae672 100644 --- a/test_regress/t/t_with.out +++ b/test_regress/t/t_with.out @@ -1,4 +1,41 @@ -%Error: t/t_with.v:32:22: Can't find definition of variable: 'v' +%Error-UNSUPPORTED: t/t_with.v:19:23: Unsupported/unknown built-in queue method 'find' + : ... In instance t + 19 | found = aliases.find(i) with (i == tofind); + | ^~~~ +%Error-UNSUPPORTED: t/t_with.v:21:15: Unsupported/unknown built-in queue method 'find' + : ... In instance t + 21 | aliases.find(i) with (i == tofind); + | ^~~~ +%Error-UNSUPPORTED: t/t_with.v:24:23: Unsupported/unknown built-in queue method 'find' + : ... In instance t + 24 | found = aliases.find with (item == i); + | ^~~~ +%Error-UNSUPPORTED: t/t_with.v:25:15: Unsupported/unknown built-in queue method 'find' + : ... In instance t + 25 | aliases.find with (item == i); + | ^~~~ +%Error-UNSUPPORTED: t/t_with.v:29:23: Unsupported/unknown built-in queue method 'unique' + : ... In instance t + 29 | found = aliases.unique with (id); + | ^~~~~~ +%Error-UNSUPPORTED: t/t_with.v:30:23: Unsupported/unknown built-in queue method 'unique' + : ... In instance t + 30 | found = aliases.unique() with (id); + | ^~~~~~ +%Error-UNSUPPORTED: t/t_with.v:31:23: Unsupported/unknown built-in queue method 'unique' + : ... In instance t + 31 | found = aliases.unique(i) with (id); + | ^~~~~~ +%Error-UNSUPPORTED: t/t_with.v:32:19: Unsupported/unknown built-in queue method 'or' + : ... In instance t 32 | i = aliases.or(v) with (v); - | ^ + | ^~ +%Error-UNSUPPORTED: t/t_with.v:33:19: Unsupported/unknown built-in queue method 'and' + : ... In instance t + 33 | i = aliases.and(v) with (v); + | ^~~ +%Error-UNSUPPORTED: t/t_with.v:34:19: Unsupported/unknown built-in queue method 'xor' + : ... In instance t + 34 | i = aliases.xor(v) with (v); + | ^~~ %Error: Exiting due to