diff --git a/Changes b/Changes index 1adee83c5..143508bb8 100644 --- a/Changes +++ b/Changes @@ -9,6 +9,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** For --xml, add additional information, bug1372. [Jonathan Kimmitt] +**** Add circular typedef error, bug1388. [Al Grant] + **** Fix FST tracing of wide arrays, bug1376. [Aleksander Osman] **** Fix error when pattern assignment has too few elements, bug1378. [Viktor Tomov] diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 62f3dac49..99a1df347 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -929,8 +929,15 @@ void AstRange::dump(std::ostream& str) { if (littleEndian()) str<<" [LITTLE]"; } void AstRefDType::dump(std::ostream& str) { + static bool s_recursing = false; this->AstNodeDType::dump(str); - if (defp()) { str<<" -> "; defp()->dump(str); } + if (defp()) { + if (!s_recursing) { // Prevent infinite dump if circular typedefs + s_recursing = true; + str<<" -> "; defp()->dump(str); + s_recursing = false; + } + } else { str<<" -> UNLINKED"; } } void AstNodeClassDType::dump(std::ostream& str) { diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 501e18035..a9a1557a9 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -1043,12 +1043,24 @@ private: UINFO(4,"dtWidthed "<didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed - userIterateChildren(nodep, NULL); - if (nodep->subDTypep()) nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); - nodep->dtypeFrom(nodep->dtypeSkipRefp()); - nodep->widthFromSub(nodep->subDTypep()); - UINFO(4,"dtWidthed "<doingWidth()) { // Early exit if have circular parameter definition + nodep->v3error("Typedef's type is circular: "<prettyName()); + nodep->dtypeSetLogicBool(); + nodep->doingWidth(false); + return; + } + if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed + nodep->doingWidth(true); + userIterateChildren(nodep, NULL); + if (nodep->subDTypep()) nodep->refDTypep(iterateEditDTypep(nodep, nodep->subDTypep())); + // Effectively nodep->dtypeFrom(nodep->dtypeSkipRefp()); + // But might be recursive, so instead manually recurse into the referenced type + if (!nodep->defp()) nodep->v3fatalSrc("Unlinked"); + nodep->dtypeFrom(nodep->defp()); + userIterate(nodep->defp(), NULL); + nodep->widthFromSub(nodep->subDTypep()); + UINFO(4,"dtWidthed "<doingWidth(false); } virtual void visit(AstTypedef* nodep) { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed diff --git a/test_regress/t/t_typedef_circ_bad.out b/test_regress/t/t_typedef_circ_bad.out new file mode 100644 index 000000000..09126fefc --- /dev/null +++ b/test_regress/t/t_typedef_circ_bad.out @@ -0,0 +1,2 @@ +%Error: t/t_typedef_circ_bad.v:5: Typedef's type is circular: a_t +%Error: Exiting due to diff --git a/test_regress/t/t_typedef_circ_bad.pl b/test_regress/t/t_typedef_circ_bad.pl new file mode 100755 index 000000000..e88bd5043 --- /dev/null +++ b/test_regress/t/t_typedef_circ_bad.pl @@ -0,0 +1,19 @@ +#!/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. + +scenarios(vlt_all => 1); + +compile( + v_flags2 => ["--lint-only"], + fails => $Self->{vlt_all}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_typedef_circ_bad.v b/test_regress/t/t_typedef_circ_bad.v new file mode 100644 index 000000000..5c2075242 --- /dev/null +++ b/test_regress/t/t_typedef_circ_bad.v @@ -0,0 +1,6 @@ +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder + +typedef a_t; +typedef a_t b_t; +typedef b_t a_t;