To: vim_dev@googlegroups.com Subject: Patch 8.2.3395 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.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) Files: src/vim9execute.c, src/proto/vim9execute.pro, src/debugger.c, src/proto/debugger.pro, src/vim.h, src/vim9.h, src/testdir/test_debugger.vim *** ../vim-8.2.3394/src/vim9execute.c 2021-08-14 14:00:58.229863901 +0200 --- src/vim9execute.c 2021-09-02 18:01:48.496365654 +0200 *************** *** 1483,1488 **** --- 1483,1498 ---- 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,1504 **** { linenr_T breakpoint; ! if (!ufunc->uf_has_breakpoint) return; // check for the next breakpoint if needed --- 1508,1514 ---- { linenr_T breakpoint; ! if (!may_break_in_function(ufunc)) return; // check for the next breakpoint if needed *** ../vim-8.2.3394/src/proto/vim9execute.pro 2021-06-14 20:40:33.590233925 +0200 --- src/proto/vim9execute.pro 2021-09-02 18:03:28.456128943 +0200 *************** *** 5,10 **** --- 5,11 ---- 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); *** ../vim-8.2.3394/src/debugger.c 2021-07-20 21:07:32.960058864 +0200 --- src/debugger.c 2021-09-02 18:11:32.586945735 +0200 *************** *** 518,523 **** --- 518,524 ---- #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,696 **** --- 692,699 ---- // DBG_EXPR DEBUGGY(gap, gap->ga_len++).dbg_nr = ++last_breakp; ++debug_tick; + if (gap == &dbg_breakp) + has_expr_breakpoint = TRUE; } } } *************** *** 707,712 **** --- 710,738 ---- 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,804 **** --- 825,832 ---- // If all breakpoints were removed clear the array. if (gap->ga_len == 0) ga_clear(gap); + if (gap == &dbg_breakp) + update_has_expr_breakpoint(); } } *** ../vim-8.2.3394/src/proto/debugger.pro 2019-12-12 12:55:17.000000000 +0100 --- src/proto/debugger.pro 2021-09-02 18:03:22.744142564 +0200 *************** *** 6,11 **** --- 6,12 ---- 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); *** ../vim-8.2.3394/src/vim.h 2021-08-02 18:07:15.186473836 +0200 --- src/vim.h 2021-09-02 18:06:25.067703096 +0200 *************** *** 1808,1816 **** // 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) #else ! # define COMPILE_TYPE(ufunc) debug_break_level > 0 || ufunc->uf_has_breakpoint ? CT_DEBUG : CT_NONE #endif /* --- 1808,1823 ---- // Keep in sync with INSTRUCTIONS(). #ifdef FEAT_PROFILE ! # 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 \ ! || may_break_in_function(ufunc) \ ! ? CT_DEBUG \ ! : CT_NONE #endif /* *** ../vim-8.2.3394/src/vim9.h 2021-08-13 19:40:47.417028286 +0200 --- src/vim9.h 2021-09-02 18:07:07.575599458 +0200 *************** *** 513,526 **** // Keep in sync with COMPILE_TYPE() #ifdef FEAT_PROFILE # define INSTRUCTIONS(dfunc) \ ! (debug_break_level > 0 || dfunc->df_ufunc->uf_has_breakpoint \ ? (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 \ ? (dfunc)->df_instr_debug \ : (dfunc)->df_instr) #endif --- 513,526 ---- // Keep in sync with COMPILE_TYPE() #ifdef FEAT_PROFILE # define INSTRUCTIONS(dfunc) \ ! (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 || may_break_in_function(dfunc->df_ufunc) \ ? (dfunc)->df_instr_debug \ : (dfunc)->df_instr) #endif *** ../vim-8.2.3394/src/testdir/test_debugger.vim 2021-07-10 20:43:56.214042001 +0200 --- src/testdir/test_debugger.vim 2021-09-02 18:44:05.141713998 +0200 *************** *** 932,937 **** --- 932,958 ---- 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 *** ../vim-8.2.3394/src/version.c 2021-09-01 16:01:29.601137676 +0200 --- src/version.c 2021-09-02 18:44:27.009656423 +0200 *************** *** 757,758 **** --- 757,760 ---- { /* Add new patch number below this line */ + /**/ + 3395, /**/ -- At some point in the project somebody will start whining about the need to determine the project "requirements". This involves interviewing people who don't know what they want but, curiously, know exactly when they need it. (Scott Adams - The Dilbert principle) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// \\\ \\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///