@@ -1659,7 +1659,22 @@ static NODE *add_block_exit(struct parser_params *p, NODE *node);
16591659static rb_node_exits_t *init_block_exit(struct parser_params *p);
16601660static rb_node_exits_t *allow_block_exit(struct parser_params *p);
16611661static void restore_block_exit(struct parser_params *p, rb_node_exits_t *exits);
1662- static void clear_block_exit(struct parser_params *p, bool error);
1662+ static void clear_block_exit(struct parser_params *p, unsigned int error_mask);
1663+
1664+ static unsigned int
1665+ exits_mask(enum node_type t)
1666+ {
1667+ switch (t) {
1668+ case NODE_BREAK:
1669+ case NODE_NEXT:
1670+ case NODE_REDO:
1671+ return 1u << (t - NODE_BREAK);
1672+ default:
1673+ UNREACHABLE_RETURN(0);
1674+ }
1675+ }
1676+
1677+ #define EXITS_MASK_ALL (exits_mask(NODE_BREAK)|exits_mask(NODE_NEXT)|exits_mask(NODE_REDO))
16631678
16641679static void
16651680next_rescue_context(struct lex_context *next, const struct lex_context *outer, enum rescue_context def)
@@ -1677,7 +1692,7 @@ restore_defun(struct parser_params *p, rb_node_def_temp_t *temp)
16771692 p->ctxt.in_rescue = ctxt.in_rescue;
16781693 p->max_numparam = temp->save.max_numparam;
16791694 numparam_pop(p, temp->save.numparam_save);
1680- clear_block_exit(p, true );
1695+ clear_block_exit(p, EXITS_MASK_ALL );
16811696}
16821697
16831698static void
@@ -1834,20 +1849,23 @@ restore_block_exit(struct parser_params *p, rb_node_exits_t *exits)
18341849}
18351850
18361851static void
1837- clear_block_exit(struct parser_params *p, bool error )
1852+ clear_block_exit(struct parser_params *p, unsigned int error_mask )
18381853{
18391854 rb_node_exits_t *exits = p->exits;
18401855 if (!exits) return;
1841- if (error ) {
1856+ if (error_mask ) {
18421857 for (NODE *e = RNODE(exits); (e = RNODE_EXITS(e)->nd_chain) != 0; ) {
18431858 switch (nd_type(e)) {
18441859 case NODE_BREAK:
1860+ if (!(error_mask & exits_mask(NODE_BREAK))) break;
18451861 yyerror1(&e->nd_loc, "Invalid break");
18461862 break;
18471863 case NODE_NEXT:
1864+ if (!(error_mask & exits_mask(NODE_NEXT))) break;
18481865 yyerror1(&e->nd_loc, "Invalid next");
18491866 break;
18501867 case NODE_REDO:
1868+ if (!(error_mask & exits_mask(NODE_REDO))) break;
18511869 yyerror1(&e->nd_loc, "Invalid redo");
18521870 break;
18531871 default:
@@ -3212,7 +3230,7 @@ top_stmts : none
32123230
32133231top_stmt : stmt
32143232 {
3215- clear_block_exit(p, true );
3233+ clear_block_exit(p, EXITS_MASK_ALL );
32163234 $$ = $1;
32173235 }
32183236 | keyword_BEGIN begin_block
@@ -3352,7 +3370,7 @@ stmt : keyword_alias[kw] fitem[new] {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fit
33523370 }
33533371 | stmt[body] modifier_while[mod] expr_value[cond_expr]
33543372 {
3355- clear_block_exit(p, false );
3373+ clear_block_exit(p, 0 );
33563374 if ($body && nd_type_p($body, NODE_BEGIN)) {
33573375 $$ = NEW_WHILE(cond(p, $cond_expr, &@cond_expr), RNODE_BEGIN($body)->nd_body, 0, &@$, &@mod, &NULL_LOC);
33583376 }
@@ -3363,7 +3381,7 @@ stmt : keyword_alias[kw] fitem[new] {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fit
33633381 }
33643382 | stmt[body] modifier_until[mod] expr_value[cond_expr]
33653383 {
3366- clear_block_exit(p, false );
3384+ clear_block_exit(p, 0 );
33673385 if ($body && nd_type_p($body, NODE_BEGIN)) {
33683386 $$ = NEW_UNTIL(cond(p, $cond_expr, &@cond_expr), RNODE_BEGIN($body)->nd_body, 0, &@$, &@mod, &NULL_LOC);
33693387 }
@@ -3381,9 +3399,10 @@ stmt : keyword_alias[kw] fitem[new] {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fit
33813399 $$ = NEW_RESCUE(remove_begin($body), resq, 0, &@$);
33823400 /*% ripper: rescue_mod!($:body, $:resbody) %*/
33833401 }
3384- | k_END[k_end] allow_exits[allow] '{' [lbrace] compstmt(stmts)[body] '}'[rbrace]
3402+ | k_END[k_end] block_open [lbrace] compstmt(stmts)[body] '}'[rbrace]
33853403 {
3386- restore_block_exit(p, $allow);
3404+ clear_block_exit(p, exits_mask(NODE_BREAK) | exits_mask(NODE_REDO));
3405+ restore_block_exit(p, $block_open);
33873406 p->ctxt = $k_end;
33883407 {
33893408 NODE *scope = NEW_SCOPE2(0 /* tbl */, 0 /* args */, $body /* body */, NULL /* parent */, &@$);
0 commit comments