diff --git a/parse.y b/parse.y index 3dd8ecd39f..359a0cc261 100644 --- a/parse.y +++ b/parse.y @@ -14296,12 +14296,21 @@ value_expr_check(struct parser_params *p, NODE *node) } while (node) { switch (nd_type(node)) { + case NODE_ENSURE: + vn = RNODE_ENSURE(node)->nd_head; + node = RNODE_ENSURE(node)->nd_ensr; + /* nd_ensr should not be NULL, check it out next */ + if (vn && (vn = value_expr_check(p, vn))) { + goto found; + } + break; + case NODE_RETURN: case NODE_BREAK: case NODE_NEXT: case NODE_REDO: case NODE_RETRY: - return void_node ? void_node : node; + goto found; case NODE_CASE3: if (!RNODE_CASE3(node)->nd_body || !nd_type_p(RNODE_CASE3(node)->nd_body, NODE_IN)) { @@ -14312,7 +14321,7 @@ value_expr_check(struct parser_params *p, NODE *node) return NULL; } /* single line pattern matching with "=>" operator */ - return void_node ? void_node : node; + goto found; case NODE_BLOCK: while (RNODE_BLOCK(node)->nd_next) { @@ -14356,6 +14365,10 @@ value_expr_check(struct parser_params *p, NODE *node) } return NULL; + + found: + /* return the first found node */ + return void_node ? void_node : node; } static int diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 858c623bcc..7d7e7eebc0 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1434,7 +1434,12 @@ x = __ENCODING__ def test_void_value_in_rhs w = "void value expression" - ["x = return 1", "x = return, 1", "x = 1, return", "x, y = return"].each do |code| + [ + "x = return 1", "x = return, 1", "x = 1, return", "x, y = return", + "x = begin return ensure end", + "x = begin ensure return end", + "x = begin return ensure 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 diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 7ca7e2bcf7..954ad56156 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1411,7 +1411,6 @@ eom "#{return}" raise((return; "should not raise")) begin raise; ensure return; end; self - begin raise; ensure return; end and self nil&defined?0--begin e=no_method_error(); return; 0;end return puts('ignored') #=> ignored BEGIN {return}