Patch 8.2.4071
Problem: Vim9: no detection of return in try/endtry. (Dominique Pellé)
Solution: Check if any of the blocks inside try/endtry did not end in
return.
Files: src/vim9.h, src/vim9compile.c, src/vim9cmds.c,
src/testdir/test_vim9_script.vim
*** ../vim-8.2.4070/src/vim9.h 2022-01-03 12:27:59.355039941 +0000
--- src/vim9.h 2022-01-12 15:59:01.409943723 +0000
***************
*** 594,599 ****
--- 594,601 ----
endlabel_T *ts_end_label; // jump to :finally or :endtry
int ts_catch_label; // instruction idx of last CATCH
int ts_caught_all; // "catch" without argument encountered
+ int ts_has_finally; // "finally" encountered
+ int ts_no_return; // one of the blocks did not end in return
} tryscope_T;
typedef enum {
*** ../vim-8.2.4070/src/vim9compile.c 2022-01-12 11:46:36.314615880 +0000
--- src/vim9compile.c 2022-01-12 16:06:00.544331815 +0000
***************
*** 3041,3047 ****
break;
case CMD_endtry:
line = compile_endtry(p, &cctx);
- cctx.ctx_had_return = FALSE;
break;
case CMD_throw:
line = compile_throw(p, &cctx);
--- 3041,3046 ----
*** ../vim-8.2.4070/src/vim9cmds.c 2022-01-06 21:38:07.822094822 +0000
--- src/vim9cmds.c 2022-01-12 16:03:43.108852149 +0000
***************
*** 1343,1348 ****
--- 1343,1350 ----
emsg(_(e_catch_unreachable_after_catch_all));
return NULL;
}
+ if (!cctx->ctx_had_return)
+ scope->se_u.se_try.ts_no_return = TRUE;
if (cctx->ctx_skip != SKIP_YES)
{
***************
*** 1498,1503 ****
--- 1500,1506 ----
isn->isn_arg.jump.jump_where = this_instr;
scope->se_u.se_try.ts_catch_label = 0;
}
+ scope->se_u.se_try.ts_has_finally = TRUE;
if (generate_instr(cctx, ISN_FINALLY) == NULL)
return NULL;
}
***************
*** 1567,1572 ****
--- 1570,1583 ----
}
}
+ // If there is a finally clause that ends in return then we will return.
+ // If one of the blocks didn't end in "return" or we did not catch all
+ // exceptions reset the had_return flag.
+ if (!(scope->se_u.se_try.ts_has_finally && cctx->ctx_had_return)
+ && (scope->se_u.se_try.ts_no_return
+ || !scope->se_u.se_try.ts_caught_all))
+ cctx->ctx_had_return = FALSE;
+
compile_endblock(cctx);
if (cctx->ctx_skip != SKIP_YES)
*** ../vim-8.2.4070/src/testdir/test_vim9_script.vim 2022-01-10 21:29:53.380429159 +0000
--- src/testdir/test_vim9_script.vim 2022-01-12 16:15:39.562178890 +0000
***************
*** 667,673 ****
finally
return 6
endtry
- return -1
enddef
assert_equal(6, ReturnInFinally())
--- 667,672 ----
***************
*** 708,713 ****
--- 707,770 ----
CheckDefAndScriptSuccess(lines)
enddef
+ def Test_try_ends_in_return()
+ var lines =<< trim END
+ vim9script
+ def Foo(): string
+ try
+ return 'foo'
+ catch
+ return 'caught'
+ endtry
+ enddef
+ assert_equal('foo', Foo())
+ END
+ CheckScriptSuccess(lines)
+
+ lines =<< trim END
+ vim9script
+ def Foo(): string
+ try
+ return 'foo'
+ catch
+ return 'caught'
+ endtry
+ echo 'notreached'
+ enddef
+ assert_equal('foo', Foo())
+ END
+ CheckScriptFailure(lines, 'E1095:')
+
+ lines =<< trim END
+ vim9script
+ def Foo(): string
+ try
+ return 'foo'
+ catch /x/
+ return 'caught'
+ endtry
+ enddef
+ assert_equal('foo', Foo())
+ END
+ CheckScriptFailure(lines, 'E1027:')
+
+ lines =<< trim END
+ vim9script
+ def Foo(): string
+ try
+ echo 'foo'
+ catch
+ echo 'caught'
+ finally
+ return 'done'
+ endtry
+ enddef
+ assert_equal('done', Foo())
+ END
+ CheckScriptSuccess(lines)
+
+ enddef
+
def Test_try_in_catch()
var lines =<< trim END
vim9script
*** ../vim-8.2.4070/src/version.c 2022-01-12 15:24:36.641292770 +0000
--- src/version.c 2022-01-12 15:52:28.623463378 +0000
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 4071,
/**/
--
DINGO: You must spank her well and after you have spanked her you
may deal with her as you like and then ... spank me.
AMAZING: And spank me!
STUNNER: And me.
LOVELY: And me.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///