зеркало из https://github.com/github/ruby.git
Out of place jumps are valid in `defined?`
This commit is contained in:
Родитель
29e5fca718
Коммит
5b36c11e21
22
parse.y
22
parse.y
|
@ -1493,10 +1493,12 @@ add_block_exit(struct parser_params *p, NODE *node)
|
|||
compile_error(p, "unexpected node: %s", ruby_node_name(nd_type(node)));
|
||||
break;
|
||||
}
|
||||
NODE *exits = p->exits;
|
||||
if (exits) {
|
||||
exits->nd_end->nd_next = node;
|
||||
exits->nd_end = node;
|
||||
if (!p->ctxt.in_defined) {
|
||||
NODE *exits = p->exits;
|
||||
if (exits) {
|
||||
exits->nd_end->nd_next = node;
|
||||
exits->nd_end = node;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
@ -3865,11 +3867,13 @@ primary : literal
|
|||
}
|
||||
| keyword_retry
|
||||
{
|
||||
switch (p->ctxt.in_rescue) {
|
||||
case before_rescue: yyerror1(&@1, "Invalid retry without rescue"); break;
|
||||
case after_rescue: /* ok */ break;
|
||||
case after_else: yyerror1(&@1, "Invalid retry after else"); break;
|
||||
case after_ensure: yyerror1(&@1, "Invalid retry after ensure"); break;
|
||||
if (!p->ctxt.in_defined) {
|
||||
switch (p->ctxt.in_rescue) {
|
||||
case before_rescue: yyerror1(&@1, "Invalid retry without rescue"); break;
|
||||
case after_rescue: /* ok */ break;
|
||||
case after_else: yyerror1(&@1, "Invalid retry after else"); break;
|
||||
case after_ensure: yyerror1(&@1, "Invalid retry after ensure"); break;
|
||||
}
|
||||
}
|
||||
/*%%%*/
|
||||
$$ = NEW_RETRY(&@$);
|
||||
|
|
|
@ -244,6 +244,15 @@ class TestAst < Test::Unit::TestCase
|
|||
assert_invalid_parse(msg, "def m; #{code}; end")
|
||||
assert_invalid_parse(msg, "begin; #{code}; end")
|
||||
assert_parse("END {#{code}}")
|
||||
|
||||
assert_parse("defined?(#{code})")
|
||||
assert_parse("def m; defined?(#{code}); end")
|
||||
assert_parse("begin; defined?(#{code}); end")
|
||||
|
||||
next if code.include?(" ")
|
||||
assert_parse("defined? #{code}")
|
||||
assert_parse("def m; defined? #{code}; end")
|
||||
assert_parse("begin; defined? #{code}; end")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -258,6 +267,22 @@ class TestAst < Test::Unit::TestCase
|
|||
assert_parse("nil rescue retry")
|
||||
assert_invalid_parse(msg, "END {retry}")
|
||||
assert_invalid_parse(msg, "begin rescue; END {retry}; end")
|
||||
|
||||
assert_parse("defined?(retry)")
|
||||
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("END {defined?(retry)}")
|
||||
assert_parse("begin rescue; END {defined?(retry)}; end")
|
||||
assert_parse("defined? retry")
|
||||
|
||||
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("END {defined? retry}")
|
||||
assert_parse("begin rescue; END {defined? retry}; end")
|
||||
end
|
||||
|
||||
def test_node_id_for_location
|
||||
|
|
|
@ -377,6 +377,10 @@ class TestRubyOptions < Test::Unit::TestCase
|
|||
assert_in_out_err(%w(-c -e begin -e next -e end), "", [], ["-e:2: Invalid next", :*])
|
||||
assert_in_out_err(%w(-c -e begin -e redo -e end), "", [], ["-e:2: Invalid redo", :*])
|
||||
assert_in_out_err(%w(-c -e begin -e retry -e end), "", [], ["-e:2: Invalid retry", :*])
|
||||
assert_in_out_err(%w(-c -e defined?(break)), "", ["Syntax OK"], [])
|
||||
assert_in_out_err(%w(-c -e defined?(next)), "", ["Syntax OK"], [])
|
||||
assert_in_out_err(%w(-c -e defined?(redo)), "", ["Syntax OK"], [])
|
||||
assert_in_out_err(%w(-c -e defined?(retry)), "", ["Syntax OK"], [])
|
||||
end
|
||||
|
||||
def test_invalid_option
|
||||
|
|
Загрузка…
Ссылка в новой задаче