[Bug #20680] ensure block is always void context

This commit is contained in:
Nobuyoshi Nakada 2024-08-17 20:50:24 +09:00
parent 519152db6d
commit 620ce3807b
No known key found for this signature in database
GPG Key ID: 3582D74E1FEE4465
Notes: git 2024-08-24 23:17:32 +00:00
4 changed files with 23 additions and 10 deletions

10
parse.y
View File

@ -3005,7 +3005,7 @@ program : {
top_compstmt : top_stmts terms?
{
$$ = void_stmts(p, $1);
void_stmts(p, $$ = $1);
}
;
@ -3082,7 +3082,7 @@ bodystmt : compstmt[body]
compstmt : stmts terms?
{
$$ = void_stmts(p, $1);
void_stmts(p, $$ = $1);
}
;
@ -5994,10 +5994,11 @@ exc_var : tASSOC lhs
| none
;
opt_ensure : k_ensure compstmt
opt_ensure : k_ensure stmts terms?
{
p->ctxt.in_rescue = $1.in_rescue;
$$ = $2;
void_expr(p, void_stmts(p, $$));
/*% ripper: ensure!($:2) %*/
}
| none
@ -14038,6 +14039,7 @@ void_expr(struct parser_params *p, NODE *node)
}
}
/* warns useless use of block and returns the last statement node */
static NODE *
void_stmts(struct parser_params *p, NODE *node)
{
@ -14050,7 +14052,7 @@ void_stmts(struct parser_params *p, NODE *node)
void_expr(p, RNODE_BLOCK(node)->nd_head);
node = RNODE_BLOCK(node)->nd_next;
}
return n;
return RNODE_BLOCK(node)->nd_head;
}
static NODE *

View File

@ -1304,9 +1304,10 @@ pm_void_statement_check(pm_parser_t *parser, const pm_node_t *node) {
* a "void" statement.
*/
static void
pm_void_statements_check(pm_parser_t *parser, const pm_statements_node_t *node) {
pm_void_statements_check(pm_parser_t *parser, const pm_statements_node_t *node, bool last_value) {
assert(node->body.size > 0);
for (size_t index = 0; index < node->body.size - 1; index++) {
const size_t size = node->body.size - (last_value ? 1 : 0);
for (size_t index = 0; index < size; index++) {
pm_void_statement_check(parser, node->body.nodes[index]);
}
}
@ -13858,7 +13859,16 @@ parse_statements(pm_parser_t *parser, pm_context_t context) {
}
context_pop(parser);
pm_void_statements_check(parser, statements);
bool last_value = true;
switch (context) {
case PM_CONTEXT_BEGIN_ENSURE:
case PM_CONTEXT_DEF_ENSURE:
last_value = false;
break;
default:
break;
}
pm_void_statements_check(parser, statements, last_value);
return statements;
}
@ -18052,7 +18062,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
pm_void_statements_check(parser, statements);
pm_void_statements_check(parser, statements, true);
return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous);
}
case PM_TOKEN_BRACE_LEFT: {

View File

@ -273,7 +273,7 @@ class TestAst < Test::Unit::TestCase
assert_parse("def m; defined?(retry); end")
assert_parse("!begin defined?(retry); end")
assert_parse("begin rescue; else; defined?(retry); end")
assert_parse("begin rescue; ensure; defined?(retry); end")
assert_parse("begin rescue; ensure; p defined?(retry); end")
assert_parse("END {defined?(retry)}")
assert_parse("begin rescue; END {defined?(retry)}; end")
assert_parse("!defined? retry")
@ -281,7 +281,7 @@ class TestAst < Test::Unit::TestCase
assert_parse("def m; defined? retry; end")
assert_parse("!begin defined? retry; end")
assert_parse("begin rescue; else; defined? retry; end")
assert_parse("begin rescue; ensure; defined? retry; end")
assert_parse("begin rescue; ensure; p defined? retry; end")
assert_parse("END {defined? retry}")
assert_parse("begin rescue; END {defined? retry}; end")

View File

@ -952,6 +952,7 @@ x = __ENCODING__
assert_nil assert_warning(useless_use) {eval("true; nil")}
assert_nil assert_warning(useless_use) {eval("false; nil")}
assert_nil assert_warning(useless_use) {eval("defined?(1); nil")}
assert_nil assert_warning(useless_use) {eval("begin; ensure; x; end")}
assert_equal 1, x
assert_syntax_error("1; next; 2", /Invalid next/)