To: vim_dev@googlegroups.com Subject: Patch 8.2.3077 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.3077 Problem: Vim9: an error in a catch block is not reported. Solution: Put the "in catch" flag in the try stack. (closes #8478) Files: src/vim9execute.c, src/testdir/test_vim9_script.vim *** ../vim-8.2.3076/src/vim9execute.c 2021-06-30 12:02:21.227862458 +0200 --- src/vim9execute.c 2021-06-30 19:52:59.466584740 +0200 *************** *** 26,32 **** typedef struct { int tcd_frame_idx; // ec_frame_idx at ISN_TRY int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY ! int tcd_save_in_catch; // saved ec_in_catch int tcd_catch_idx; // instruction of the first :catch or :finally int tcd_finally_idx; // instruction of the :finally block or zero int tcd_endtry_idx; // instruction of the :endtry --- 26,33 ---- typedef struct { int tcd_frame_idx; // ec_frame_idx at ISN_TRY int tcd_stack_len; // size of ectx.ec_stack at ISN_TRY ! int tcd_in_catch; // in catch or finally block ! int tcd_did_throw; // set did_throw in :endtry int tcd_catch_idx; // instruction of the first :catch or :finally int tcd_finally_idx; // instruction of the :finally block or zero int tcd_endtry_idx; // instruction of the :endtry *************** *** 83,89 **** funclocal_T ec_funclocal; garray_T ec_trystack; // stack of trycmd_T values - int ec_in_catch; // when TRUE in catch or finally block int ec_dfunc_idx; // current function index isn_T *ec_instr; // array with instructions --- 84,89 ---- *************** *** 1566,1585 **** *msg_list = NULL; } ! if (did_throw && !ectx->ec_in_catch) { garray_T *trystack = &ectx->ec_trystack; trycmd_T *trycmd = NULL; // An exception jumps to the first catch, finally, or returns from // the current function. ! if (trystack->ga_len > 0) ! trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; if (trycmd != NULL && trycmd->tcd_frame_idx == ectx->ec_frame_idx) { // jump to ":catch" or ":finally" ! ectx->ec_in_catch = TRUE; ectx->ec_iidx = trycmd->tcd_catch_idx; } else { --- 1566,1596 ---- *msg_list = NULL; } ! if (did_throw) { garray_T *trystack = &ectx->ec_trystack; trycmd_T *trycmd = NULL; + int index = trystack->ga_len; // An exception jumps to the first catch, finally, or returns from // the current function. ! while (index > 0) ! { ! trycmd = ((trycmd_T *)trystack->ga_data) + index - 1; ! if (!trycmd->tcd_in_catch) ! break; ! // In the catch and finally block of this try we have to go up ! // one level. ! --index; ! trycmd = NULL; ! } if (trycmd != NULL && trycmd->tcd_frame_idx == ectx->ec_frame_idx) { // jump to ":catch" or ":finally" ! trycmd->tcd_in_catch = TRUE; ectx->ec_iidx = trycmd->tcd_catch_idx; + did_throw = FALSE; // don't come back here until :endtry + trycmd->tcd_did_throw = TRUE; } else { *************** *** 3167,3174 **** CLEAR_POINTER(trycmd); trycmd->tcd_frame_idx = ectx->ec_frame_idx; trycmd->tcd_stack_len = ectx->ec_stack.ga_len; - trycmd->tcd_save_in_catch = ectx->ec_in_catch; - ectx->ec_in_catch = FALSE; trycmd->tcd_catch_idx = iptr->isn_arg.try.try_ref->try_catch; trycmd->tcd_finally_idx = --- 3178,3183 ---- *************** *** 3205,3210 **** --- 3214,3220 ---- trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; trycmd->tcd_caught = TRUE; + trycmd->tcd_did_throw = FALSE; } did_emsg = got_int = did_throw = FALSE; force_abort = need_rethrow = FALSE; *************** *** 3268,3274 **** --trylevel; trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len; ! ectx->ec_in_catch = trycmd->tcd_save_in_catch; if (trycmd->tcd_caught && current_exception != NULL) { // discard the exception --- 3278,3285 ---- --trylevel; trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len; ! if (trycmd->tcd_did_throw) ! did_throw = TRUE; if (trycmd->tcd_caught && current_exception != NULL) { // discard the exception *** ../vim-8.2.3076/src/testdir/test_vim9_script.vim 2021-06-30 12:02:21.227862458 +0200 --- src/testdir/test_vim9_script.vim 2021-06-30 19:32:45.012725213 +0200 *************** *** 631,636 **** --- 631,647 ---- END enddef + def Test_error_in_catch() + var lines =<< trim END + try + eval [][0] + catch /E684:/ + eval [][0] + endtry + END + CheckDefExecFailure(lines, 'E684:', 4) + enddef + " :while at the very start of a function that :continue jumps to def TryContinueFunc() while g:Count < 2 *************** *** 768,773 **** --- 779,808 ---- assert_equal('intry', ReturnFinally()) assert_equal('finally', g:in_finally) + + var l = [] + try + l->add('1') + throw 'bad' + l->add('x') + catch /bad/ + l->add('2') + try + l->add('3') + throw 'one' + l->add('x') + catch /one/ + l->add('4') + try + l->add('5') + throw 'more' + l->add('x') + catch /more/ + l->add('6') + endtry + endtry + endtry + assert_equal(['1', '2', '3', '4', '5', '6'], l) enddef def TryOne(): number *** ../vim-8.2.3076/src/version.c 2021-06-30 12:02:21.231862454 +0200 --- src/version.c 2021-06-30 18:41:54.410310932 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3077, /**/ -- Over the years, I've developed my sense of deja vu so acutely that now I can remember things that *have* happened before ... /// Bram Moolenaar -- Bram@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 ///