]> granicus.if.org Git - vim/commitdiff
patch 8.2.3395: Vim9: expression breakpoint not checked in :def function v8.2.3395
authorBram Moolenaar <Bram@vim.org>
Thu, 2 Sep 2021 16:49:06 +0000 (18:49 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 2 Sep 2021 16:49:06 +0000 (18:49 +0200)
Problem:    Vim9: expression breakpoint not checked in :def function.
Solution:   Always compile a function for debugging if there is an expression
            breakpoint. (closes #8803)

src/debugger.c
src/proto/debugger.pro
src/proto/vim9execute.pro
src/testdir/test_debugger.vim
src/version.c
src/vim.h
src/vim9.h
src/vim9execute.c

index 1b01998759cb643120f4855bc9673672d877906e..1e28d66f6160fe75df301493b23695fa3d44bff3 100644 (file)
@@ -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();
     }
 }
 
index e018622394e3a8cbc632b7352dcd6142e62ba769..d80ecf5019598f75a3e0ef09a7abba1727512807 100644 (file)
@@ -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);
index 8b4b6eaafcdd32456e27dbc7c321358f0bfde69c..ef22af75b490b72b2c23798ea74199d1d1a4aced 100644 (file)
@@ -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);
index 2937d54604b8d41e659ec35d966a0589dfff61a6..85ab6ea3936c4eac4dd094260a5fa57451991c4e 100644 (file)
@@ -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
index 8811ee1518c7699ecc98ffd09e1943d2dc758891..435affea7a7005105e24b61a6e86c9cb85f0e5c9 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3395,
 /**/
     3394,
 /**/
index b9105b5d1d04b4dab0590daa11ced97859a04be8..cb769e2a4bf5344c3f09303a3ee2ed6ea6fd3276 100644 (file)
--- 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
 
 /*
index 67c9a710a58b615198e8b8129da77ce197da18da..0fc1ab5d4cf67f85c3214ea463884781fd2b139a 100644 (file)
@@ -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
index 4562a08bf4e130a49cdd5bced5814dd86b433873..fdca9771450e692c79388ae1027789d8cee724a7 100644 (file)
@@ -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