From ad2cb45a14eaa9e33ad3185527453256da648673 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Mon, 29 Jun 2020 20:02:15 -0400 Subject: [PATCH] Parser: Move unsupported error detection of 'this'/'super' down into link stage --- src/V3LinkDot.cpp | 8 ++++ src/verilog.y | 22 ++++++----- test_regress/t/t_class_extends_this.out | 49 +++++++++++++++++++++++++ test_regress/t/t_class_extends_this.pl | 23 ++++++++++++ test_regress/t/t_class_extends_this.v | 39 ++++++++++++++++++++ test_regress/t/t_with_unsup.out | 2 +- 6 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 test_regress/t/t_class_extends_this.out create mode 100755 test_regress/t/t_class_extends_this.pl create mode 100644 test_regress/t/t_class_extends_this.v diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 30c173a01..89db5174e 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -2033,6 +2033,14 @@ private: m_ds.init(m_curSymp); // Note m_ds.m_dot remains NULL; this is a reference not under a dot } + if (nodep->name() == "this") { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: this"); + m_ds.m_dotErr = true; + } + else if (nodep->name() == "super") { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: super"); + m_ds.m_dotErr = true; + } if (m_ds.m_dotPos == DP_MEMBER) { // Found a Var, everything following is membership. {scope}.{var}.HERE {member} AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack(); diff --git a/src/verilog.y b/src/verilog.y index 9dd91ba17..856fa2978 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -3432,7 +3432,7 @@ task_subroutine_callNoMethod: // function_subroutine_callNoMethod (as tas // // funcref below not task ref to avoid conflict, must later handle either | funcRef yWITH__PAREN '(' expr ')' { $$ = $1; BBUNSUP($2, "Unsupported: 'with' on task call"); } // // can call as method and yWITH without parenthesis - | id yWITH__PAREN '(' expr ')' { $$ = new AstFuncRef($1, *$1, NULL); BBUNSUP($2, "Unsupported: 'with' on function call"); } + | id yWITH__PAREN '(' expr ')' { $$ = new AstFuncRef($1, *$1, NULL); BBUNSUP($2, "Unsupported: 'with' on task call"); } | system_t_call { $$ = $1; } // // IEEE: method_call requires a "." so is in expr // // IEEE: ['std::'] not needed, as normal std package resolution will find it @@ -3454,7 +3454,7 @@ function_subroutine_callNoMethod: // IEEE: function_subroutine_call (as f // // IEEE: randomize_call // // We implement randomize as a normal funcRef, since randomize isn't a keyword // // Note yNULL is already part of expressions, so they come for free - | funcRef yWITH__CUR constraint_block { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with'"); } + | funcRef yWITH__CUR constraint_block { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with' constraint"); } | funcRef yWITH__CUR '{' '}' { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with'"); } ; @@ -4250,8 +4250,7 @@ exprScope: // scope and variable for use to inside an expression // // IEEE: [ implicit_class_handle . | class_scope | package_scope ] hierarchical_identifier select // // Or method_call_body without parenthesis // // See also varRefClassBit, which is the non-expr version of most of this - yTHIS { $$ = new AstConst($1, AstConst::LogicFalse()); - BBUNSUP($1, "Unsupported: this"); } + yTHIS { $$ = new AstParseRef($1, VParseRefExp::PX_ROOT, "this"); } | yD_ROOT { $$ = new AstParseRef($1, VParseRefExp::PX_ROOT, "$root"); } | idArrayed { $$ = $1; } | packageClassScope idArrayed { $$ = AstDot::newIfPkg($2->fileline(), CAST_PACKAGE_CLASS($1), $2); } @@ -4259,8 +4258,7 @@ exprScope: // scope and variable for use to inside an expression // // expr below must be a "yTHIS" | ~l~expr '.' ySUPER { $$ = $1; BBUNSUP($3, "Unsupported: super"); } // // Part of implicit_class_handle - | ySUPER { $$ = new AstConst($1, AstConst::LogicFalse()); - BBUNSUP($1, "Unsupported: super"); } + | ySUPER { $$ = new AstParseRef($1, VParseRefExp::PX_ROOT, "super"); } ; fexprScope: // exprScope, For use as first part of statement (disambiguates <=) @@ -4728,8 +4726,10 @@ variable_lvalueConcList: // IEEE: part of variable_lvalue: '{' variable_l idClassSel: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged variable idDotted { $$ = $1; } // // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select - | yTHIS '.' idDotted { $$ = $3; BBUNSUP($1, "Unsupported: this"); } - | ySUPER '.' idDotted { $$ = $3; BBUNSUP($1, "Unsupported: super"); } + | yTHIS '.' idDotted + { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "this"), $3); } + | ySUPER '.' idDotted + { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "super"), $3); } | yTHIS '.' ySUPER '.' idDotted { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); } // // Expanded: package_scope idDotted | packageClassScope idDotted { $$ = $2; BBUNSUP($2, "Unsupported: package scoped id"); } @@ -4738,8 +4738,10 @@ idClassSel: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged va idClassSelForeach: idDottedForeach { $$ = $1; } // // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select - | yTHIS '.' idDottedForeach { $$ = $3; BBUNSUP($1, "Unsupported: this"); } - | ySUPER '.' idDottedForeach { $$ = $3; BBUNSUP($1, "Unsupported: super"); } + | yTHIS '.' idDottedForeach + { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "this"), $3); } + | ySUPER '.' idDottedForeach + { $$ = new AstDot($2, false, new AstParseRef($1, VParseRefExp::PX_ROOT, "super"), $3); } | yTHIS '.' ySUPER '.' idDottedForeach { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); } // // Expanded: package_scope idForeach | packageClassScope idDottedForeach { $$ = $2; BBUNSUP($2, "Unsupported: package/class scoped id"); } diff --git a/test_regress/t/t_class_extends_this.out b/test_regress/t/t_class_extends_this.out new file mode 100644 index 000000000..020f115a4 --- /dev/null +++ b/test_regress/t/t_class_extends_this.out @@ -0,0 +1,49 @@ +%Error-UNSUPPORTED: t/t_class_extends_this.v:13:11: Unsupported: this + 13 | if (this.value != 1) $stop; + | ^~~~ +%Error: t/t_class_extends_this.v:13:11: Can't find definition of scope/variable: 'this' + 13 | if (this.value != 1) $stop; + | ^~~~ +%Error-UNSUPPORTED: t/t_class_extends_this.v:17:19: Unsupported: class extends + 17 | class Cls extends Base; + | ^~~~ +%Error: t/t_class_extends_this.v:17:19: Found definition of 'Base' as a CLASS but expected a variable + 17 | class Cls extends Base; + | ^~~~ +%Error-UNSUPPORTED: t/t_class_extends_this.v:21:11: Unsupported: this + 21 | if (this.value != 2) $stop; + | ^~~~ +%Error: t/t_class_extends_this.v:21:11: Can't find definition of scope/variable: 'this' + 21 | if (this.value != 2) $stop; + | ^~~~ +%Error-UNSUPPORTED: t/t_class_extends_this.v:22:11: Unsupported: super + 22 | if (super.value != 1) $stop; + | ^~~~~ +%Error: t/t_class_extends_this.v:22:11: Can't find definition of scope/variable: 'super' + 22 | if (super.value != 1) $stop; + | ^~~~~ +%Error-UNSUPPORTED: t/t_class_extends_this.v:23:7: Unsupported: super + 23 | super.test(); + | ^~~~~ +%Error: t/t_class_extends_this.v:23:7: Can't find definition of scope/variable: 'super' + 23 | super.test(); + | ^~~~~ +%Error-UNSUPPORTED: t/t_class_extends_this.v:24:7: Unsupported: super + 24 | super.value = 10; + | ^~~~~ +%Error: t/t_class_extends_this.v:24:7: Can't find definition of scope/variable: 'super' + 24 | super.value = 10; + | ^~~~~ +%Error-UNSUPPORTED: t/t_class_extends_this.v:25:7: Unsupported: this + 25 | this.value = 20; + | ^~~~ +%Error: t/t_class_extends_this.v:25:7: Can't find definition of scope/variable: 'this' + 25 | this.value = 20; + | ^~~~ +%Error-UNSUPPORTED: t/t_class_extends_this.v:26:11: Unsupported: super + 26 | if (super.value != 10) $stop; + | ^~~~~ +%Error: t/t_class_extends_this.v:26:11: Can't find definition of scope/variable: 'super' + 26 | if (super.value != 10) $stop; + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_extends_this.pl b/test_regress/t/t_class_extends_this.pl new file mode 100755 index 000000000..b8b56e6f0 --- /dev/null +++ b/test_regress/t/t_class_extends_this.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2020 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(simulator => 1); + +compile( + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +#execute( +# check_finished => 1, +# ); + +ok(1); +1; diff --git a/test_regress/t/t_class_extends_this.v b/test_regress/t/t_class_extends_this.v new file mode 100644 index 000000000..4f72270e9 --- /dev/null +++ b/test_regress/t/t_class_extends_this.v @@ -0,0 +1,39 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +typedef class Cls; + +class Base; + int value = 1; + function void test; + if (value != 1) $stop; + if (this.value != 1) $stop; + endfunction +endclass + +class Cls extends Base; + int value = 2; + function void test; + if (value != 2) $stop; + if (this.value != 2) $stop; + if (super.value != 1) $stop; + super.test(); + super.value = 10; + this.value = 20; + if (super.value != 10) $stop; + if (value != 20) $stop;; + endfunction +endclass + +module t (/*AUTOARG*/); + initial begin + Cls c; + c = new; + c.test(); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_with_unsup.out b/test_regress/t/t_with_unsup.out index 24569dad3..596929544 100644 --- a/test_regress/t/t_with_unsup.out +++ b/test_regress/t/t_with_unsup.out @@ -7,7 +7,7 @@ %Error-UNSUPPORTED: t/t_with_unsup.v:24:28: Unsupported: 'with' on function call 24 | found = aliases.find with (item == i); | ^~~~ -%Error-UNSUPPORTED: t/t_with_unsup.v:25:20: Unsupported: 'with' on function call +%Error-UNSUPPORTED: t/t_with_unsup.v:25:20: Unsupported: 'with' on task call 25 | aliases.find with (item == i); | ^~~~ %Error-UNSUPPORTED: t/t_with_unsup.v:29:36: Unsupported: 'with' on method call