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

Alan Mackenzie <[email protected]> Tue, 18 Oct 2022 08:02:24 +0000
Newsgroups gmane.emacs.cc-mode.general
Message-ID <Y05dkKJdu3b5DLYw@ACM>
Hello, Po.

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.  What problems does an inline patch cause?

-- 
Alan Mackenzie (Nuremberg, Germany).
diff.20221017.diff (text/plain, 3.9 KB)
diff -r 0e4b43dec11c cc-engine.el
--- a/cc-engine.el	Fri Oct 14 17:13:47 2022 +0000
+++ b/cc-engine.el	Mon Oct 17 15:29:55 2022 +0000
@@ -9123,7 +9123,9 @@
       (when (eq name-res t)
 	;; In many languages the name can be used without the
 	;; prefix, so we add it to `c-found-types'.
-	(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)))
@@ -9208,7 +9210,10 @@
 	     (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
@@ -10777,8 +10782,16 @@
 			 (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
@@ -10894,8 +10907,13 @@
 
 	 ;; 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 -r 0e4b43dec11c cc-fonts.el
--- a/cc-fonts.el	Fri Oct 14 17:13:47 2022 +0000
+++ b/cc-fonts.el	Mon Oct 17 15:29:55 2022 +0000
@@ -1200,8 +1200,21 @@
   ;; 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 -r 0e4b43dec11c cc-mode.el
--- a/cc-mode.el	Fri Oct 14 17:13:47 2022 +0000
+++ b/cc-mode.el	Mon Oct 17 15:29:55 2022 +0000
@@ -2066,13 +2066,14 @@
 (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