From 7e18eba848d64e46fdd4a8b1bda2884fdbc079a3 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 4 Feb 2022 12:27:17 +0100 Subject: [PATCH 1/3] Add helper function to check end label Most named constructs support a end label in SystemVerilog. The handling of this end label is always the same. * Generate an error if the end label does not match the name of the block * Generate an error if not in SystemVerilog mode * Delete the end label Factor this into a common helper function. This reduces code size a bit and results in consistent error messages. The latter requires refreshing of some gold files to match the slightly different error messages. Signed-off-by: Lars-Peter Clausen --- ivtest/gold/sv_end_label_fail.gold | 30 ++--- ivtest/gold/sv_end_labels_bad.gold | 4 +- parse.y | 193 +++++++---------------------- 3 files changed, 60 insertions(+), 167 deletions(-) diff --git a/ivtest/gold/sv_end_label_fail.gold b/ivtest/gold/sv_end_label_fail.gold index 6c1b2492b..3c172d4e6 100644 --- a/ivtest/gold/sv_end_label_fail.gold +++ b/ivtest/gold/sv_end_label_fail.gold @@ -1,15 +1,15 @@ -./ivltests/sv_end_label_fail.v:4: error: End label doesn't match begin name -./ivltests/sv_end_label_fail.v:7: error: End label doesn't match fork name -./ivltests/sv_end_label_fail.v:10: error: End label doesn't match fork name -./ivltests/sv_end_label_fail.v:13: error: End label doesn't match fork name -./ivltests/sv_end_label_fail.v:16: error: End label doesn't match task name -./ivltests/sv_end_label_fail.v:19: error: End label doesn't match task name -./ivltests/sv_end_label_fail.v:23: error: End label doesn't match function name -./ivltests/sv_end_label_fail.v:26: error: End label doesn't match function name -./ivltests/sv_end_label_fail.v:28: error: End label doesn't match module name. -./ivltests/sv_end_label_fail.v:38: error: End label doesn't match begin name -./ivltests/sv_end_label_fail.v:40: error: End label doesn't match module name. -./ivltests/sv_end_label_fail.v:43: error: End label doesn't match package name -./ivltests/sv_end_label_fail.v:47: error: Class end label doesn't match class name. -./ivltests/sv_end_label_fail.v:48: error: End label doesn't match program name. -./ivltests/sv_end_label_fail.v:64: error: End label doesn't match primitive name +./ivltests/sv_end_label_fail.v:4: error: block end label `b_label_f` doesn't match block name `b_label`. +./ivltests/sv_end_label_fail.v:7: error: fork end label `fj_label_f` doesn't match fork name `fj_label`. +./ivltests/sv_end_label_fail.v:10: error: fork end label `fja_label_f` doesn't match fork name `fja_label`. +./ivltests/sv_end_label_fail.v:13: error: fork end label `fjn_label_f` doesn't match fork name `fjn_label`. +./ivltests/sv_end_label_fail.v:16: error: task end label `t_label_f` doesn't match task name `t_label`. +./ivltests/sv_end_label_fail.v:19: error: task end label `twa_label_f` doesn't match task name `twa_label`. +./ivltests/sv_end_label_fail.v:23: error: function end label `fn_label_f` doesn't match function name `fn_label`. +./ivltests/sv_end_label_fail.v:26: error: function end label `fa_label_f` doesn't match function name `fa_label`. +./ivltests/sv_end_label_fail.v:28: error: module end label `top_f` doesn't match module name `top`. +./ivltests/sv_end_label_fail.v:38: error: block end label `g_label_f` doesn't match block name `g_label`. +./ivltests/sv_end_label_fail.v:40: error: module end label `extra_f` doesn't match module name `extra`. +./ivltests/sv_end_label_fail.v:43: error: package end label `pkg_f` doesn't match package name `pkg`. +./ivltests/sv_end_label_fail.v:47: error: class end label `foo_f` doesn't match class name `foo`. +./ivltests/sv_end_label_fail.v:48: error: program end label `pgm_f` doesn't match program name `pgm`. +./ivltests/sv_end_label_fail.v:64: error: primitive end label `pinv_f` doesn't match primitive name `pinv`. diff --git a/ivtest/gold/sv_end_labels_bad.gold b/ivtest/gold/sv_end_labels_bad.gold index 4e98a1ce8..392e99fbe 100644 --- a/ivtest/gold/sv_end_labels_bad.gold +++ b/ivtest/gold/sv_end_labels_bad.gold @@ -1,2 +1,2 @@ -./ivltests/sv_end_labels_bad.v:14: error: End label doesn't match begin name -./ivltests/sv_end_labels_bad.v:16: error: End label doesn't match module name. +./ivltests/sv_end_labels_bad.v:14: error: block end label `dummy_label_bad` doesn't match block name `dummy_label`. +./ivltests/sv_end_labels_bad.v:16: error: module end label `test_bad` doesn't match module name `test`. diff --git a/parse.y b/parse.y index 977cfa3de..a1d714f1f 100644 --- a/parse.y +++ b/parse.y @@ -284,6 +284,22 @@ static long check_enum_seq_value(const YYLTYPE&loc, verinum *arg, bool zero_ok) return value; } +static void check_end_label(const struct vlltype&loc, const char *type, + const char *begin, const char *end) +{ + if (!end) + return; + + if (strcmp(begin, end) != 0) + yyerror(loc, "error: %s end label `%s` doesn't match %s name" + " `%s`.", type, end, type, begin); + + if (!gn_system_verilog()) + yyerror(loc, "error: %s end label requires SystemVerilog.", type); + + delete[] end; +} + static void current_task_set_statement(const YYLTYPE&loc, std::vector*s) { if (s == 0) { @@ -788,10 +804,7 @@ class_declaration /* IEEE1800-2005: A.1.2 */ } class_declaration_endlabel_opt { // Wrap up the class. - if ($11 && $4 && $4->name != $11) { - yyerror(@11, "error: Class end label doesn't match class name."); - delete[]$11; - } + check_end_label(@11, "class", $4->name, $11); } ; @@ -1456,17 +1469,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */ } endlabel_opt { // Last step: check any closing name. - if ($11) { - if (strcmp($4,$11) != 0) { - yyerror(@11, "error: End label doesn't match " - "function name"); - } - if (! gn_system_verilog()) { - yyerror(@11, "error: Function end labels require " - "SystemVerilog."); - } - delete[]$11; - } + check_end_label(@11, "function", $4, $11); delete[]$4; } @@ -1490,17 +1493,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */ } endlabel_opt { // Last step: check any closing name. - if ($14) { - if (strcmp($4,$14) != 0) { - yyerror(@14, "error: End label doesn't match " - "function name"); - } - if (! gn_system_verilog()) { - yyerror(@14, "error: Function end labels require " - "SystemVerilog."); - } - delete[]$14; - } + check_end_label(@14, "function", $4, $14); delete[]$4; } @@ -1518,16 +1511,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */ } endlabel_opt { // Last step: check any closing name. - if ($8) { - if (strcmp($4,$8) != 0) { - yyerror(@8, "error: End label doesn't match function name"); - } - if (! gn_system_verilog()) { - yyerror(@8, "error: Function end labels require " - "SystemVerilog."); - } - delete[]$8; - } + check_end_label(@8, "function", $4, $8); delete[]$4; } @@ -1998,13 +1982,7 @@ package_declaration /* IEEE1800-2005 A.1.2 */ package_item_list_opt K_endpackage endlabel_opt { pform_end_package_declaration(@1); - // If an end label is present make sure it match the package name. - if ($10) { - if (strcmp($3,$10) != 0) { - yyerror(@10, "error: End label doesn't match package name"); - } - delete[]$10; - } + check_end_label(@10, "package", $3, $10); delete[]$3; } ; @@ -2336,16 +2314,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */ // endlabel_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. - if ($10) { - if (strcmp($3,$10) != 0) { - yyerror(@10, "error: End label doesn't match task name"); - } - if (! gn_system_verilog()) { - yyerror(@10, "error: Task end labels require " - "SystemVerilog."); - } - delete[]$10; - } + check_end_label(@10, "task", $3, $10); delete[]$3; } @@ -2374,16 +2343,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */ // endlabel_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. - if ($13) { - if (strcmp($3,$13) != 0) { - yyerror(@13, "error: End label doesn't match task name"); - } - if (! gn_system_verilog()) { - yyerror(@13, "error: Task end labels require " - "SystemVerilog."); - } - delete[]$13; - } + check_end_label(@13, "task", $3, $13); delete[]$3; } @@ -2400,16 +2360,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */ // endlabel_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. - if ($7) { - if (strcmp($3,$7) != 0) { - yyerror(@7, "error: End label doesn't match task name"); - } - if (! gn_system_verilog()) { - yyerror(@7, "error: Task end labels require " - "SystemVerilog."); - } - delete[]$7; - } + check_end_label(@7, "task", $3, $7); delete[]$3; } @@ -4927,30 +4878,18 @@ module // endlabel_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. - if ($17) { - if (strcmp($4,$17) != 0) { - switch ($2) { - case K_module: - yyerror(@17, "error: End label doesn't match " - "module name."); - break; - case K_program: - yyerror(@17, "error: End label doesn't match " - "program name."); - break; - case K_interface: - yyerror(@17, "error: End label doesn't match " - "interface name."); - break; - default: - break; - } - } - if (($2 == K_module) && (! gn_system_verilog())) { - yyerror(@8, "error: Module end labels require " - "SystemVerilog."); - } - delete[]$17; + switch ($2) { + case K_module: + check_end_label(@17, "module", $4, $17); + break; + case K_program: + check_end_label(@17, "program", $4, $17); + break; + case K_interface: + check_end_label(@17, "interface", $4, $17); + break; + default: + break; } delete[]$4; } @@ -5589,17 +5528,7 @@ generate_block | K_begin generate_item_list_opt K_end | K_begin ':' IDENTIFIER generate_item_list_opt K_end endlabel_opt { pform_generate_block_name($3); - if ($6) { - if (strcmp($3,$6) != 0) { - yyerror(@6, "error: End label doesn't match " - "begin name"); - } - if (! gn_system_verilog()) { - yyerror(@6, "error: Begin end labels require " - "SystemVerilog."); - } - delete[]$6; - } + check_end_label(@6, "block", $3, $6); delete[]$3; } ; @@ -6633,16 +6562,7 @@ statement_item /* This is roughly statement_item in the LRM */ current_block_stack.pop(); if ($6) tmp->set_statement(*$6); delete $6; - if ($8) { - if (strcmp($3,$8) != 0) { - yyerror(@8, "error: End label doesn't match begin name"); - } - if (! gn_system_verilog()) { - yyerror(@8, "error: Begin end labels require " - "SystemVerilog."); - } - delete[]$8; - } + check_end_label(@8, "block", $3, $8); delete[]$3; $$ = tmp; } @@ -6701,16 +6621,7 @@ statement_item /* This is roughly statement_item in the LRM */ tmp->set_join_type($7); if ($6) tmp->set_statement(*$6); delete $6; - if ($8) { - if (strcmp($3,$8) != 0) { - yyerror(@8, "error: End label doesn't match fork name"); - } - if (! gn_system_verilog()) { - yyerror(@8, "error: Fork end labels require " - "SystemVerilog."); - } - delete[]$8; - } + check_end_label(@8, "fork", $3, $8); delete[]$3; $$ = tmp; } @@ -7403,17 +7314,8 @@ udp_primitive { perm_string tmp2 = lex_strings.make($2); pform_make_udp(tmp2, $4, $7, $9, $8, @2.text, @2.first_line); - if ($11) { - if (strcmp($2,$11) != 0) { - yyerror(@11, "error: End label doesn't match " - "primitive name"); - } - if (! gn_system_verilog()) { - yyerror(@11, "error: Primitive end labels " - "require SystemVerilog."); - } - delete[]$11; - } + + check_end_label(@11, "primitive", $2, $11); delete[]$2; } @@ -7430,17 +7332,8 @@ udp_primitive perm_string tmp6 = lex_strings.make($6); pform_make_udp(tmp2, $5, tmp6, $7, $9, $12, @2.text, @2.first_line); - if ($14) { - if (strcmp($2,$14) != 0) { - yyerror(@14, "error: End label doesn't match " - "primitive name"); - } - if (! gn_system_verilog()) { - yyerror(@14, "error: Primitive end labels " - "require SystemVerilog."); - } - delete[]$14; - } + + check_end_label(@14, "primitive", $2, $14); delete[]$2; delete[]$6; } From e950e2d0d35cc86cff0c7bdc391ae18c148d2b7c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 5 Feb 2022 13:32:34 +0100 Subject: [PATCH 2/3] Let the parser recover from end label on unnamed block Currently when encountering an end label on a unnamed block a 'syntax error' will be generated and the parser will give up. Slightly refactor the parser so that this case is detected, a more specific error message is generated and the parser can recover and continue. This also slightly reduces the parser since it allows to merge the almost identical rules for handling named and unnamed blocks. Signed-off-by: Lars-Peter Clausen --- parse.y | 154 ++++++++++++++++++++++++-------------------------------- 1 file changed, 66 insertions(+), 88 deletions(-) diff --git a/parse.y b/parse.y index a1d714f1f..25ed54c8d 100644 --- a/parse.y +++ b/parse.y @@ -290,7 +290,9 @@ static void check_end_label(const struct vlltype&loc, const char *type, if (!end) return; - if (strcmp(begin, end) != 0) + if (!begin) + yyerror(loc, "error: unnamed %s must not have end label.", type); + else if (strcmp(begin, end) != 0) yyerror(loc, "error: %s end label `%s` doesn't match %s name" " `%s`.", type, end, type, begin); @@ -606,7 +608,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector udp_initial udp_init_opt %type udp_initial_expr_opt -%type register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt +%type register_variable net_variable event_variable label_opt class_declaration_endlabel_opt %type block_identifier_opt %type register_variable_list net_variable_list event_variable_list %type list_of_identifiers loop_variables @@ -1467,7 +1469,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */ pform_pop_scope(); current_function = 0; } - endlabel_opt + label_opt { // Last step: check any closing name. check_end_label(@11, "function", $4, $11); delete[]$4; @@ -1491,7 +1493,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */ yyerror(@4, "error: Empty parenthesis syntax requires SystemVerilog."); } } - endlabel_opt + label_opt { // Last step: check any closing name. check_end_label(@14, "function", $4, $14); delete[]$4; @@ -1509,7 +1511,7 @@ function_declaration /* IEEE1800-2005: A.2.6 */ yyerror(@1, "error: Syntax error defining function."); yyerrok; } - endlabel_opt + label_opt { // Last step: check any closing name. check_end_label(@8, "function", $4, $8); delete[]$4; @@ -1980,7 +1982,7 @@ package_declaration /* IEEE1800-2005 A.1.2 */ timeunits_declaration_opt { pform_set_scope_timescale(@1); } package_item_list_opt - K_endpackage endlabel_opt + K_endpackage label_opt { pform_end_package_declaration(@1); check_end_label(@10, "package", $3, $10); delete[]$3; @@ -2308,10 +2310,10 @@ task_declaration /* IEEE1800-2005: A.2.7 */ } delete $7; } - endlabel_opt + label_opt { // Last step: check any closing name. This is done late so // that the parser can look ahead to detect the present - // endlabel_opt but still have the pform_endmodule() called + // label_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. check_end_label(@10, "task", $3, $10); @@ -2337,10 +2339,10 @@ task_declaration /* IEEE1800-2005: A.2.7 */ current_task = 0; if ($10) delete $10; } - endlabel_opt + label_opt { // Last step: check any closing name. This is done late so // that the parser can look ahead to detect the present - // endlabel_opt but still have the pform_endmodule() called + // label_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. check_end_label(@13, "task", $3, $13); @@ -2354,10 +2356,10 @@ task_declaration /* IEEE1800-2005: A.2.7 */ current_task = 0; } } - endlabel_opt + label_opt { // Last step: check any closing name. This is done late so // that the parser can look ahead to detect the present - // endlabel_opt but still have the pform_endmodule() called + // label_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. check_end_label(@7, "task", $3, $7); @@ -4872,10 +4874,10 @@ module } pform_endmodule($4, in_celldefine, ucd); } - endlabel_opt + label_opt { // Last step: check any closing name. This is done late so // that the parser can look ahead to detect the present - // endlabel_opt but still have the pform_endmodule() called + // label_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. switch ($2) { @@ -4912,7 +4914,7 @@ module_end | K_endinterface { $$ = K_interface; } ; -endlabel_opt +label_opt : ':' IDENTIFIER { $$ = $2; } | { $$ = 0; } ; @@ -5385,7 +5387,7 @@ module_item yyerrok; } - | K_function error K_endfunction endlabel_opt + | K_function error K_endfunction label_opt { yyerror(@1, "error: I give up on this function definition."); if ($4) { if (!gn_system_verilog()) { @@ -5525,11 +5527,11 @@ generate_block : { pform_generate_single_item = true; } module_item { pform_generate_single_item = false; } - | K_begin generate_item_list_opt K_end - | K_begin ':' IDENTIFIER generate_item_list_opt K_end endlabel_opt - { pform_generate_block_name($3); - check_end_label(@6, "block", $3, $6); - delete[]$3; + | K_begin label_opt generate_item_list_opt K_end label_opt + { if ($2) + pform_generate_block_name($2); + check_end_label(@5, "block", $2, $5); + delete[]$2; } ; @@ -6516,28 +6518,30 @@ statement_item /* This is roughly statement_item in the LRM */ the declarations. The scope is popped at the end of the block. */ /* In SystemVerilog an unnamed block can contain variable declarations. */ - | K_begin - { PBlock*tmp = pform_push_block_scope(@1, 0, PBlock::BL_SEQ); + | K_begin label_opt + { PBlock*tmp = pform_push_block_scope(@1, $2, PBlock::BL_SEQ); current_block_stack.push(tmp); } block_item_decls_opt - { if ($3) { - if (! gn_system_verilog()) { - yyerror("error: Variable declaration in unnamed block " - "requires SystemVerilog."); + { if (!$2) { + if ($4) { + if (! gn_system_verilog()) { + yyerror("error: Variable declaration in unnamed block " + "requires SystemVerilog."); + } + } else { + /* If there are no declarations in the scope then just delete it. */ + pform_pop_scope(); + assert(! current_block_stack.empty()); + PBlock*tmp = current_block_stack.top(); + current_block_stack.pop(); + delete tmp; } - } else { - /* If there are no declarations in the scope then just delete it. */ - pform_pop_scope(); - assert(! current_block_stack.empty()); - PBlock*tmp = current_block_stack.top(); - current_block_stack.pop(); - delete tmp; } } - statement_or_null_list_opt K_end + statement_or_null_list_opt K_end label_opt { PBlock*tmp; - if ($3) { + if ($2 || $4) { pform_pop_scope(); assert(! current_block_stack.empty()); tmp = current_block_stack.top(); @@ -6546,24 +6550,10 @@ statement_item /* This is roughly statement_item in the LRM */ tmp = new PBlock(PBlock::BL_SEQ); FILE_NAME(tmp, @1); } - if ($5) tmp->set_statement(*$5); - delete $5; - $$ = tmp; - } - | K_begin ':' IDENTIFIER - { PBlock*tmp = pform_push_block_scope(@1, $3, PBlock::BL_SEQ); - current_block_stack.push(tmp); - } - block_item_decls_opt - statement_or_null_list_opt K_end endlabel_opt - { pform_pop_scope(); - assert(! current_block_stack.empty()); - PBlock*tmp = current_block_stack.top(); - current_block_stack.pop(); if ($6) tmp->set_statement(*$6); delete $6; - check_end_label(@8, "block", $3, $8); - delete[]$3; + check_end_label(@8, "block", $2, $8); + delete[]$2; $$ = tmp; } @@ -6573,56 +6563,44 @@ statement_item /* This is roughly statement_item in the LRM */ code generator can do the right thing. */ /* In SystemVerilog an unnamed block can contain variable declarations. */ - | K_fork - { PBlock*tmp = pform_push_block_scope(@1, 0, PBlock::BL_PAR); + | K_fork label_opt + { PBlock*tmp = pform_push_block_scope(@1, $2, PBlock::BL_PAR); current_block_stack.push(tmp); } block_item_decls_opt - { if ($3) { - if (! gn_system_verilog()) { - yyerror("error: Variable declaration in unnamed block " - "requires SystemVerilog."); + { + if (!$2) { + if ($4) { + if (! gn_system_verilog()) { + yyerror("error: Variable declaration in unnamed block " + "requires SystemVerilog."); + } + } else { + /* If there are no declarations in the scope then just delete it. */ + pform_pop_scope(); + assert(! current_block_stack.empty()); + PBlock*tmp = current_block_stack.top(); + current_block_stack.pop(); + delete tmp; } - } else { - /* If there are no declarations in the scope then just delete it. */ - pform_pop_scope(); - assert(! current_block_stack.empty()); - PBlock*tmp = current_block_stack.top(); - current_block_stack.pop(); - delete tmp; } } - statement_or_null_list_opt join_keyword + statement_or_null_list_opt join_keyword label_opt { PBlock*tmp; - if ($3) { + if ($2 || $4) { pform_pop_scope(); assert(! current_block_stack.empty()); tmp = current_block_stack.top(); current_block_stack.pop(); - tmp->set_join_type($6); + tmp->set_join_type($7); } else { - tmp = new PBlock($6); + tmp = new PBlock($7); FILE_NAME(tmp, @1); } - if ($5) tmp->set_statement(*$5); - delete $5; - $$ = tmp; - } - | K_fork ':' IDENTIFIER - { PBlock*tmp = pform_push_block_scope(@1, $3, PBlock::BL_PAR); - current_block_stack.push(tmp); - } - block_item_decls_opt - statement_or_null_list_opt join_keyword endlabel_opt - { pform_pop_scope(); - assert(! current_block_stack.empty()); - PBlock*tmp = current_block_stack.top(); - current_block_stack.pop(); - tmp->set_join_type($7); if ($6) tmp->set_statement(*$6); delete $6; - check_end_label(@8, "fork", $3, $8); - delete[]$3; + check_end_label(@8, "fork", $2, $8); + delete[]$2; $$ = tmp; } @@ -7309,7 +7287,7 @@ udp_primitive udp_port_decls udp_init_opt udp_body - K_endprimitive endlabel_opt + K_endprimitive label_opt { perm_string tmp2 = lex_strings.make($2); pform_make_udp(tmp2, $4, $7, $9, $8, @@ -7326,7 +7304,7 @@ udp_primitive '(' K_output udp_reg_opt IDENTIFIER udp_initial_expr_opt ',' udp_input_declaration_list ')' ';' udp_body - K_endprimitive endlabel_opt + K_endprimitive label_opt { perm_string tmp2 = lex_strings.make($2); perm_string tmp6 = lex_strings.make($6); From 305a1a9262eedd95fca56892df89f27b6d873b21 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 6 Feb 2022 20:55:09 +0100 Subject: [PATCH 3/3] Add regression test for end labels on unnamed blocks An end label on an unnamed block should generate an error. Add a regression test to check this. Signed-off-by: Lars-Peter Clausen --- ivtest/gold/sv_end_labels_unnamed.gold | 3 +++ ivtest/ivltests/sv_end_labels_unnamed.v | 16 ++++++++++++++++ ivtest/regress-sv.list | 1 + 3 files changed, 20 insertions(+) create mode 100644 ivtest/gold/sv_end_labels_unnamed.gold create mode 100644 ivtest/ivltests/sv_end_labels_unnamed.v diff --git a/ivtest/gold/sv_end_labels_unnamed.gold b/ivtest/gold/sv_end_labels_unnamed.gold new file mode 100644 index 000000000..2979cbbc3 --- /dev/null +++ b/ivtest/gold/sv_end_labels_unnamed.gold @@ -0,0 +1,3 @@ +./ivltests/sv_end_labels_unnamed.v:7: error: unnamed block must not have end label. +./ivltests/sv_end_labels_unnamed.v:11: error: unnamed block must not have end label. +./ivltests/sv_end_labels_unnamed.v:14: error: unnamed fork must not have end label. diff --git a/ivtest/ivltests/sv_end_labels_unnamed.v b/ivtest/ivltests/sv_end_labels_unnamed.v new file mode 100644 index 000000000..eb8f788c8 --- /dev/null +++ b/ivtest/ivltests/sv_end_labels_unnamed.v @@ -0,0 +1,16 @@ +// Check that end labels on unnamed blocks generate an error + +module test; + + generate + if (1) begin + end : label + endgenerate + + initial begin + end : label + + initial fork + join : label + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 9a64bde65..f6045ebfe 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -451,6 +451,7 @@ sv_end_label normal,-g2005-sv ivltests sv_end_label_fail CE,-g2009 ivltests gold=sv_end_label_fail.gold sv_end_labels normal,-g2009 ivltests sv_end_labels_bad CE,-g2009 ivltests gold=sv_end_labels_bad.gold +sv_end_labels_unnamed CE,-g2009 ivltests gold=sv_end_labels_unnamed.gold sv_enum1 normal,-g2009 ivltests sv_for_variable normal,-g2009 ivltests sv_foreach1 normal,-g2009 ivltests