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/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 0e307de18..e8b36c9a6 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -452,6 +452,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 diff --git a/parse.y b/parse.y index b11f4aa56..4850a0611 100644 --- a/parse.y +++ b/parse.y @@ -284,6 +284,24 @@ 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 (!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); + + 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) { @@ -590,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 @@ -789,10 +807,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); } ; @@ -1454,19 +1469,9 @@ function_declaration /* IEEE1800-2005: A.2.6 */ pform_pop_scope(); current_function = 0; } - endlabel_opt + label_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; } @@ -1488,19 +1493,9 @@ 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. - 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; } @@ -1516,18 +1511,9 @@ 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. - 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; } @@ -1996,15 +1982,9 @@ 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); - // 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; } ; @@ -2319,22 +2299,13 @@ 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. - 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; } @@ -2357,22 +2328,13 @@ 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. - 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; } @@ -2383,22 +2345,13 @@ 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. - 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; } @@ -4910,36 +4863,24 @@ 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. - 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; } @@ -4962,7 +4903,7 @@ module_end | K_endinterface { $$ = K_interface; } ; -endlabel_opt +label_opt : ':' IDENTIFIER { $$ = $2; } | { $$ = 0; } ; @@ -5435,7 +5376,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()) { @@ -5575,21 +5516,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); - 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; - } - 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; } ; @@ -6576,28 +6507,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(); @@ -6606,33 +6539,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; - 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; - } - delete[]$3; + check_end_label(@8, "block", $2, $8); + delete[]$2; $$ = tmp; } @@ -6642,65 +6552,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; - 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; - } - delete[]$3; + check_end_label(@8, "fork", $2, $8); + delete[]$2; $$ = tmp; } @@ -7387,22 +7276,13 @@ 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, @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; } @@ -7413,23 +7293,14 @@ 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); 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; }