diff options
-rw-r--r-- | src/ex_eval.c | 3 | ||||
-rw-r--r-- | src/testdir/test_vim9_script.vim | 14 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9compile.c | 75 |
4 files changed, 57 insertions, 37 deletions
diff --git a/src/ex_eval.c b/src/ex_eval.c index 77dceccf0..6bc7c18b8 100644 --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -2018,7 +2018,8 @@ ex_endtry(exarg_T *eap) { idx = cstack->cs_idx; - if (in_vim9script() + // Check the flags only when not in a skipped block. + if (!skip && in_vim9script() && (cstack->cs_flags[idx] & (CSF_CATCH|CSF_FINALLY)) == 0) { // try/endtry without any catch or finally: give an error and diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index b11149a59..93dce8339 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -641,6 +641,20 @@ def Test_try_catch_throw() endtry END CheckScriptFailure(lines, 'E1032:') + + # skipping try-finally-endtry when try-finally-endtry is used in another block + lines =<< trim END + if v:true + try + finally + endtry + else + try + finally + endtry + endif + END + CheckDefAndScriptSuccess(lines) enddef def Test_try_in_catch() diff --git a/src/version.c b/src/version.c index 206234d9b..d1117610f 100644 --- a/src/version.c +++ b/src/version.c @@ -756,6 +756,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 3305, +/**/ 3304, /**/ 3303, diff --git a/src/vim9compile.c b/src/vim9compile.c index 23f0a746e..9d7af52a0 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -8569,49 +8569,52 @@ compile_finally(char_u *arg, cctx_T *cctx) return NULL; } - // End :catch or :finally scope: set value in ISN_TRY instruction - isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label; - if (isn->isn_arg.try.try_ref->try_finally != 0) + if (cctx->ctx_skip != SKIP_YES) { - emsg(_(e_finally_dup)); - return NULL; - } + // End :catch or :finally scope: set value in ISN_TRY instruction + isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label; + if (isn->isn_arg.try.try_ref->try_finally != 0) + { + emsg(_(e_finally_dup)); + return NULL; + } - this_instr = instr->ga_len; + this_instr = instr->ga_len; #ifdef FEAT_PROFILE - if (cctx->ctx_compile_type == CT_PROFILE - && ((isn_T *)instr->ga_data)[this_instr - 1] - .isn_type == ISN_PROF_START) - { - // jump to the profile start of the "finally" - --this_instr; - - // jump to the profile end above it - if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1] - .isn_type == ISN_PROF_END) + if (cctx->ctx_compile_type == CT_PROFILE + && ((isn_T *)instr->ga_data)[this_instr - 1] + .isn_type == ISN_PROF_START) + { + // jump to the profile start of the "finally" --this_instr; - } + + // jump to the profile end above it + if (this_instr > 0 && ((isn_T *)instr->ga_data)[this_instr - 1] + .isn_type == ISN_PROF_END) + --this_instr; + } #endif - // Fill in the "end" label in jumps at the end of the blocks. - compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, - this_instr, cctx); - - // If there is no :catch then an exception jumps to :finally. - if (isn->isn_arg.try.try_ref->try_catch == 0) - isn->isn_arg.try.try_ref->try_catch = this_instr; - isn->isn_arg.try.try_ref->try_finally = this_instr; - if (scope->se_u.se_try.ts_catch_label != 0) - { - // Previous catch without match jumps here - isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label; - isn->isn_arg.jump.jump_where = this_instr; - scope->se_u.se_try.ts_catch_label = 0; - } - if (generate_instr(cctx, ISN_FINALLY) == NULL) - return NULL; + // Fill in the "end" label in jumps at the end of the blocks. + compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, + this_instr, cctx); + + // If there is no :catch then an exception jumps to :finally. + if (isn->isn_arg.try.try_ref->try_catch == 0) + isn->isn_arg.try.try_ref->try_catch = this_instr; + isn->isn_arg.try.try_ref->try_finally = this_instr; + if (scope->se_u.se_try.ts_catch_label != 0) + { + // Previous catch without match jumps here + isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label; + isn->isn_arg.jump.jump_where = this_instr; + scope->se_u.se_try.ts_catch_label = 0; + } + if (generate_instr(cctx, ISN_FINALLY) == NULL) + return NULL; - // TODO: set index in ts_finally_label jumps + // TODO: set index in ts_finally_label jumps + } return arg; } |