comparison src/vim9compile.c @ 23440:b0587f7ec422 v8.2.2263

patch 8.2.2263: Vim9: compilation error with try-catch in skipped block Commit: https://github.com/vim/vim/commit/69f7050cebb0f069d6e39571961b9bbe8531c69a Author: Bram Moolenaar <Bram@vim.org> Date: Fri Jan 1 16:10:46 2021 +0100 patch 8.2.2263: Vim9: compilation error with try-catch in skipped block Problem: Vim9: compilation error with try-catch in skipped block. Solution: Do not bail out when generate_instr() returns NULL. (closes https://github.com/vim/vim/issues/7584)
author Bram Moolenaar <Bram@vim.org>
date Fri, 01 Jan 2021 16:15:04 +0100
parents ab163feb30cb
children b1dbbc81a011
comparison
equal deleted inserted replaced
23439:ce571f96b8a7 23440:b0587f7ec422
6914 // scope that holds the jumps that go to catch/finally/endtry 6914 // scope that holds the jumps that go to catch/finally/endtry
6915 try_scope = new_scope(cctx, TRY_SCOPE); 6915 try_scope = new_scope(cctx, TRY_SCOPE);
6916 if (try_scope == NULL) 6916 if (try_scope == NULL)
6917 return NULL; 6917 return NULL;
6918 6918
6919 // "catch" is set when the first ":catch" is found. 6919 if (cctx->ctx_skip != SKIP_YES)
6920 // "finally" is set when ":finally" or ":endtry" is found 6920 {
6921 try_scope->se_u.se_try.ts_try_label = instr->ga_len; 6921 // "catch" is set when the first ":catch" is found.
6922 if (generate_instr(cctx, ISN_TRY) == NULL) 6922 // "finally" is set when ":finally" or ":endtry" is found
6923 return NULL; 6923 try_scope->se_u.se_try.ts_try_label = instr->ga_len;
6924 if (generate_instr(cctx, ISN_TRY) == NULL)
6925 return NULL;
6926 }
6924 6927
6925 // scope for the try block itself 6928 // scope for the try block itself
6926 scope = new_scope(cctx, BLOCK_SCOPE); 6929 scope = new_scope(cctx, BLOCK_SCOPE);
6927 if (scope == NULL) 6930 if (scope == NULL)
6928 return NULL; 6931 return NULL;
6957 { 6960 {
6958 emsg(_(e_catch_unreachable_after_catch_all)); 6961 emsg(_(e_catch_unreachable_after_catch_all));
6959 return NULL; 6962 return NULL;
6960 } 6963 }
6961 6964
6962 // Jump from end of previous block to :finally or :endtry 6965 if (cctx->ctx_skip != SKIP_YES)
6963 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label, 6966 {
6967 // Jump from end of previous block to :finally or :endtry
6968 if (compile_jump_to_end(&scope->se_u.se_try.ts_end_label,
6964 JUMP_ALWAYS, cctx) == FAIL) 6969 JUMP_ALWAYS, cctx) == FAIL)
6965 return NULL; 6970 return NULL;
6966 6971
6967 // End :try or :catch scope: set value in ISN_TRY instruction 6972 // End :try or :catch scope: set value in ISN_TRY instruction
6968 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label; 6973 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
6969 if (isn->isn_arg.try.try_catch == 0) 6974 if (isn->isn_arg.try.try_catch == 0)
6970 isn->isn_arg.try.try_catch = instr->ga_len; 6975 isn->isn_arg.try.try_catch = instr->ga_len;
6971 if (scope->se_u.se_try.ts_catch_label != 0) 6976 if (scope->se_u.se_try.ts_catch_label != 0)
6972 { 6977 {
6973 // Previous catch without match jumps here 6978 // Previous catch without match jumps here
6974 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label; 6979 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
6975 isn->isn_arg.jump.jump_where = instr->ga_len; 6980 isn->isn_arg.jump.jump_where = instr->ga_len;
6981 }
6976 } 6982 }
6977 6983
6978 p = skipwhite(arg); 6984 p = skipwhite(arg);
6979 if (ends_excmd2(arg, p)) 6985 if (ends_excmd2(arg, p))
6980 { 6986 {
7017 scope->se_u.se_try.ts_catch_label = instr->ga_len; 7023 scope->se_u.se_try.ts_catch_label = instr->ga_len;
7018 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL) 7024 if (generate_JUMP(cctx, JUMP_IF_FALSE, 0) == FAIL)
7019 return NULL; 7025 return NULL;
7020 } 7026 }
7021 7027
7022 if (generate_instr(cctx, ISN_CATCH) == NULL) 7028 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_CATCH) == NULL)
7023 return NULL; 7029 return NULL;
7024 7030
7025 if (new_scope(cctx, BLOCK_SCOPE) == NULL) 7031 if (new_scope(cctx, BLOCK_SCOPE) == NULL)
7026 return NULL; 7032 return NULL;
7027 return p; 7033 return p;
7095 else 7101 else
7096 emsg(_(e_endif)); 7102 emsg(_(e_endif));
7097 return NULL; 7103 return NULL;
7098 } 7104 }
7099 7105
7100 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label; 7106 if (cctx->ctx_skip != SKIP_YES)
7101 if (isn->isn_arg.try.try_catch == 0 && isn->isn_arg.try.try_finally == 0) 7107 {
7102 { 7108 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_try_label;
7103 emsg(_(e_missing_catch_or_finally)); 7109 if (isn->isn_arg.try.try_catch == 0
7104 return NULL; 7110 && isn->isn_arg.try.try_finally == 0)
7105 } 7111 {
7106 7112 emsg(_(e_missing_catch_or_finally));
7107 // Fill in the "end" label in jumps at the end of the blocks, if not done 7113 return NULL;
7108 // by ":finally". 7114 }
7109 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx); 7115
7110 7116 // Fill in the "end" label in jumps at the end of the blocks, if not
7111 // End :catch or :finally scope: set value in ISN_TRY instruction 7117 // done by ":finally".
7112 if (isn->isn_arg.try.try_catch == 0) 7118 compile_fill_jump_to_end(&scope->se_u.se_try.ts_end_label, cctx);
7113 isn->isn_arg.try.try_catch = instr->ga_len; 7119
7114 if (isn->isn_arg.try.try_finally == 0) 7120 // End :catch or :finally scope: set value in ISN_TRY instruction
7115 isn->isn_arg.try.try_finally = instr->ga_len; 7121 if (isn->isn_arg.try.try_catch == 0)
7116 7122 isn->isn_arg.try.try_catch = instr->ga_len;
7117 if (scope->se_u.se_try.ts_catch_label != 0) 7123 if (isn->isn_arg.try.try_finally == 0)
7118 { 7124 isn->isn_arg.try.try_finally = instr->ga_len;
7119 // Last catch without match jumps here 7125
7120 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label; 7126 if (scope->se_u.se_try.ts_catch_label != 0)
7121 isn->isn_arg.jump.jump_where = instr->ga_len; 7127 {
7128 // Last catch without match jumps here
7129 isn = ((isn_T *)instr->ga_data) + scope->se_u.se_try.ts_catch_label;
7130 isn->isn_arg.jump.jump_where = instr->ga_len;
7131 }
7122 } 7132 }
7123 7133
7124 compile_endblock(cctx); 7134 compile_endblock(cctx);
7125 7135
7126 if (generate_instr(cctx, ISN_ENDTRY) == NULL) 7136 if (cctx->ctx_skip != SKIP_YES && generate_instr(cctx, ISN_ENDTRY) == NULL)
7127 return NULL; 7137 return NULL;
7128 return arg; 7138 return arg;
7129 } 7139 }
7130 7140
7131 /* 7141 /*