Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 7 additions & 25 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -1659,22 +1659,7 @@ static NODE *add_block_exit(struct parser_params *p, NODE *node);
static rb_node_exits_t *init_block_exit(struct parser_params *p);
static rb_node_exits_t *allow_block_exit(struct parser_params *p);
static void restore_block_exit(struct parser_params *p, rb_node_exits_t *exits);
static void clear_block_exit(struct parser_params *p, unsigned int error_mask);

static unsigned int
exits_mask(enum node_type t)
{
switch (t) {
case NODE_BREAK:
case NODE_NEXT:
case NODE_REDO:
return 1u << (t - NODE_BREAK);
default:
UNREACHABLE_RETURN(0);
}
}

#define EXITS_MASK_ALL (exits_mask(NODE_BREAK)|exits_mask(NODE_NEXT)|exits_mask(NODE_REDO))
static void clear_block_exit(struct parser_params *p, bool error);

static void
next_rescue_context(struct lex_context *next, const struct lex_context *outer, enum rescue_context def)
Expand All @@ -1692,7 +1677,7 @@ restore_defun(struct parser_params *p, rb_node_def_temp_t *temp)
p->ctxt.in_rescue = ctxt.in_rescue;
p->max_numparam = temp->save.max_numparam;
numparam_pop(p, temp->save.numparam_save);
clear_block_exit(p, EXITS_MASK_ALL);
clear_block_exit(p, true);
}

static void
Expand Down Expand Up @@ -1849,23 +1834,20 @@ restore_block_exit(struct parser_params *p, rb_node_exits_t *exits)
}

static void
clear_block_exit(struct parser_params *p, unsigned int error_mask)
clear_block_exit(struct parser_params *p, bool error)
{
rb_node_exits_t *exits = p->exits;
if (!exits) return;
if (error_mask) {
if (error) {
for (NODE *e = RNODE(exits); (e = RNODE_EXITS(e)->nd_chain) != 0; ) {
switch (nd_type(e)) {
case NODE_BREAK:
if (!(error_mask & exits_mask(NODE_BREAK))) break;
yyerror1(&e->nd_loc, "Invalid break");
break;
case NODE_NEXT:
if (!(error_mask & exits_mask(NODE_NEXT))) break;
yyerror1(&e->nd_loc, "Invalid next");
break;
case NODE_REDO:
if (!(error_mask & exits_mask(NODE_REDO))) break;
yyerror1(&e->nd_loc, "Invalid redo");
break;
default:
Expand Down Expand Up @@ -3230,7 +3212,7 @@ top_stmts : none

top_stmt : stmt
{
clear_block_exit(p, EXITS_MASK_ALL);
clear_block_exit(p, true);
$$ = $1;
}
| keyword_BEGIN begin_block
Expand Down Expand Up @@ -3370,7 +3352,7 @@ stmt : keyword_alias[kw] fitem[new] {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fit
}
| stmt[body] modifier_while[mod] expr_value[cond_expr]
{
clear_block_exit(p, 0);
clear_block_exit(p, false);
if ($body && nd_type_p($body, NODE_BEGIN)) {
$$ = NEW_WHILE(cond(p, $cond_expr, &@cond_expr), RNODE_BEGIN($body)->nd_body, 0, &@$, &@mod, &NULL_LOC);
}
Expand Down Expand Up @@ -3401,7 +3383,7 @@ stmt : keyword_alias[kw] fitem[new] {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fit
}
| k_END[k_end] block_open[lbrace] compstmt(stmts)[body] '}'[rbrace]
{
clear_block_exit(p, exits_mask(NODE_BREAK) | exits_mask(NODE_REDO));
clear_block_exit(p, true);
restore_block_exit(p, $block_open);
p->ctxt = $k_end;
{
Expand Down
3 changes: 0 additions & 3 deletions prism/prism.c
Original file line number Diff line number Diff line change
Expand Up @@ -15332,9 +15332,6 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node) {
if (parser->version < PM_OPTIONS_VERSION_CRUBY_4_1) {
return;
}
if (PM_NODE_TYPE_P(node, PM_NEXT_NODE)) {
return;
}
}
PRISM_FALLTHROUGH
case PM_CONTEXT_DEF:
Expand Down
5 changes: 5 additions & 0 deletions test/prism/errors/4.1/end_block_exit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@ END {
^~~~~ Invalid break
}

END {
next
^~~~ Invalid next
}

4 changes: 4 additions & 0 deletions test/prism/fixtures/3.3-4.0/end_block_exit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ END {
END {
break
}

END {
next
}
3 changes: 0 additions & 3 deletions test/prism/fixtures/end_block_exit.txt

This file was deleted.

7 changes: 2 additions & 5 deletions test/ruby/test_ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,8 @@ def test_invalid_exit
assert_invalid_parse(msg, "#{code}")
assert_invalid_parse(msg, "def m; #{code}; end")
assert_invalid_parse(msg, "begin; #{code}; end")
if code.start_with?("next")
assert_parse("END {#{code}}")
else
assert_invalid_parse(msg, "END {#{code}}")
end
assert_invalid_parse(msg, "BEGIN {#{code}}")
assert_invalid_parse(msg, "END {#{code}}")

assert_parse("!defined?(#{code})")
assert_parse("def m; defined?(#{code}); end")
Expand Down