From 5f733a1ae7e5fd20d4cba61af5408b33204fe8fc Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 28 Jan 2024 11:09:55 +0900 Subject: [PATCH] [Bug #20217] `rescue` block is void only if all children are void --- parse.y | 20 ++++++++++++++++++++ test/ruby/test_parse.rb | 8 ++++++++ 2 files changed, 28 insertions(+) diff --git a/parse.y b/parse.y index 359a0cc261..5b9955a66a 100644 --- a/parse.y +++ b/parse.y @@ -14305,6 +14305,26 @@ value_expr_check(struct parser_params *p, NODE *node) } break; + case NODE_RESCUE: + /* void only if all children are void */ + vn = RNODE_RESCUE(node)->nd_head; + if (!vn || !(vn = value_expr_check(p, vn))) return NULL; + if (!void_node) void_node = vn; + for (NODE *r = RNODE_RESCUE(node)->nd_resq; r; r = RNODE_RESBODY(r)->nd_next) { + if (!nd_type_p(r, NODE_RESBODY)) { + compile_error(p, "unexpected node"); + return NULL; + } + if (!(vn = value_expr_check(p, RNODE_RESBODY(r)->nd_body))) { + void_node = 0; + break; + } + if (!void_node) void_node = vn; + } + node = RNODE_RESCUE(node)->nd_else; + if (!node) return void_node; + break; + case NODE_RETURN: case NODE_BREAK: case NODE_NEXT: diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 7d7e7eebc0..f68bf96cd1 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1439,10 +1439,18 @@ x = __ENCODING__ "x = begin return ensure end", "x = begin ensure return end", "x = begin return ensure return end", + "x = begin return; rescue; return end", + "x = begin return; rescue; return; else return end", ].each do |code| ex = assert_syntax_error(code, w) assert_equal(1, ex.message.scan(w).size, ->{"same #{w.inspect} warning should be just once\n#{w.message}"}) end + [ + "x = begin return; rescue; end", + "x = begin return; rescue; return; else end", + ].each do |code| + assert_valid_syntax(code) + end end def eval_separately(code)