GNU bug report logs - #11749
24.1; C-mode indentation gives wrong-type-argument error.

Previous Next

Packages: emacs, cc-mode;

Reported by: storm <at> cua.dk (Kim F. Storm)

Date: Tue, 19 Jun 2012 20:50:02 UTC

Severity: normal

Merged with 9957, 13385

Found in versions 24.0.90, 24.1

Done: Alan Mackenzie <acm <at> muc.de>

Bug is archived. No further changes may be made.

Full log


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).




This bug report was last modified 12 years and 107 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.