Subject: bug#22156: CC Mode 5.33 (C++/l); Strange end-of-buffer error

From: Alan Mackenzie <[email-masked]>
Date: Thu, 17 Dec 2015 14:35:46 +0000

Hello, Michael.

On Sun, Dec 13, 2015 at 12:15:42AM -0500, Michael Welsh Duggan wrote:
> Using emacs -Q /tmp/foo.cpp to start a new file, type the following:

> struct foo<A<B,

> When you type the comma, you should get an "End of buffer" error.  The
> error seems to be at the point following this in the backtrace:

Yes.  Thanks again for such a succinct bug report, and for the
backtrace.  For some reason I couldn't get Emacs to give me a backtrace
no matter what I tried.

> Debugger entered--returning value: nil
>   c-syntactic-re-search-forward("[<;{},|+&-]\\|[>)]" nil t t)
> * c-forward-<>-arglist-recur(nil)
> * c-forward-<>-arglist-recur(nil)
> * c-forward-<>-arglist(nil)
> * c-forward-name()
> * c-forward-type(t)
> * #[(preceding-token-end context last-cast-end) "`\306\211\211\211\211\211\ ...
> * apply(#[(preceding-token-end context last-cast-end) "`\306\211\211\211\211\211 ...
> * c-forward-decl-or-cast-1(1 nil nil)
>   c-just-after-func-arglist-p(1)
>   c-guess-basic-syntax()
>   c-indent-line()
>   c-electric-semi&comma(nil)
>   funcall-interactively(c-electric-semi&comma nil)
>   call-interactively(c-electric-semi&comma nil nil)
>   command-execute(c-electric-semi&comma)

> Emacs  : GNU Emacs 25.1.50.1 (x86_64-pc-linux-gnu, X toolkit)
>  of 2015-11-26
> Package: CC Mode 5.33 (C++/l)
> Buffer Style: SiLK
> c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties 1-bit)

[ Dump of CC Mode's state snipped, but appreciated. ]

The cause was a simple coding error: after searching forward (for a
closing >), c-forward-<>-arglist-recur failed to set point back to the
starting place before trying the next possibility.

Here is a patch which I hope fixes things.  Please let me know whether
or not it works satisfactorily.

diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index acc2edd..11a0db2 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -5964,7 +5964,7 @@ c-forward-<>-arglist-recur
   ;; Recursive part of `c-forward-<>-arglist'.
   ;;
   ;; This function might do hidden buffer changes.
-  (let ((start (point)) res pos tmp
+  (let ((start (point)) res pos
 	;; Cover this so that any recorded found type ranges are
 	;; automatically lost if it turns out to not be an angle
 	;; bracket arglist.  It's propagated through the return value
@@ -6059,15 +6059,13 @@ c-forward-<>-arglist-recur
 		  ;; Either an operator starting with '<' or a nested arglist.
 		  (setq pos (point))
 		  (let (id-start id-end subres keyword-match)
-                  (cond
+		    (cond
 		     ;; The '<' begins a multi-char operator.
 		     ((looking-at c-<-op-cont-regexp)
-		      (setq tmp (match-end 0))
 		      (goto-char (match-end 0)))
 		     ;; We're at a nested <.....>
 		     ((progn
-			(setq tmp pos)
-			(backward-char) ; to the '<'
+			(backward-char)	; to the '<'
 			(and
 			 (save-excursion
 			   ;; There's always an identifier before an angle
@@ -6087,7 +6085,9 @@ c-forward-<>-arglist-recur
 				  (and keyword-match
 				       (c-keyword-member
 					(c-keyword-sym (match-string 1))
-					'c-<>-type-kwds)))))))
+					'c-<>-type-kwds))))))
+			(or subres (goto-char pos))
+			subres)
 		      ;; It was an angle bracket arglist.
 		      (setq c-record-found-types subres)
 
@@ -6103,11 +6103,11 @@ c-forward-<>-arglist-recur
 			    (c-record-ref-id (cons id-start id-end))
                         (c-record-type-id (cons id-start id-end)))))
 
-                   ;; At a "less than" operator.
-                   (t
-                    (forward-char)
-                    )))
-                t)                    ; carry on looping.
+		     ;; At a "less than" operator.
+		     (t
+		      ;; (forward-char) ; NO!  We've already gone over it.
+		      )))
+		  t)			; carry on looping.
 
 		 ((and (not c-restricted-<>-arglists)
 		       (or (and (eq (char-before) ?&)

> -- 
> Michael Welsh Duggan
> ([email-masked])

-- 
Alan Mackenzie (Nuremberg, Germany).