GNU bug report logs - #16910
24.3; c++ mode: autoindent stops working

Previous Next

Packages: cc-mode, emacs;

Reported by: admin <at> practicealgebra.net

Date: Fri, 28 Feb 2014 17:43:02 UTC

Severity: normal

Tags: moreinfo

Found in version 24.3

Fixed in version 24.4

Done: Glenn Morris <rgm <at> gnu.org>

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: Alan Mackenzie <acm <at> muc.de>
To: admin <at> practicealgebra.net
Cc: 16910 <at> debbugs.gnu.org
Subject: bug#16910: 24.3; c++ mode: autoindent stops working
Date: Sun, 2 Mar 2014 14:38:00 +0000
Hi, Andrew.

> Hi-

> While editing files in c++ mode, autoindent sometimes stops working
> after a while. Saving, making a trivial change and then immediately
> reverting sometimes solves the problem, but usually not. I'm afraid I
> can't give a recipe, since I myself don't understand when it happens; it
> seems unpredictable. But (some of) the error messages from emacs (which
> appear in the echo area) are below.

>              -Andrew Warshall


> In GNU Emacs 24.3.1 (i686-pc-linux-gnu, GTK+ Version 3.10.7)
> of 2014-02-24 on warshall

[ .... ]

> Recent messages:
> c-parse-state inconsistency at 1692: using cache: ((1415 . 1506) 220), from scratch: nil
> Old state:
> (setq c-state-cache '((1415 . 1506) 220)  c-state-cache-good-pos 1636  c-state-nonlit-pos-cache '(3001)  c-state-nonlit-pos-cache-limit 1  c-state-semi-nonlit-pos-cache nil  c-state-semi-nonlit-pos-cache-limit 1  c-state-brace-pair-desert '(220 . 322)  c-state-point-min 1  c-state-point-min-lit-type nil  c-state-point-min-lit-start nil  c-state-min-scan-pos 1  c-state-old-cpp-beg nil  c-state-old-cpp-end nil  c-parse-state-point 1764)
> c-parse-state inconsistency at 1417: using cache: (1415 (1001 . 1156) 220), from scratch: nil
> Old state:
> (setq c-state-cache '((1415 . 1506) 220)  c-state-cache-good-pos 1636  c-state-nonlit-pos-cache '(3001)  c-state-nonlit-pos-cache-limit 1  c-state-semi-nonlit-pos-cache nil  c-state-semi-nonlit-pos-cache-limit 1  c-state-brace-pair-desert '(220 . 322)  c-state-point-min 1  c-state-point-min-lit-type nil  c-state-point-min-lit-start nil  c-state-min-scan-pos 1  c-state-old-cpp-beg nil  c-state-old-cpp-end nil  c-parse-state-point 1692)
> c-parse-state inconsistency at 1417: using cache: (1415 (1001 . 1156) 220), from scratch: nil
> Old state:
> (setq c-state-cache '(1415 (1001 . 1156) 220)  c-state-cache-good-pos 1416  c-state-nonlit-pos-cache '(3001)  c-state-nonlit-pos-cache-limit 1  c-state-semi-nonlit-pos-cache nil  c-state-semi-nonlit-pos-cache-limit 1  c-state-brace-pair-desert '(220 . 322)  c-state-point-min 1  c-state-point-min-lit-type nil  c-state-point-min-lit-start nil  c-state-min-scan-pos 1  c-state-old-cpp-beg nil  c-state-old-cpp-end nil  c-parse-state-point 1417)

These debug messages originate from a particular CC Mode function
`c-parse-state' which crawls through the buffer recording the position of
certain near and enclosing braces/brackets/parentheses.  Somewhere, e.g.
in your .emacs, you presumably have toggled `c-toggle-parse-state-debug'
to get this output.

`c-parse-state' in Emacs 24.3 was buggy.  The latest version, which will
be getting released along with Emacs 24.4, is less buggy.  I suggest you
apply the following patch to ..../emacs-24.3/lisp/progmodes/cc-engine.el
to bring that file up to the latest state, which should hopefully make CC
Mode indentation run more smoothly, or even correctly.  After applying
the patch, recompile cc-engine.el with either M-x byte-compile-file, or
(from the command line)

    emacs -Q -batch -f batch-byte-compile cc-engine.el

.


--- cc-engine.el	2013-04-26 12:35:20.000000000 +0000
+++ cc-engine.el.new	2014-02-02 16:16:42.000000000 +0000
@@ -2180,32 +2187,46 @@
 ;; reduced by buffer changes, and increased by invocations of
 ;; `c-state-literal-at'.  FIXME!!!
 
-(defsubst c-state-pp-to-literal (from to)
+(defsubst c-state-pp-to-literal (from to &optional not-in-delimiter)
   ;; Do a parse-partial-sexp from FROM to TO, returning either
   ;;     (STATE TYPE (BEG . END))     if TO is in a literal; or
   ;;     (STATE)                      otherwise,
   ;; where STATE is the parsing state at TO, TYPE is the type of the literal
   ;; (one of 'c, 'c++, 'string) and (BEG . END) is the boundaries of the literal.
   ;;
+  ;; Unless NOT-IN-DELIMITER is non-nil, when TO is inside a two-character
+  ;; comment opener, this is recognized as being in a comment literal.
+  ;;
   ;; Only elements 3 (in a string), 4 (in a comment), 5 (following a quote),
   ;; 7 (comment type) and 8 (start of comment/string) (and possibly 9) of
   ;; STATE are valid.
   (save-excursion
     (let ((s (parse-partial-sexp from to))
-	  ty)
-      (when (or (nth 3 s) (nth 4 s))	; in a string or comment
+	  ty co-st)
+      (cond
+       ((or (nth 3 s) (nth 4 s))	; in a string or comment
 	(setq ty (cond
 		  ((nth 3 s) 'string)
-		  ((eq (nth 7 s) t) 'c++)
+		  ((nth 7 s) 'c++)
 		  (t 'c)))
 	(parse-partial-sexp (point) (point-max)
-			    nil			 ; TARGETDEPTH
-			    nil			 ; STOPBEFORE
-			    s			 ; OLDSTATE
-			    'syntax-table))	 ; stop at end of literal
-      (if ty
-	  `(,s ,ty (,(nth 8 s) . ,(point)))
-	`(,s)))))
+			    nil		   ; TARGETDEPTH
+			    nil		   ; STOPBEFORE
+			    s		   ; OLDSTATE
+			    'syntax-table) ; stop at end of literal
+	`(,s ,ty (,(nth 8 s) . ,(point))))
+
+       ((and (not not-in-delimiter)	; inside a comment starter
+	     (not (bobp))
+	     (progn (backward-char)
+		    (and (not (looking-at "\\s!"))
+			 (looking-at c-comment-start-regexp))))
+	(setq ty (if (looking-at c-block-comment-start-regexp) 'c 'c++)
+	      co-st (point))
+	(forward-comment 1)
+	`(,s ,ty (,co-st . ,(point))))
+
+       (t `(,s))))))
 
 (defun c-state-safe-place (here)
   ;; Return a buffer position before HERE which is "safe", i.e. outside any
@@ -2280,25 +2301,25 @@
 	(while (and c (> (car c) c-state-semi-nonlit-pos-cache-limit))
 	  (setq c (cdr c)))
 	(setq c-state-semi-nonlit-pos-cache c)
-	
+
 	(while (and c (> (car c) here))
 	  (setq high-pos (car c))
 	  (setq c (cdr c)))
 	(setq pos (or (car c) (point-min)))
-	
+
 	(unless high-pos
 	  (while
 	      ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
 	      (and
 	       (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
-	       
+
 	       ;; Test for being in a literal.  If so, go to after it.
 	       (progn
 		 (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
 		 (or (null lit)
 		     (prog1 (<= (cdr lit) here)
 		       (setq npos (cdr lit))))))
-	       
+
 	    (setq pos npos)
 	    (setq c-state-semi-nonlit-pos-cache
 		  (cons pos c-state-semi-nonlit-pos-cache))))
@@ -2532,8 +2553,11 @@
   ;; The return value is a list, one of the following:
   ;;
   ;; o - ('forward START-POINT) - scan forward from START-POINT,
-  ;;	 which is not less than the highest position in `c-state-cache' below here.
+  ;;	 which is not less than the highest position in `c-state-cache' below HERE,
+  ;;     which is after GOOD-POS.
   ;; o - ('backward nil) - scan backwards (from HERE).
+  ;; o - ('back-and-forward START-POINT) - like 'forward, but when HERE is earlier
+  ;;     than GOOD-POS.
   ;; o - ('IN-LIT nil) - point is inside the literal containing point-min.
   (let ((cache-pos (c-get-cache-scan-pos here))	; highest position below HERE in cache (or 1)
 	strategy	    ; 'forward, 'backward, or 'IN-LIT.
@@ -2548,9 +2572,9 @@
      ((< (- good-pos here) (- here cache-pos)) ; FIXME!!! ; apply some sort of weighting.
       (setq strategy 'backward))
      (t
-      (setq strategy 'forward
+      (setq strategy 'back-and-forward
 	    start-point cache-pos)))
-    (list strategy (and (eq strategy 'forward) start-point))))
+    (list strategy start-point)))
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2606,11 +2630,11 @@
   ;; OLD:   {                       (.)    {...........}
   ;;                                       ^             ^
   ;;                                     FROM          HERE
-  ;;                                     
+  ;;
   ;; NEW:   {             {....}    (.)    {.........
   ;;                         ^           ^           ^
   ;;                LOWER BRACE PAIR   HERE   or   HERE
-  ;;                                       
+  ;;
   ;; This routine should be fast.  Since it can get called a LOT, we maintain
   ;; `c-state-brace-pair-desert', a small cache of "failures", such that we
   ;; reduce the time wasted in repeated fruitless searches in brace deserts.
@@ -2822,9 +2846,10 @@
 
 (defun c-remove-stale-state-cache (start-point here pps-point)
   ;; Remove stale entries from the `c-cache-state', i.e. those which will
-  ;; not be in it when it is amended for position HERE.  Additionally, the
-  ;; "outermost" open-brace entry before HERE will be converted to a cons if
-  ;; the matching close-brace is scanned.
+  ;; not be in it when it is amended for position HERE.  This may involve
+  ;; replacing a CONS element for a brace pair containing HERE with its car.
+  ;; Additionally, the "outermost" open-brace entry before HERE will be
+  ;; converted to a cons if the matching close-brace is below HERE.
   ;;
   ;; START-POINT is a "maximal" "safe position" - there must be no open
   ;; parens/braces/brackets between START-POINT and HERE.
@@ -2835,7 +2860,7 @@
   ;; adjust it to get outside a string/comment.	 (Sorry about this!  The code
   ;; needs to be FAST).
   ;;
-  ;; Return a list (GOOD-POS SCAN-BACK-POS PPS-STATE), where
+  ;; Return a list (GOOD-POS SCAN-BACK-POS CONS-SEPARATED PPS-STATE), where
   ;; o - GOOD-POS is a position where the new value `c-state-cache' is known
   ;;   to be good (we aim for this to be as high as possible);
   ;; o - SCAN-BACK-POS, if not nil, indicates there may be a brace pair
@@ -2843,6 +2868,9 @@
   ;;   position to scan backwards from.  It is the position of the "{" of the
   ;;   last element to be removed from `c-state-cache', when that elt is a
   ;;   cons, otherwise nil.
+  ;; o - CONS-SEPARATED is t when a cons element in `c-state-cache' has been
+  ;;   replaced by its car because HERE lies inside the brace pair represented
+  ;;   by the cons.
   ;; o - PPS-STATE is the parse-partial-sexp state at PPS-POINT.
   (save-excursion
     (save-restriction
@@ -2870,6 +2898,7 @@
 	     pos
 	     upper-lim	   ; ,beyond which `c-state-cache' entries are removed
 	     scan-back-pos
+	     cons-separated
 	     pair-beg pps-point-state target-depth)
 
 	;; Remove entries beyond HERE.  Also remove any entries inside
@@ -2891,7 +2920,8 @@
 		   (consp (car c-state-cache))
 		   (> (cdar c-state-cache) upper-lim))
 	  (setcar c-state-cache (caar c-state-cache))
-	  (setq scan-back-pos (car c-state-cache)))
+	  (setq scan-back-pos (car c-state-cache)
+		cons-separated t))
 
 	;; The next loop jumps forward out of a nested level of parens each
 	;; time round; the corresponding elements in `c-state-cache' are
@@ -2907,7 +2937,7 @@
 		    start-point))
 	(goto-char pos)
 	(while (and c-state-cache
-		    (or (numberp (car c-state-cache)) ; Have we a { at all? 
+		    (or (numberp (car c-state-cache)) ; Have we a { at all?
 			(cdr c-state-cache))
 		    (< (point) here))
 	  (cond
@@ -2963,7 +2993,7 @@
 	  (setq c-state-cache (cons (cons pair-beg pos)
 				    c-state-cache)))
 
-	(list pos scan-back-pos pps-state)))))
+	(list pos scan-back-pos cons-separated pps-state)))))
 
 (defun c-remove-stale-state-cache-backwards (here)
   ;; Strip stale elements of `c-state-cache' by moving backwards through the
@@ -3143,10 +3173,13 @@
   ;; This function is called from c-after-change.
 
   ;; The caches of non-literals:
-  (if (< here c-state-nonlit-pos-cache-limit)
-      (setq c-state-nonlit-pos-cache-limit here))
-  (if (< here c-state-semi-nonlit-pos-cache-limit)
-      (setq c-state-semi-nonlit-pos-cache-limit here))
+  ;; Note that we use "<=" for the possibility of the second char of a two-char
+  ;; comment opener being typed; this would invalidate any cache position at
+  ;; HERE.
+  (if (<= here c-state-nonlit-pos-cache-limit)
+      (setq c-state-nonlit-pos-cache-limit (1- here)))
+  (if (<= here c-state-semi-nonlit-pos-cache-limit)
+      (setq c-state-semi-nonlit-pos-cache-limit (1- here)))
 
   ;; `c-state-cache':
   ;; Case 1: if `here' is in a literal containing point-min, everything
@@ -3160,7 +3193,8 @@
     ;; Truncate `c-state-cache' and set `c-state-cache-good-pos' to a value
     ;; below `here'.  To maintain its consistency, we may need to insert a new
     ;; brace pair.
-    (let ((here-bol (c-point 'bol here))
+    (let (open-paren-in-column-0-is-defun-start
+	  (here-bol (c-point 'bol here))
 	  too-high-pa		  ; recorded {/(/[ next above here, or nil.
 	  dropped-cons		  ; was the last removed element a brace pair?
 	  pa)
@@ -3231,6 +3265,7 @@
   ;; This function might do hidden buffer changes.
   (let* ((here (point))
 	 (here-bopl (c-point 'bopl))
+	 open-paren-in-column-0-is-defun-start
 	 strategy	     ; 'forward, 'backward etc..
 	 ;; Candidate positions to start scanning from:
 	 cache-pos	     ; highest position below HERE already existing in
@@ -3240,6 +3275,7 @@
 		     ; are no open parens/braces between it and HERE.
 	 bopl-state
 	 res
+	 cons-separated
 	 scan-backward-pos scan-forward-p) ; used for 'backward.
     ;; If POINT-MIN has changed, adjust the cache
     (unless (= (point-min) c-state-point-min)
@@ -3252,13 +3288,15 @@
 
     ;; SCAN!
     (cond
-     ((eq strategy 'forward)
+     ((memq strategy '(forward back-and-forward))
       (setq res (c-remove-stale-state-cache start-point here here-bopl))
       (setq cache-pos (car res)
 	    scan-backward-pos (cadr res)
-	    bopl-state (car (cddr res))) ; will be nil if (< here-bopl
+	    cons-separated (car (cddr res)) 
+	    bopl-state (cadr (cddr res))) ; will be nil if (< here-bopl
 					; start-point)
-      (if scan-backward-pos
+      (if (and scan-backward-pos
+	       (or cons-separated (eq strategy 'forward))) ;scan-backward-pos
 	  (c-append-lower-brace-pair-to-state-cache scan-backward-pos here))
       (setq good-pos
 	    (c-append-to-state-cache cache-pos here))



-- 
Alan Mackenzie (Nuremberg, Germany).




This bug report was last modified 11 years and 135 days ago.

Previous Next


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