forked from aniani/vim
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.
This commit is contained in:
parent
bd5da371aa
commit
05afceeddc
@ -738,6 +738,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
488,
|
||||||
/**/
|
/**/
|
||||||
487,
|
487,
|
||||||
/**/
|
/**/
|
||||||
|
@ -257,7 +257,7 @@ struct dfunc_S {
|
|||||||
// Functions defined with :def are stored in this growarray.
|
// Functions defined with :def are stored in this growarray.
|
||||||
// They are never removed, so that they can be found by index.
|
// They are never removed, so that they can be found by index.
|
||||||
// Deleted functions have the df_deleted flag set.
|
// Deleted functions have the df_deleted flag set.
|
||||||
garray_T def_functions = {0, 0, sizeof(dfunc_T), 200, NULL};
|
garray_T def_functions = {0, 0, sizeof(dfunc_T), 50, NULL};
|
||||||
#else
|
#else
|
||||||
extern garray_T def_functions;
|
extern garray_T def_functions;
|
||||||
#endif
|
#endif
|
||||||
|
@ -5029,11 +5029,12 @@ compile_execute(char_u *arg, cctx_T *cctx)
|
|||||||
* Adds the function to "def_functions".
|
* Adds the function to "def_functions".
|
||||||
* When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
|
* When "set_return_type" is set then set ufunc->uf_ret_type to the type of the
|
||||||
* return statement (used for lambda).
|
* return statement (used for lambda).
|
||||||
|
* This can be used recursively through compile_lambda(), which may reallocate
|
||||||
|
* "def_functions".
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
compile_def_function(ufunc_T *ufunc, int set_return_type)
|
compile_def_function(ufunc_T *ufunc, int set_return_type)
|
||||||
{
|
{
|
||||||
dfunc_T *dfunc;
|
|
||||||
char_u *line = NULL;
|
char_u *line = NULL;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
exarg_T ea;
|
exarg_T ea;
|
||||||
@ -5046,25 +5047,29 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
|
|||||||
sctx_T save_current_sctx = current_sctx;
|
sctx_T save_current_sctx = current_sctx;
|
||||||
int emsg_before = called_emsg;
|
int emsg_before = called_emsg;
|
||||||
|
|
||||||
if (ufunc->uf_dfunc_idx >= 0)
|
|
||||||
{
|
{
|
||||||
// Redefining a function that was compiled before.
|
dfunc_T *dfunc; // may be invalidated by compile_lambda()
|
||||||
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
|
|
||||||
|
|
||||||
// Free old instructions.
|
if (ufunc->uf_dfunc_idx >= 0)
|
||||||
delete_def_function_contents(dfunc);
|
{
|
||||||
}
|
// Redefining a function that was compiled before.
|
||||||
else
|
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
|
||||||
{
|
|
||||||
// Add the function to "def_functions".
|
// Free old instructions.
|
||||||
if (ga_grow(&def_functions, 1) == FAIL)
|
delete_def_function_contents(dfunc);
|
||||||
return;
|
}
|
||||||
dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
|
else
|
||||||
vim_memset(dfunc, 0, sizeof(dfunc_T));
|
{
|
||||||
dfunc->df_idx = def_functions.ga_len;
|
// Add the function to "def_functions".
|
||||||
ufunc->uf_dfunc_idx = dfunc->df_idx;
|
if (ga_grow(&def_functions, 1) == FAIL)
|
||||||
dfunc->df_ufunc = ufunc;
|
return;
|
||||||
++def_functions.ga_len;
|
dfunc = ((dfunc_T *)def_functions.ga_data) + def_functions.ga_len;
|
||||||
|
vim_memset(dfunc, 0, sizeof(dfunc_T));
|
||||||
|
dfunc->df_idx = def_functions.ga_len;
|
||||||
|
ufunc->uf_dfunc_idx = dfunc->df_idx;
|
||||||
|
dfunc->df_ufunc = ufunc;
|
||||||
|
++def_functions.ga_len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vim_memset(&cctx, 0, sizeof(cctx));
|
vim_memset(&cctx, 0, sizeof(cctx));
|
||||||
@ -5414,10 +5419,14 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
|
|||||||
generate_instr(&cctx, ISN_RETURN);
|
generate_instr(&cctx, ISN_RETURN);
|
||||||
}
|
}
|
||||||
|
|
||||||
dfunc->df_deleted = FALSE;
|
{
|
||||||
dfunc->df_instr = instr->ga_data;
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||||
dfunc->df_instr_count = instr->ga_len;
|
+ ufunc->uf_dfunc_idx;
|
||||||
dfunc->df_varcount = cctx.ctx_max_local;
|
dfunc->df_deleted = FALSE;
|
||||||
|
dfunc->df_instr = instr->ga_data;
|
||||||
|
dfunc->df_instr_count = instr->ga_len;
|
||||||
|
dfunc->df_varcount = cctx.ctx_max_local;
|
||||||
|
}
|
||||||
|
|
||||||
ret = OK;
|
ret = OK;
|
||||||
|
|
||||||
@ -5425,6 +5434,8 @@ erret:
|
|||||||
if (ret == FAIL)
|
if (ret == FAIL)
|
||||||
{
|
{
|
||||||
int idx;
|
int idx;
|
||||||
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||||
|
+ ufunc->uf_dfunc_idx;
|
||||||
|
|
||||||
for (idx = 0; idx < instr->ga_len; ++idx)
|
for (idx = 0; idx < instr->ga_len; ++idx)
|
||||||
delete_instr(((isn_T *)instr->ga_data) + idx);
|
delete_instr(((isn_T *)instr->ga_data) + idx);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user