Reported by: storm <at> cua.dk (Kim F. Storm)
Date: Tue, 19 Jun 2012 20:50:02 UTC
Severity: normal
Found in versions 24.0.90, 24.1
Done: Alan Mackenzie <acm <at> muc.de>
Bug is archived. No further changes may be made.
Message #101 received at 11749 <at> debbugs.gnu.org (full text, mbox):
From: Alan Mackenzie <acm <at> muc.de> To: Kim Storm <storm <at> cua.dk>, Michael Welsh Duggan <mwd <at> cert.org> Cc: "11749 <at> debbugs.gnu.org" <11749 <at> debbugs.gnu.org> Subject: Re: bug#11749: Acknowledgement (24.1; C-mode indentation gives wrong-type-argument error.) Date: Sun, 4 Nov 2012 20:39:12 +0000
Kim, could you please try out this patch on your C++ files, and let me know if the main problem has been resolved. Michael, there was a rather crass bug in last week's patch. Sorry. It's fixed now, below. M-x c-toggle-parse-state-debug has been enhanced to display messages when the state-cache is intrinsically invalid. It also now gives a message when you {en,dis}able it. Would you try out this patch now, please. Thanks to you both! On Sun, Oct 28, 2012 at 11:36:10AM +0000, Alan Mackenzie wrote: > On Thu, Oct 25, 2012 at 09:41:11AM -0400, Michael Welsh Duggan wrote: > > A new recipe. This is a strange one. I hope it works for you as well. > > emacs -Q > > M-x tool-bar-mode > > resize the frame to be height 56 (according to the window manager) > > Load the included file > > M-x c-toggle-parse-state-debug > > C-s FIXME C-s > > Move cursor to the "o" on the next line (1175). > > Type: > > PyTYPE( > > C-f > > ) > > I get errors at the first open paren, and the close paren. Resizing the > > fame is important! I think it's due to caching that happens during font > > locking. > Thanks for this one. > The cause was the cache invalidation function being called from > after-change-functions. The newly inserted parens were fouling up the > invalidation algorithm. :-( The solution is to call that function from > before-change-functions instead. diff -r ac6584d14c06 cc-engine.el --- a/cc-engine.el Sun Sep 09 11:15:13 2012 +0000 +++ b/cc-engine.el Sun Nov 04 20:24:06 2012 +0000 @@ -2560,8 +2560,11 @@ start-point cache-pos))) ;; Might we be better off starting from the top level, two defuns back, - ;; instead? - (when (> how-far c-state-cache-too-far) + ;; instead? This heuristic no longer works well in C++, where + ;; declarations inside namespace brace blocks are frequently placed at + ;; column zero. + (when (and (not (c-major-mode-is 'c++-mode)) + (> how-far c-state-cache-too-far)) (setq BOD-pos (c-get-fallback-scan-pos here)) ; somewhat EXPENSIVE!!! (if (< (- here BOD-pos) how-far) (setq strategy 'BOD @@ -2648,17 +2651,20 @@ ;; If we're essentially repeating a fruitless search, just give up. (unless (and c-state-brace-pair-desert (eq cache-pos (car c-state-brace-pair-desert)) + (or (null (car c-state-brace-pair-desert)) + (> from (car c-state-brace-pair-desert))) (<= from (cdr c-state-brace-pair-desert))) - ;; DESERT-LIM. Only search what we absolutely need to, + ;; DESERT-LIM. Avoid repeated searching through the cached desert. (let ((desert-lim (and c-state-brace-pair-desert (eq cache-pos (car c-state-brace-pair-desert)) + (>= from (cdr c-state-brace-pair-desert)) (cdr c-state-brace-pair-desert))) ;; CACHE-LIM. This limit will be necessary when an opening ;; paren at `cache-pos' has just had its matching close paren - ;; inserted. `cache-pos' continues to be a search bound, even - ;; though the algorithm below would skip over the new paren - ;; pair. + ;; inserted into the buffer. `cache-pos' continues to be a + ;; search bound, even though the algorithm below would skip + ;; over the new paren pair. (cache-lim (and cache-pos (< cache-pos from) cache-pos))) (narrow-to-region (cond @@ -3354,13 +3360,19 @@ (fset 'c-real-parse-state (symbol-function 'c-parse-state))) (cc-bytecomp-defun c-real-parse-state) +(defvar c-parse-state-point nil) (defvar c-parse-state-state nil) (make-variable-buffer-local 'c-parse-state-state) (defun c-record-parse-state-state () + (setq c-parse-state-point (point)) (setq c-parse-state-state (mapcar (lambda (arg) - (cons arg (symbol-value arg))) + (let ((val (symbol-value arg))) + (cons arg + (if (consp val) + (copy-tree val) + val)))) '(c-state-cache c-state-cache-good-pos c-state-nonlit-pos-cache @@ -3373,7 +3385,8 @@ c-state-point-min-lit-start c-state-min-scan-pos c-state-old-cpp-beg - c-state-old-cpp-end)))) + c-state-old-cpp-end + c-parse-state-point)))) (defun c-replay-parse-state-state () (message (concat "(setq " @@ -3383,6 +3396,16 @@ c-parse-state-state " ") ")"))) +(defun c-debug-parse-state-double-cons (state) + (let (state-car conses-not-ok) + (while state + (setq state-car (car state) + state (cdr state)) + (if (and (consp state-car) + (consp (car state))) + (setq conses-not-ok t))) + conses-not-ok)) + (defun c-debug-parse-state () (let ((here (point)) (res1 (c-real-parse-state)) res2) (let ((c-state-cache nil) @@ -3415,8 +3438,16 @@ here res1 res2) (message "Old state:") (c-replay-parse-state-state)) + + (when (c-debug-parse-state-double-cons res1) + (message "c-parse-state INVALIDITY at %s: %s" + here res1) + (message "Old state:") + (c-replay-parse-state-state)) + (c-record-parse-state-state) - res1)) + res2 ; res1 correct a cascading series of errors ASAP + )) (defun c-toggle-parse-state-debug (&optional arg) (interactive "P") @@ -3424,7 +3455,9 @@ (fset 'c-parse-state (symbol-function (if c-debug-parse-state 'c-debug-parse-state 'c-real-parse-state))) - (c-keep-region-active)) + (c-keep-region-active) + (message "c-debug-parse-state %sabled" + (if c-debug-parse-state "en" "dis"))) (when c-debug-parse-state (c-toggle-parse-state-debug 1)) diff -r ac6584d14c06 cc-mode.el --- a/cc-mode.el Sun Sep 09 11:15:13 2012 +0000 +++ b/cc-mode.el Sun Nov 04 20:24:06 2012 +0000 @@ -1058,7 +1058,10 @@ (mapc (lambda (fn) (funcall fn beg end)) c-get-state-before-change-functions)) - ))))) + ))) + ;; The following must be done here rather than in `c-after-change' because + ;; newly inserted parens would foul up the invalidation algorithm. + (c-invalidate-state-cache beg))) (defvar c-in-after-change-fontification nil) (make-variable-buffer-local 'c-in-after-change-fontification) @@ -1108,7 +1111,7 @@ (c-trim-found-types beg end old-len) ; maybe we don't need all of these. (c-invalidate-sws-region-after beg end) - (c-invalidate-state-cache beg) + ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'. (c-invalidate-find-decl-cache beg) (when c-recognize-<>-arglists > > -- > > Michael Welsh Duggan > > (mwd <at> cert.org) -- Alan Mackenzie (Nuremberg, Germany).
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.