]> granicus.if.org Git - vim/commitdiff
patch 7.4.1640 v7.4.1640
authorBram Moolenaar <Bram@vim.org>
Wed, 23 Mar 2016 19:55:42 +0000 (20:55 +0100)
committerBram Moolenaar <Bram@vim.org>
Wed, 23 Mar 2016 19:55:42 +0000 (20:55 +0100)
Problem:    Crash when an autocommand changes a quickfix list. (Dominique)
Solution:   Check wether an entry is still valid. (Yegappan Lakshmanan,
            Hirohito Higashi)

runtime/doc/quickfix.txt
src/quickfix.c
src/testdir/test_quickfix.vim
src/version.c

index 0ca314db1a5aee75eb1cd6dbdd73ba6cec47dea5..a4c120863ce56a5ea7892e87b3520bb6b00f00ad 100644 (file)
@@ -1,4 +1,4 @@
-*quickfix.txt*  For Vim version 7.4.  Last change: 2016 Mar 19
+*quickfix.txt*  For Vim version 7.4.  Last change: 2016 Mar 23
 
 
                  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -60,6 +60,10 @@ command with 'l'.
 If the current window was closed by an |autocommand| while processing a
 location list command, it will be aborted.
 
+                                                       *E925* *E926*
+If the current quickfix or location list was changed by an |autocommand| while
+processing a quickfix or location list command, it will be aborted.
+
                                                        *:cc*
 :cc[!] [nr]            Display error [nr].  If [nr] is omitted, the same
                        error is displayed again.  Without [!] this doesn't
index 06e50da47db6be0d97edd27000a71f81478c06cb..a2506e1a32ebb8b2a9bf02b626d6132dcd103a76 100644 (file)
@@ -1412,6 +1412,33 @@ qf_guess_filepath(char_u *filename)
 
 }
 
+/*
+ * When loading a file from the quickfix, the auto commands may modify it.
+ * This may invalidate the current quickfix entry.  This function checks
+ * whether a entry is still present in the quickfix.
+ * Similar to location list.
+ */
+    static int
+is_qf_entry_present(qf_info_T *qi, qfline_T *qf_ptr)
+{
+    qf_list_T  *qfl;
+    qfline_T   *qfp;
+    int                i;
+
+    qfl = &qi->qf_lists[qi->qf_curlist];
+
+    /* Search for the entry in the current list */
+    for (i = 0, qfp = qfl->qf_start; i < qfl->qf_count;
+           ++i, qfp = qfp->qf_next)
+       if (qfp == qf_ptr)
+           break;
+
+    if (i == qfl->qf_count) /* Entry is not found */
+       return FALSE;
+
+    return TRUE;
+}
+
 /*
  * jump to a quickfix line
  * if dir == FORWARD go "errornr" valid entries forward
@@ -1794,18 +1821,34 @@ win_found:
        }
        else
        {
+           int old_qf_curlist = qi->qf_curlist;
+           int is_abort = FALSE;
+
            ok = buflist_getfile(qf_ptr->qf_fnum,
                            (linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
            if (qi != &ql_info && !win_valid(oldwin))
            {
                EMSG(_("E924: Current window was closed"));
+               is_abort = TRUE;
+               opened_window = FALSE;
+           }
+           else if (old_qf_curlist != qi->qf_curlist
+                   || !is_qf_entry_present(qi, qf_ptr))
+           {
+               if (qi == &ql_info)
+                   EMSG(_("E925: Current quickfix was changed"));
+               else
+                   EMSG(_("E926: Current location list was changed"));
+               is_abort = TRUE;
+           }
+
+           if (is_abort)
+           {
                ok = FALSE;
                qi = NULL;
                qf_ptr = NULL;
-               opened_window = FALSE;
            }
        }
-
     }
 
     if (ok == OK)
index 07c465d8d3896723a9ec3e81a2f803a4d01552ae..667ece4e677bbe0a234d88047990ae90363467d6 100644 (file)
@@ -504,7 +504,7 @@ function Test_locationlist_curwin_was_closed()
       autocmd BufReadCmd t call R(expand("<amatch>"))
     augroup END
 
-    function R(n)
+    function! R(n)
       quit
     endfunc
 
@@ -637,3 +637,45 @@ function! Test_efm1()
     call delete('Xerrorfile2')
     call delete('Xtestfile')
 endfunction
+
+function XquickfixChangedByAutocmd(cchar)
+  let Xolder = a:cchar . 'older'
+  let Xgetexpr = a:cchar . 'getexpr'
+  let Xrewind = a:cchar . 'rewind'
+  if a:cchar == 'c'
+    let Xsetlist = 'setqflist('
+    let ErrorNr = 'E925'
+    function! ReadFunc()
+      colder
+      cgetexpr []
+    endfunc
+  else
+    let Xsetlist = 'setloclist(0,'
+    let ErrorNr = 'E926'
+    function! ReadFunc()
+      lolder
+      lgetexpr []
+    endfunc
+  endif
+
+  augroup testgroup
+    au!
+    autocmd BufReadCmd t call ReadFunc()
+  augroup END
+
+  bwipe!
+  let words = [ "a", "b" ]
+  let qflist = []
+  for word in words
+    call add(qflist, {'filename': 't'})
+    exec "call " . Xsetlist . "qflist, '')"
+  endfor
+  exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')"
+
+  augroup! testgroup
+endfunc
+
+function Test_quickfix_was_changed_by_autocmd()
+  call XquickfixChangedByAutocmd('c')
+  call XquickfixChangedByAutocmd('l')
+endfunction
index 6fffeeb7617a39d39c7518ef6c4e552743819562..c9c550a490b9f101ef16e775f8a9859134399c68 100644 (file)
@@ -748,6 +748,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1640,
 /**/
     1639,
 /**/