From 0c7341be3714ed27c2e9246ecff8784593a11ff1 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 3 Jul 2026 18:10:54 -0700 Subject: [PATCH 1/2] Support enum items shadowing type identifiers SystemVerilog allows a declaration in an inner scope to use the same name as a type identifier from an outer scope. This also applies to enum item names. The lexer reports such names as `TYPE_IDENTIFIER` before the enum item has been installed, which made constructs such as: typedef int T; module test; enum { T = 1 } e; endmodule fail in the enum item grammar. Enum item declarations do not have the local type/name ambiguity that exists for variable, net, or parameter declarations. The name in each `enum_name` production is always the enum item name, including the sequence forms like `T[2]` and `T[1:2]`. Use `identifier_name` for these names so they can shadow a visible type identifier. Signed-off-by: Lars-Peter Clausen --- parse.y | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/parse.y b/parse.y index 0803658e8..c7c655661 100644 --- a/parse.y +++ b/parse.y @@ -3242,20 +3242,23 @@ pos_neg_number } ; + /* Enum items are declaration names. Use identifier_name so an enum item can + shadow a visible type identifier without introducing a type/name + ambiguity. */ enum_name - : IDENTIFIER initializer_opt + : identifier_name initializer_opt { perm_string name = lex_strings.make($1); delete[]$1; $$ = make_named_number(@$, name, $2); } - | IDENTIFIER '[' pos_neg_number ']' initializer_opt + | identifier_name '[' pos_neg_number ']' initializer_opt { perm_string name = lex_strings.make($1); long count = check_enum_seq_value(@1, $3, false); $$ = make_named_numbers(@$, name, 0, count-1, $5); delete[]$1; delete $3; } - | IDENTIFIER '[' pos_neg_number ':' pos_neg_number ']' initializer_opt + | identifier_name '[' pos_neg_number ':' pos_neg_number ']' initializer_opt { perm_string name = lex_strings.make($1); $$ = make_named_numbers(@$, name, check_enum_seq_value(@1, $3, true), check_enum_seq_value(@1, $5, true), $7); From 43817251f4c55f4f7cc14fa661a1626d0b1b6b0a Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 3 Jul 2026 18:13:51 -0700 Subject: [PATCH 2/2] Add regression test for enum items shadowing type identifiers Check that enum item names can shadow visible type identifiers. Cover plain enum items as well as the counted and ranged enum item sequence forms. Signed-off-by: Lars-Peter Clausen --- .../sv_type_identifier_enum_item_name.v | 40 +++++++++++++++++++ ivtest/regress-vvp.list | 1 + .../sv_type_identifier_enum_item_name.json | 9 +++++ 3 files changed, 50 insertions(+) create mode 100644 ivtest/ivltests/sv_type_identifier_enum_item_name.v create mode 100644 ivtest/vvp_tests/sv_type_identifier_enum_item_name.json diff --git a/ivtest/ivltests/sv_type_identifier_enum_item_name.v b/ivtest/ivltests/sv_type_identifier_enum_item_name.v new file mode 100644 index 000000000..9be765a20 --- /dev/null +++ b/ivtest/ivltests/sv_type_identifier_enum_item_name.v @@ -0,0 +1,40 @@ +// Check that enum item names can shadow visible type identifiers. + +typedef int T; +typedef int U; +typedef int V; + +module test; + + reg failed; + + `define check(value, expected, error) \ + if ((value) !== (expected)) begin \ + $display("FAILED(%0d). %s", `__LINE__, error); \ + $display(" expected %0h, got %0h", expected, value); \ + failed = 1'b1; \ + end + + enum { + T = 3, + U[2] = 5, + V[3:4] = 9 + } e; + + initial begin + failed = 1'b0; + + e = T; + + `check(e, 3, "Enum item name did not hide typedef"); + `check(U0, 5, "Enum item sequence name did not hide typedef"); + `check(U1, 6, "Enum item sequence value mismatch"); + `check(V3, 9, "Enum item range name did not hide typedef"); + `check(V4, 10, "Enum item range value mismatch"); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index b7bf85cc5..2c8699b64 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -386,6 +386,7 @@ sv_soft_packed_union_fail1 vvp_tests/sv_soft_packed_union_fail1.json sv_super_member_fail vvp_tests/sv_super_member_fail.json sv_type_identifier_ams_name_fields vvp_tests/sv_type_identifier_ams_name_fields.json sv_type_identifier_config_name vvp_tests/sv_type_identifier_config_name.json +sv_type_identifier_enum_item_name vvp_tests/sv_type_identifier_enum_item_name.json sv_type_identifier_foreach_name vvp_tests/sv_type_identifier_foreach_name.json sv_type_identifier_genvar_name vvp_tests/sv_type_identifier_genvar_name.json sv_type_identifier_modport_name vvp_tests/sv_type_identifier_modport_name.json diff --git a/ivtest/vvp_tests/sv_type_identifier_enum_item_name.json b/ivtest/vvp_tests/sv_type_identifier_enum_item_name.json new file mode 100644 index 000000000..25adc3e46 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_identifier_enum_item_name.json @@ -0,0 +1,9 @@ +{ + "type" : "normal", + "source" : "sv_type_identifier_enum_item_name.v", + "iverilog-args" : [ "-g2005-sv" ], + "vlog95" : { + "__comment" : "Enums are SystemVerilog", + "type" : "CE" + } +}