bug#58537: CC Mode 5.35.1 (C/*l); Keywords being fontified as types at random

Alan Mackenzie <[email protected]> Wed, 19 Oct 2022 09:40:07 +0000
Newsgroups gmane.emacs.cc-mode.general
Message-ID <Y0/F9+dxfCCnlxYN@ACM>
Hello, Po.

On Wed, Oct 19, 2022 at 09:03:11 +0800, Po Lu wrote:
> Alan Mackenzie <[email protected]> writes:

> > On Tue, Oct 18, 2022 at 09:04:23 +0800, Po Lu wrote:
> >> Alan Mackenzie <[email protected]> writes:

> > [ .... ]

> >> > Please try out the following patch (which also includes yesterday's
> >> > change).  It also aims to solve the same problem when instead of

> >> > Does this patch, together with that for bug #58534 also solve #58539, or
> >> > is that still giving trouble?

> >> Could you please send it as an attachment instead?  Thanks.

> > OK, attached.

> Thanks, but now I get:

> <stdin>:73: trailing whitespace.
>     (cond 
> error: patch failed: lisp/progmodes/cc-engine.el:9123
> error: lisp/progmodes/cc-engine.el: patch does not apply

Apologies.  I'd committed the fix for bug #58534 after creating the
patch, and forgot about that.

I attach a corrected patch, which should now apply cleanly.

> > What problems does an inline patch cause?

> It gets turned into HTML due to the presence of ":)" in its contents.

What a wierd mail-reader!

I think the patch solves #58537 together with the problems you reported
since.  Does it also solve #58539?

-- 
Alan Mackenzie (Nuremberg, Germany).
diff.20221019.diff (text/plain, 4.1 KB)
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 596cccdf48..409b27d0a9 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -9106,7 +9106,9 @@ c-forward-type
 	(when (save-excursion
 		(goto-char post-prefix-pos)
 		(looking-at c-self-contained-typename-key))
-	  (c-add-type pos (point)))
+	  (c-add-type pos (save-excursion
+			    (c-backward-syntactic-ws)
+			    (point))))
 	(when (and c-record-type-identifiers
 		   c-last-identifier-range)
 	  (c-record-type-id c-last-identifier-range)))
@@ -9191,7 +9193,10 @@ c-forward-type
 	     (goto-char id-end)
 	     (if (or res c-promote-possible-types)
 		 (progn
-		   (c-add-type id-start id-end)
+		   (c-add-type id-start (save-excursion
+					  (goto-char id-end)
+					  (c-backward-syntactic-ws)
+					  (point)))
 		   (when (and c-record-type-identifiers id-range)
 		     (c-record-type-id id-range))
 		   (unless res
@@ -10762,8 +10767,16 @@ c-forward-decl-or-cast-1
 			 (setq backup-if-not-cast t)
 			 (throw 'at-decl-or-cast t)))
 
-		     (setq backup-if-not-cast t)
-		     (throw 'at-decl-or-cast t)))
+		     ;; If we're in declaration or template delimiters, or one
+		     ;; of a certain set of characters follows, we've got a
+		     ;; type and variable.
+		     (if (or (memq context '(decl <>))
+			     (memq (char-after) '(?\; ?, ?= ?\( ?{ ?:)))
+			 (progn
+			   (setq backup-if-not-cast t)
+			   (throw 'at-decl-or-cast t))
+		       ;; We're probably just typing a statement.
+		       (throw 'at-decl-or-cast nil))))
 
 		 ;; CASE 4
 		 (when (and got-suffix
@@ -10879,8 +10892,13 @@ c-forward-decl-or-cast-1
 
 	 ;; CASE 10
 	 (when at-decl-or-cast
-	   ;; By now we've located the type in the declaration that we know
-	   ;; we're in.
+	   ;; By now we've located the type in the declaration that we think
+	   ;; we're in.  Do we have enough evidence to promote the putative
+	   ;; type to a found type?  The user may be halfway through typing
+	   ;; a statement beginning with an identifier.
+	   (when (and (eq at-type 'maybe)
+		      (not (eq context 'top)))
+	     (setq c-record-type-identifiers nil))
 	   (throw 'at-decl-or-cast t))
 
 	 ;; CASE 11
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index b4ff32b907..aa16da7070 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -1197,8 +1197,21 @@ c-get-fontification-context
   ;; arguments lists (i.e. lists enclosed by <...>) is more strict about what
   ;; characters it allows within the list.
   (let ((type (and (> match-pos (point-min))
-		   (c-get-char-property (1- match-pos) 'c-type))))
-    (cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?< ?{)))
+		   (c-get-char-property (1- match-pos) 'c-type)))
+	id-pos)
+    (cond
+     ;; Are we just after something like "(foo((bar))" ?
+     ((and (eq (char-before match-pos) ?\))
+	   (c-go-list-backward match-pos)
+	   (progn
+	     (c-backward-syntactic-ws)
+	     (and (setq id-pos (c-on-identifier))
+		  (goto-char id-pos)
+		  (progn
+		    (c-backward-syntactic-ws)
+		    (eq (char-before) ?\()))))
+      (c-get-fontification-context (point) not-front-decl toplev))
+	  ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?< ?{)))
 	   (cons (and toplev 'top) nil))
 	  ;; A control flow expression or a decltype
 	  ((and (eq (char-before match-pos) ?\()
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index dce300f33c..2aa6b90dea 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -2080,13 +2080,14 @@ c-after-change-fix-comment-escapes
 (defun c-update-new-id (end)
   ;; Note the bounds of any identifier that END is in or just after, in
   ;; `c-new-id-start' and `c-new-id-end'.  Otherwise set these variables to
-  ;; nil.
+  ;; nil.  Set `c-new-id-is-type' unconditionally to nil.
   (save-excursion
     (goto-char end)
     (let ((id-beg (c-on-identifier)))
       (setq c-new-id-start id-beg
 	    c-new-id-end (and id-beg
-			      (progn (c-end-of-current-token) (point)))))))
+			      (progn (c-end-of-current-token) (point)))
+	    c-new-id-is-type nil))))
 
 (defun c-post-command ()
   ;; If point was inside of a new identifier and no longer is, record that