summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-09-02 18:49:06 +0200
committerBram Moolenaar <Bram@vim.org>2021-09-02 18:49:06 +0200
commit26a4484da20039b61f18d3565a4b4339c4d1f7e3 (patch)
tree36b3d0dada37e17686da0627af5cda5848658052
parent04626c243c47af91c2580eaf23e12286180e0e81 (diff)
patch 8.2.3395: Vim9: expression breakpoint not checked in :def functionv8.2.3395
Problem: Vim9: expression breakpoint not checked in :def function. Solution: Always compile a function for debugging if there is an expression breakpoint. (closes #8803)
-rw-r--r--src/debugger.c28
-rw-r--r--src/proto/debugger.pro1
-rw-r--r--src/proto/vim9execute.pro1
-rw-r--r--src/testdir/test_debugger.vim21
-rw-r--r--src/version.c2
-rw-r--r--src/vim.h11
-rw-r--r--src/vim9.h4
-rw-r--r--src/vim9execute.c12
8 files changed, 75 insertions, 5 deletions
diff --git a/src/debugger.c b/src/debugger.c
index 1b01998759..1e28d66f61 100644
--- a/src/debugger.c
+++ b/src/debugger.c
@@ -518,6 +518,7 @@ static garray_T dbg_breakp = {0, 0, sizeof(struct debuggy), 4, NULL};
#define BREAKP(idx) (((struct debuggy *)dbg_breakp.ga_data)[idx])
#define DEBUGGY(gap, idx) (((struct debuggy *)gap->ga_data)[idx])
static int last_breakp = 0; // nr of last defined breakpoint
+static int has_expr_breakpoint = FALSE;
#ifdef FEAT_PROFILE
// Profiling uses file and func names similar to breakpoints.
@@ -691,6 +692,8 @@ ex_breakadd(exarg_T *eap)
// DBG_EXPR
DEBUGGY(gap, gap->ga_len++).dbg_nr = ++last_breakp;
++debug_tick;
+ if (gap == &dbg_breakp)
+ has_expr_breakpoint = TRUE;
}
}
}
@@ -707,6 +710,29 @@ ex_debuggreedy(exarg_T *eap)
debug_greedy = FALSE;
}
+ static void
+update_has_expr_breakpoint()
+{
+ int i;
+
+ has_expr_breakpoint = FALSE;
+ for (i = 0; i < dbg_breakp.ga_len; ++i)
+ if (BREAKP(i).dbg_type == DBG_EXPR)
+ {
+ has_expr_breakpoint = TRUE;
+ break;
+ }
+}
+
+/*
+ * Return TRUE if there is any expression breakpoint.
+ */
+ int
+debug_has_expr_breakpoint()
+{
+ return has_expr_breakpoint;
+}
+
/*
* ":breakdel" and ":profdel".
*/
@@ -799,6 +825,8 @@ ex_breakdel(exarg_T *eap)
// If all breakpoints were removed clear the array.
if (gap->ga_len == 0)
ga_clear(gap);
+ if (gap == &dbg_breakp)
+ update_has_expr_breakpoint();
}
}
diff --git a/src/proto/debugger.pro b/src/proto/debugger.pro
index e018622394..d80ecf5019 100644
--- a/src/proto/debugger.pro
+++ b/src/proto/debugger.pro
@@ -6,6 +6,7 @@ void dbg_check_breakpoint(exarg_T *eap);
int dbg_check_skipped(exarg_T *eap);
void ex_breakadd(exarg_T *eap);
void ex_debuggreedy(exarg_T *eap);
+int debug_has_expr_breakpoint(void);
void ex_breakdel(exarg_T *eap);
void ex_breaklist(exarg_T *eap);
linenr_T dbg_find_breakpoint(int file, char_u *fname, linenr_T after);
diff --git a/src/proto/vim9execute.pro b/src/proto/vim9execute.pro
index 8b4b6eaafc..ef22af75b4 100644
--- a/src/proto/vim9execute.pro
+++ b/src/proto/vim9execute.pro
@@ -5,6 +5,7 @@ char_u *char_from_string(char_u *str, varnumber_T index);
char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive);
int fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx);
typval_T *lookup_debug_var(char_u *name);
+int may_break_in_function(ufunc_T *ufunc);
int exe_typval_instr(typval_T *tv, typval_T *rettv);
char_u *exe_substitute_instr(void);
int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, partial_T *partial, typval_T *rettv);
diff --git a/src/testdir/test_debugger.vim b/src/testdir/test_debugger.vim
index 2937d54604..85ab6ea393 100644
--- a/src/testdir/test_debugger.vim
+++ b/src/testdir/test_debugger.vim
@@ -932,6 +932,27 @@ func Test_Backtrace_DefFunction()
call delete('Xtest2.vim')
endfunc
+func Test_DefFunction_expr()
+ CheckCWD
+ let file3 =<< trim END
+ vim9script
+ g:someVar = "foo"
+ def g:ChangeVar()
+ g:someVar = "bar"
+ echo "changed"
+ enddef
+ defcompile
+ END
+ call writefile(file3, 'Xtest3.vim')
+ let buf = RunVimInTerminal('-S Xtest3.vim', {})
+
+ call RunDbgCmd(buf, ':breakadd expr g:someVar')
+ call RunDbgCmd(buf, ':call g:ChangeVar()', ['Oldval = "''foo''"', 'Newval = "''bar''"', 'function ChangeVar', 'line 2: echo "changed"'])
+
+ call StopVimInTerminal(buf)
+ call delete('Xtest3.vim')
+endfunc
+
func Test_debug_def_and_legacy_function()
CheckCWD
let file =<< trim END
diff --git a/src/version.c b/src/version.c
index 8811ee1518..435affea7a 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 */
/**/
+ 3395,
+/**/
3394,
/**/
3393,
diff --git a/src/vim.h b/src/vim.h
index b9105b5d1d..cb769e2a4b 100644
--- a/src/vim.h
+++ b/src/vim.h
@@ -1808,9 +1808,16 @@ typedef enum {
// Keep in sync with INSTRUCTIONS().
#ifdef FEAT_PROFILE
-# define COMPILE_TYPE(ufunc) (debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : do_profiling == PROF_YES && (ufunc)->uf_profiling ? CT_PROFILE : CT_NONE)
+# define COMPILE_TYPE(ufunc) (debug_break_level > 0 \
+ || may_break_in_function(ufunc) \
+ ? CT_DEBUG \
+ : do_profiling == PROF_YES && (ufunc)->uf_profiling \
+ ? CT_PROFILE : CT_NONE)
#else
-# define COMPILE_TYPE(ufunc) debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : CT_NONE
+# define COMPILE_TYPE(ufunc) debug_break_level > 0 \
+ || may_break_in_function(ufunc) \
+ ? CT_DEBUG \
+ : CT_NONE
#endif
/*
diff --git a/src/vim9.h b/src/vim9.h
index 67c9a710a5..0fc1ab5d4c 100644
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -513,14 +513,14 @@ extern garray_T def_functions;
// Keep in sync with COMPILE_TYPE()
#ifdef FEAT_PROFILE
# define INSTRUCTIONS(dfunc) \
- (debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \
+ (debug_break_level > 0 || may_break_in_function(dfunc->df_ufunc) \
? (dfunc)->df_instr_debug \
: ((do_profiling == PROF_YES && (dfunc->df_ufunc)->uf_profiling) \
? (dfunc)->df_instr_prof \
: (dfunc)->df_instr))
#else
# define INSTRUCTIONS(dfunc) \
- (debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \
+ (debug_break_level > 0 || may_break_in_function(dfunc->df_ufunc) \
? (dfunc)->df_instr_debug \
: (dfunc)->df_instr)
#endif
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 4562a08bf4..fdca977145 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1483,6 +1483,16 @@ lookup_debug_var(char_u *name)
return NULL;
}
+/*
+ * Return TRUE if there might be a breakpoint in "ufunc", which is when a
+ * breakpoint was set in that function or when there is any expression.
+ */
+ int
+may_break_in_function(ufunc_T *ufunc)
+{
+ return ufunc->uf_has_breakpoint || debug_has_expr_breakpoint();
+}
+
static void
handle_debug(isn_T *iptr, ectx_T *ectx)
{
@@ -1498,7 +1508,7 @@ handle_debug(isn_T *iptr, ectx_T *ectx)
{
linenr_T breakpoint;
- if (!ufunc->uf_has_breakpoint)
+ if (!may_break_in_function(ufunc))
return;
// check for the next breakpoint if needed