From 463ea57b0a12e4551f20b06487fe03b7f847747e Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 1 Mar 2023 22:36:42 -0500 Subject: [PATCH] Add error (vs previous warning) on enum value overflow. --- src/V3Width.cpp | 9 ++++++++- test_regress/t/t_enum_bad_value.out | 5 +++++ test_regress/t/t_enum_bad_value.pl | 20 ++++++++++++++++++++ test_regress/t/t_enum_bad_value.v | 13 +++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test_regress/t/t_enum_bad_value.out create mode 100755 test_regress/t/t_enum_bad_value.pl create mode 100644 test_regress/t/t_enum_bad_value.v diff --git a/src/V3Width.cpp b/src/V3Width.cpp index b5f7fff74..89ee71e5a 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -2288,10 +2288,17 @@ private: if (nodep->valuep()) { // else the value will be assigned sequentially // Default type is int, but common to assign narrower values, so minwidth from value userIterateAndNext(nodep->valuep(), WidthVP{CONTEXT_DET, PRELIM}.p()); + bool warnOn = true; + if (const AstConst* const constp = VN_CAST(nodep->valuep(), Const)) { + if (static_cast(constp->num().mostSetBitP1()) > nodep->width()) { + constp->v3error("Enum value exceeds width of enum type (IEEE 1800-2017 6.19)"); + warnOn = false; // Prevent normal WIDTHTRUNC + } + } // Minwidth does not come from value, as spec says set based on parent // and if we keep minwidth we'll consider it unsized which is incorrect iterateCheck(nodep, "Enum value", nodep->valuep(), CONTEXT_DET, FINAL, nodep->dtypep(), - EXTEND_EXP); + EXTEND_EXP, warnOn); // Always create a cast, to avoid later ENUMVALUE warnings nodep->valuep(new AstCast{nodep->valuep()->fileline(), nodep->valuep()->unlinkFrBack(), nodep->dtypep()}); diff --git a/test_regress/t/t_enum_bad_value.out b/test_regress/t/t_enum_bad_value.out new file mode 100644 index 000000000..052f16ac8 --- /dev/null +++ b/test_regress/t/t_enum_bad_value.out @@ -0,0 +1,5 @@ +%Error: t/t_enum_bad_value.v:10:19: Enum value exceeds width of enum type (IEEE 1800-2017 6.19) + : ... In instance t + 10 | VALUE_BAD = 8 + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_enum_bad_value.pl b/test_regress/t/t_enum_bad_value.pl new file mode 100755 index 000000000..0a723255a --- /dev/null +++ b/test_regress/t/t_enum_bad_value.pl @@ -0,0 +1,20 @@ +#!/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(linter => 1); + +lint( + verilator_flags2 => ["--Wno-fatal"], + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_enum_bad_value.v b/test_regress/t/t_enum_bad_value.v new file mode 100644 index 000000000..ed97f82a0 --- /dev/null +++ b/test_regress/t/t_enum_bad_value.v @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(); + + typedef enum [2:0] { + VALUE_BAD = 8 + } enum_t; + +endmodule