From a0e52401091546b1e8ad2d0ad8101805b96c7cb4 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 27 Jun 2026 12:28:24 -0700 Subject: [PATCH 1/2] Support assertion item labels shadowing type identifiers SystemVerilog assertion item labels use ordinary identifiers. A visible type identifier should therefore be accepted as the label on a module level assertion item: typedef int CHECK; module test; CHECK: assert property (1); endmodule Procedural assertion statements already accept either identifier token in their optional label rule. Reusing that rule for module level concurrent and deferred assertion items exposes a declaration ambiguity: module items can also start with a typedef name followed by a variable declaration. Keep the grammar conflict-free by parsing typedef-start variable declarations in a single production that includes the first declarator. This lets the parser see `:` before reducing the typedef-start declaration path, so module and procedural assertions can share the same label rule while preserving the existing declaration handling for typedef data types. Signed-off-by: Lars-Peter Clausen --- parse.y | 71 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/parse.y b/parse.y index 6a78b6eb8..44ce2341f 100644 --- a/parse.y +++ b/parse.y @@ -936,7 +936,6 @@ Module::port_t *module_declare_interface_port(const YYLTYPE&loc, char *type, %type udp_initial udp_init_opt %type event_variable label_opt interface_port_modport_opt -%type block_identifier_opt %type identifier_name %type event_variable_list %type genvar_identifier_list list_of_identifiers @@ -1001,6 +1000,7 @@ Module::port_t *module_declare_interface_port(const YYLTYPE&loc, char *type, %type net_decl_assigns list_of_variable_decl_assignments %type list_of_net_decl_assignments_with_type %type list_of_variable_decl_assignments_with_type +%type type_identifier_variable_decl_assignments_with_type %type data_type data_type_opt data_type_or_implicit data_type_or_implicit_or_void %type block_reg_data_type @@ -1156,15 +1156,8 @@ assignment_pattern /* IEEE1800-2005: A.6.7.1 */ } ; - /* Some rules have a ... [ block_identifier ':' ] ... part. This - implements it in a LALR way. */ -block_identifier_opt /* */ - : IDENTIFIER ':' - { $$ = $1; } - | - { $$ = 0; } - ; - + /* Assertion items have an optional block identifier prefix. Consume the + label here because its spelling is not used when assertions are parsed. */ assertion_item_label_opt : identifier_name ':' { delete[]$1; } @@ -1375,9 +1368,8 @@ class_new /* IEEE1800-2005 A.2.4 */ concurrent_assertion_statement and checker_instantiation rules. */ concurrent_assertion_item /* IEEE1800-2012 A.2.10 */ - : block_identifier_opt concurrent_assertion_statement - { delete $1; - delete $2; + : assertion_item_label_opt concurrent_assertion_statement + { delete $2; } ; @@ -1736,9 +1728,8 @@ data_type_or_implicit_or_void ; deferred_immediate_assertion_item /* IEEE1800-2012: A.6.10 */ - : block_identifier_opt deferred_immediate_assertion_statement - { delete $1; - delete $2; + : assertion_item_label_opt deferred_immediate_assertion_statement + { delete $2; } ; @@ -2257,6 +2248,25 @@ list_of_variable_decl_assignments /* IEEE1800-2005 A.2.3 */ } ; +type_identifier_variable_decl_assignments_with_type + : TYPE_IDENTIFIER dimensions_opt list_of_variable_decl_assignments + { pform_set_type_referenced(@1, $1.text); + auto tmp = new typeref_t($1.type); + FILE_NAME(tmp, @1); + delete[]$1.text; + $$.decl_assignments = $3; + $$.type = pform_make_parray_type(@2, tmp, $2); + } + | package_scope TYPE_IDENTIFIER dimensions_opt list_of_variable_decl_assignments + { lex_in_package_scope(nullptr); + auto tmp = new typeref_t($2.type, $1); + FILE_NAME(tmp, @2); + delete[]$2.text; + $$.decl_assignments = $4; + $$.type = pform_make_parray_type(@3, tmp, $3); + } + ; + initializer_opt : '=' expression { $$ = $2; } | { $$ = nullptr; } @@ -3213,6 +3223,18 @@ attribute rule has presumably set up the scope. */ block_item_decl + : block_item_decl_no_type_identifier_start + | type_identifier_variable_decl_assignments_with_type ';' + { if ($1.type) pform_make_var(@1, $1.decl_assignments, $1.type, attributes_in_context, false); + var_lifetime = LexicalScope::INHERITED; + } + | ps_type_identifier_dim error ';' + { yyerror(@1, "error: Syntax error in variable list."); + yyerrok; + } + ; + +block_item_decl_no_type_identifier_start /* variable declarations. Note that data_type can be 0 if we are recovering from an error. */ @@ -3247,11 +3269,6 @@ block_item_decl var_lifetime = LexicalScope::INHERITED; } - | ps_type_identifier_dim list_of_variable_decl_assignments ';' - { if ($1) pform_make_var(@1, $2, $1, attributes_in_context, false); - var_lifetime = LexicalScope::INHERITED; - } - /* The extra `reg` is not valid (System)Verilog, this is an iverilog extension. */ | K_const variable_lifetime_opt K_reg reg_prefixed_atomic_type list_of_variable_decl_assignments ';' { if ($4) pform_make_var(@4, $5, $4, attributes_in_context, true); @@ -3295,10 +3312,6 @@ block_item_decl { yyerror(@1, "error: Syntax error in variable list."); yyerrok; } - | ps_type_identifier_dim error ';' - { yyerror(@1, "error: Syntax error in variable list."); - yyerrok; - } | K_event error ';' { yyerror(@1, "error: Syntax error in event variable list."); yyerrok; @@ -5613,7 +5626,13 @@ module_item /* block_item_decl rule is shared with task blocks and named begin/end. Careful to pass attributes to the block_item_decl. */ - | attribute_list_opt { attributes_in_context = $1; } block_item_decl + | attribute_list_opt type_identifier_variable_decl_assignments_with_type ';' + { if ($2.type) pform_make_var(@2, $2.decl_assignments, $2.type, $1, false); + var_lifetime = LexicalScope::INHERITED; + if ($1) delete $1; + } + + | attribute_list_opt { attributes_in_context = $1; } block_item_decl_no_type_identifier_start { delete attributes_in_context; attributes_in_context = 0; } From 713ad762af52ca0e7b6e678fdd63912e60ff4720 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 27 Jun 2026 12:28:38 -0700 Subject: [PATCH 2/2] Add regression test for assertion item labels shadowing type identifiers Check that a visible type identifier can be shadowed by labels on module level assertion items. Cover both a concurrent assertion item and a deferred immediate assertion item. Signed-off-by: Lars-Peter Clausen --- .../sv_type_identifier_assert_item_label.v | 15 +++++++++++++++ ivtest/regress-vvp.list | 1 + .../sv_type_identifier_assert_item_label.json | 5 +++++ 3 files changed, 21 insertions(+) create mode 100644 ivtest/ivltests/sv_type_identifier_assert_item_label.v create mode 100644 ivtest/vvp_tests/sv_type_identifier_assert_item_label.json diff --git a/ivtest/ivltests/sv_type_identifier_assert_item_label.v b/ivtest/ivltests/sv_type_identifier_assert_item_label.v new file mode 100644 index 000000000..07c457622 --- /dev/null +++ b/ivtest/ivltests/sv_type_identifier_assert_item_label.v @@ -0,0 +1,15 @@ +// Check that assertion item labels can shadow visible type identifiers. + +typedef int CHECK_A; +typedef int CHECK_B; + +module test; + + CHECK_A: assert property (1); + CHECK_B: assert final (1); + + initial begin + $display("PASSED"); + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 29d877666..629ea2a94 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -407,6 +407,7 @@ sv_soft_packed_union_fail1 vvp_tests/sv_soft_packed_union_fail1.json sv_string_method_substr_too_few_arg_fail vvp_tests/sv_string_method_substr_too_few_arg_fail.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_assert_item_label vvp_tests/sv_type_identifier_assert_item_label.json sv_type_identifier_assert_label vvp_tests/sv_type_identifier_assert_label.json sv_type_identifier_attribute_name vvp_tests/sv_type_identifier_attribute_name.json sv_type_identifier_attribute_target vvp_tests/sv_type_identifier_attribute_target.json diff --git a/ivtest/vvp_tests/sv_type_identifier_assert_item_label.json b/ivtest/vvp_tests/sv_type_identifier_assert_item_label.json new file mode 100644 index 000000000..05434ff05 --- /dev/null +++ b/ivtest/vvp_tests/sv_type_identifier_assert_item_label.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_type_identifier_assert_item_label.v", + "iverilog-args" : [ "-g2012", "-gsupported-assertions" ] +}