Mercurial > vim
comparison src/vim9compile.c @ 19864:8288884fdfe1 v8.2.0488
patch 8.2.0488: Vim9: compiling can break when using a lambda inside :def
Commit: https://github.com/vim/vim/commit/05afceeddc4afbbca60e4e6a729a50d33d4b19f7
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Mar 31 23:32:31 2020 +0200
patch 8.2.0488: Vim9: compiling can break when using a lambda inside :def
Problem: Vim9: Compiling can break when using a lambda inside :def.
Solution: Do not keep a pointer to the dfunc_T for longer time.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 31 Mar 2020 23:45:04 +0200 |
parents | 846fbbacce3a |
children | 1136ec381dd2 |
comparison
equal
deleted
inserted
replaced
19863:b6f8f6d22e8e | 19864:8288884fdfe1 |
---|---|
5027 * After ex_function() has collected all the function lines: parse and compile | 5027 * After ex_function() has collected all the function lines: parse and compile |
5028 * the lines into instructions. | 5028 * the lines into instructions. |
5029 * Adds the function to "def_functions". | 5029 * Adds the function to "def_functions". |
5030 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the | 5030 * When "set_return_type" is set then set ufunc->uf_ret_type to the type of the |
5031 * return statement (used for lambda). | 5031 * return statement (used for lambda). |
5032 * This can be used recursively through compile_lambda(), which may reallocate | |
5033 * "def_functions". | |
5032 */ | 5034 */ |
5033 void | 5035 void |
5034 compile_def_function(ufunc_T *ufunc, int set_return_type) | 5036 compile_def_function(ufunc_T *ufunc, int set_return_type) |
5035 { | 5037 { |
5036 dfunc_T *dfunc; | |
5037 char_u *line = NULL; | 5038 char_u *line = NULL; |
5038 char_u *p; | 5039 char_u *p; |
5039 exarg_T ea; | 5040 exarg_T ea; |
5040 char *errormsg = NULL; // error message | 5041 char *errormsg = NULL; // error message |
5041 int had_return = FALSE; | 5042 int had_return = FALSE; |
5044 int called_emsg_before = called_emsg; | 5045 int called_emsg_before = called_emsg; |
5045 int ret = FAIL; | 5046 int ret = FAIL; |
5046 sctx_T save_current_sctx = current_sctx; | 5047 sctx_T save_current_sctx = current_sctx; |
5047 int emsg_before = called_emsg; | 5048 int emsg_before = called_emsg; |
5048 | 5049 |
5049 if (ufunc->uf_dfunc_idx >= 0) | 5050 { |
5050 { | 5051 dfunc_T *dfunc; // may be invalidated by compile_lambda() |
5051 // Redefining a function that was compiled before. | 5052 |
5052 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; | 5053 if (ufunc->uf_dfunc_idx >= 0) |
5053 | 5054 { |
5054 // Free old instructions. | 5055 // Redefining a function that was compiled before. |
5055 delete_def_function_contents(dfunc); | 5056 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; |
5056 } | 5057 |
5057 else | 5058 // Free old instructions. |
5058 { | 5059 delete_def_function_contents(dfunc); |
5059 // Add the function to "def_functions". | 5060 } |
5060 if (ga_grow(&def_functions, 1) == FAIL) | 5061 else |
5061 return; | 5062 { |
5062 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len; | 5063 // Add the function to "def_functions". |
5063 vim_memset(dfunc, 0, sizeof(dfunc_T)); | 5064 if (ga_grow(&def_functions, 1) == FAIL) |
5064 dfunc->df_idx = def_functions.ga_len; | 5065 return; |
5065 ufunc->uf_dfunc_idx = dfunc->df_idx; | 5066 dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len; |
5066 dfunc->df_ufunc = ufunc; | 5067 vim_memset(dfunc, 0, sizeof(dfunc_T)); |
5067 ++def_functions.ga_len; | 5068 dfunc->df_idx = def_functions.ga_len; |
5069 ufunc->uf_dfunc_idx = dfunc->df_idx; | |
5070 dfunc->df_ufunc = ufunc; | |
5071 ++def_functions.ga_len; | |
5072 } | |
5068 } | 5073 } |
5069 | 5074 |
5070 vim_memset(&cctx, 0, sizeof(cctx)); | 5075 vim_memset(&cctx, 0, sizeof(cctx)); |
5071 cctx.ctx_ufunc = ufunc; | 5076 cctx.ctx_ufunc = ufunc; |
5072 cctx.ctx_lnum = -1; | 5077 cctx.ctx_lnum = -1; |
5412 // Return zero if there is no return at the end. | 5417 // Return zero if there is no return at the end. |
5413 generate_PUSHNR(&cctx, 0); | 5418 generate_PUSHNR(&cctx, 0); |
5414 generate_instr(&cctx, ISN_RETURN); | 5419 generate_instr(&cctx, ISN_RETURN); |
5415 } | 5420 } |
5416 | 5421 |
5417 dfunc->df_deleted = FALSE; | 5422 { |
5418 dfunc->df_instr = instr->ga_data; | 5423 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) |
5419 dfunc->df_instr_count = instr->ga_len; | 5424 + ufunc->uf_dfunc_idx; |
5420 dfunc->df_varcount = cctx.ctx_max_local; | 5425 dfunc->df_deleted = FALSE; |
5426 dfunc->df_instr = instr->ga_data; | |
5427 dfunc->df_instr_count = instr->ga_len; | |
5428 dfunc->df_varcount = cctx.ctx_max_local; | |
5429 } | |
5421 | 5430 |
5422 ret = OK; | 5431 ret = OK; |
5423 | 5432 |
5424 erret: | 5433 erret: |
5425 if (ret == FAIL) | 5434 if (ret == FAIL) |
5426 { | 5435 { |
5427 int idx; | 5436 int idx; |
5437 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) | |
5438 + ufunc->uf_dfunc_idx; | |
5428 | 5439 |
5429 for (idx = 0; idx < instr->ga_len; ++idx) | 5440 for (idx = 0; idx < instr->ga_len; ++idx) |
5430 delete_instr(((isn_T *)instr->ga_data) + idx); | 5441 delete_instr(((isn_T *)instr->ga_data) + idx); |
5431 ga_clear(instr); | 5442 ga_clear(instr); |
5432 | 5443 |