summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-03-15 15:57:04 +0000
committerBram Moolenaar <Bram@vim.org>2022-03-15 15:57:04 +0000
commit96923b7a14839e7505b194ab76e1f15bb88fa7ed (patch)
tree81ea9b6fd45875d67c735a49f08b9c26df6fe01d
parent1a572e9b3b497e0412b4001cd9c6859db0c35412 (diff)
downloadvim-git-96923b7a14839e7505b194ab76e1f15bb88fa7ed.tar.gz
patch 8.2.4573: a nested function is compiled for debugging without contextv8.2.4573
Problem: A nested function (closure) is compiled for debugging without context. Solution: Check if a nested function is marked for debugging before compiling it. Give an error when trying to compile a closure without its context. (closes #9951)
-rw-r--r--src/errors.h4
-rw-r--r--src/proto/vim9execute.pro1
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c8
-rw-r--r--src/vim9execute.c2
-rw-r--r--src/vim9expr.c8
6 files changed, 24 insertions, 1 deletions
diff --git a/src/errors.h b/src/errors.h
index b021f8204..b8e941979 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3249,3 +3249,7 @@ EXTERN char e_cannot_create_vim9_script_variable_in_function_str[]
#endif
EXTERN char e_cannot_use_s_backslash_in_vim9_script[]
INIT(= N_("E1270: Cannot use :s\\/sub/ in Vim9 script"));
+#ifdef FEAT_EVAL
+EXTERN char e_compiling_closure_without_context_str[]
+ INIT(= N_("E1271: compiling closure without context: %s"));
+#endif
diff --git a/src/proto/vim9execute.pro b/src/proto/vim9execute.pro
index 6f42fc865..bd6709291 100644
--- a/src/proto/vim9execute.pro
+++ b/src/proto/vim9execute.pro
@@ -1,5 +1,6 @@
/* vim9execute.c */
void to_string_error(vartype_T vartype);
+void update_has_breakpoint(ufunc_T *ufunc);
void funcstack_check_refcount(funcstack_T *funcstack);
int set_ref_in_funcstacks(int copyID);
char_u *char_from_string(char_u *str, varnumber_T index);
diff --git a/src/version.c b/src/version.c
index d9752fd10..9e5e142fd 100644
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 4573,
+/**/
4572,
/**/
4571,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 696301f0f..d8119c566 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -913,6 +913,7 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
}
}
+ update_has_breakpoint(ufunc);
compile_type = COMPILE_TYPE(ufunc);
#ifdef FEAT_PROFILE
// If the outer function is profiled, also compile the nested function for
@@ -2579,6 +2580,13 @@ compile_def_function(
new_def_function = TRUE;
}
+ if ((ufunc->uf_flags & FC_CLOSURE) && outer_cctx == NULL)
+ {
+ semsg(_(e_compiling_closure_without_context_str),
+ printable_func_name(ufunc));
+ return FAIL;
+ }
+
ufunc->uf_def_status = UF_COMPILING;
CLEAR_FIELD(cctx);
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 2cf7e46ed..681847a79 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -152,7 +152,7 @@ exe_newlist(int count, ectx_T *ectx)
* If debug_tick changed check if "ufunc" has a breakpoint and update
* "uf_has_breakpoint".
*/
- static void
+ void
update_has_breakpoint(ufunc_T *ufunc)
{
if (ufunc->uf_debug_tick != debug_tick)
diff --git a/src/vim9expr.c b/src/vim9expr.c
index 19cd55d3c..e2e4f8e6a 100644
--- a/src/vim9expr.c
+++ b/src/vim9expr.c
@@ -1007,6 +1007,14 @@ compile_lambda(char_u **arg, cctx_T *cctx)
)
compile_def_function(ufunc, FALSE, CT_NONE, cctx);
+ // if the outer function is not compiled for debugging, this one might be
+ if (cctx->ctx_compile_type != CT_DEBUG)
+ {
+ update_has_breakpoint(ufunc);
+ if (COMPILE_TYPE(ufunc) == CT_DEBUG)
+ compile_def_function(ufunc, FALSE, CT_DEBUG, cctx);
+ }
+
// The last entry in evalarg.eval_tofree_ga is a copy of the last line and
// "*arg" may point into it. Point into the original line to avoid a
// dangling pointer.