diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index e7391c1d7..e786acfdf 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1089,6 +1089,12 @@ class LinkDotFindVisitor : public AstNVisitor { iterateChildren(nodep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); } + virtual void visit(AstTypedefFwd* nodep) VL_OVERRIDE { + UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit"); + iterateChildren(nodep); + // No need to insert, only the real typedef matters, but need to track for errors + nodep->user1p(m_curSymp); + } virtual void visit(AstParamTypeDType* nodep) VL_OVERRIDE { UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit"); iterateChildren(nodep); @@ -1339,6 +1345,19 @@ private: // We're done with implicit gates VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } + virtual void visit(AstTypedefFwd* nodep) VL_OVERRIDE { + VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->name()); + if (!foundp && v3Global.opt.pedantic()) { + // We only check it was ever really defined in pedantic mode, as it + // might have been in a header file referring to a module we never + // needed so there are false positives + nodep->v3error( + "Forward typedef unused or does not resolve to a data type (IEEE 1800-2017 6.18): " + << nodep->prettyNameQ()); + } + // We only needed the forward declaration in order to parse correctly. + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + } virtual void visit(AstNode* nodep) VL_OVERRIDE { // Default: Just iterate iterateChildren(nodep); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index c090cb03d..ce6b45d52 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -382,13 +382,6 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstTypedefFwd* nodep) VL_OVERRIDE { - // We only needed the forward declaration in order to parse correctly. - // We won't even check it was ever really defined, as it might have been in a header - // file referring to a module we never needed - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } - virtual void visit(AstForeach* nodep) VL_OVERRIDE { // FOREACH(array,loopvars,body) // -> BEGIN(declare vars, loopa=lowest; WHILE(loopa<=highest, ... body)) diff --git a/test_regress/t/t_typedef_unused_bad.out b/test_regress/t/t_typedef_unused_bad.out new file mode 100644 index 000000000..da1d69eae --- /dev/null +++ b/test_regress/t/t_typedef_unused_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_typedef_unused_bad.v:9:9: Forward typedef unused or does not resolve to a data type (IEEE 1800-2017 6.18): 'fwd_undecl_t' +typedef fwd_undecl_t; + ^~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_typedef_unused_bad.pl b/test_regress/t/t_typedef_unused_bad.pl new file mode 100755 index 000000000..7c259dcfb --- /dev/null +++ b/test_regress/t/t_typedef_unused_bad.pl @@ -0,0 +1,20 @@ +#!/usr/bin/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(linter => 1); + +lint( + verilator_flags2 => ["--Wpedantic"], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_typedef_unused_bad.v b/test_regress/t/t_typedef_unused_bad.v new file mode 100644 index 000000000..896840cd7 --- /dev/null +++ b/test_regress/t/t_typedef_unused_bad.v @@ -0,0 +1,9 @@ +// 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 logic ok_t; + +typedef fwd_undecl_t;