Subject: bug#62339: cc-mode fontifies variables incorrectly when const follows type

From: Alan Mackenzie <[email-masked]>
Date: Thu, 23 Mar 2023 14:40:23 +0000

Hello, Daniel.

On Wed, Mar 22, 2023 at 18:17:05 -0400, Daniel Colascione wrote:

> Alan Mackenzie <[email-masked]> writes:

> > Hello, Eli and Daniel.

> > Thanks for the bug report!

> > On Wed, Mar 22, 2023 at 17:12:52 +0200, Eli Zaretskii wrote:
> >> > From: Daniel Colascione <[email-masked]>
> >> > Cc: [email-masked]
> >> > Date: Wed, 22 Mar 2023 10:19:55 -0400

> >> > This problem reproduces for me on latest master with emacs -Q:

> >> > ```
> >> > TEST(Foo, Bar) {
> >> >   NamedTemporaryDirectory const test_directory;
> >> > }
> >> > ```

> >> Thanks.  What I see with Emacs built from master is that
> >> test_directory in the above example gets font-lock-type-face in
> >> c++-mode (but not in c-mode).  With Emacs built from emacs-29, both
> >> modes produce correct fontification.

> >> Alan, can you please look into this?

> > I think this is caused by a faulty fix of bug #59267, where "typeless" C
> > declarations like

> >     const foo;

> > , which are implicit int, were not being recognised.

> Can we back out this fix in the meantime? These "typeless" declarations
> can't be all that common.

It turned out that the bug was caused by a single missing line of code, a 
(c-forward-syntactic-ws) in c-forward-type, so the fix wasn't too
difficult.  I've taken the opportunity also to fix some minor other
innaccuracies in c-forward-type.

Please try the following patch, and either confirm to me that it appears
to fix the bug, or say what's still wrong.  Thanks!

diff -r 300ebf19cd62 cc-engine.el
--- a/cc-engine.el	Fri Feb 17 08:58:11 2023 +0000
+++ b/cc-engine.el	Thu Mar 23 14:34:08 2023 +0000
@@ -9143,7 +9143,7 @@
     (c-forward-syntactic-ws))
 
   (let ((start (point)) pos res name-res id-start id-end id-range
-	post-prefix-pos)
+	post-prefix-pos prefix-end-pos)
 
     ;; Skip leading type modifiers.  If any are found we know it's a
     ;; prefix of a type.
@@ -9153,6 +9153,7 @@
 	  (when (looking-at c-no-type-key)
 	    (setq res 'no-id)))
 	(goto-char (match-end 1))
+	(setq prefix-end-pos (point))
 	(setq pos (point))
 	(c-forward-syntactic-ws)
 	(or (eq res 'no-id)
@@ -9304,7 +9305,10 @@
 		  (not (looking-at c-type-decl-prefix-key)))))
       ;; A C specifier followed by an implicit int, e.g.
       ;; "register count;"
-      (goto-char id-start)
+      (goto-char prefix-end-pos)
+      (setq pos (point))
+      (unless stop-at-end
+	(c-forward-syntactic-ws))
       (setq res 'no-id))
 
      (name-res
@@ -9312,6 +9316,7 @@
 	     ;; A normal identifier.
 	     (goto-char id-end)
 	     (setq pos (point))
+	     (c-forward-syntactic-ws)
 	     (if (or res c-promote-possible-types)
 		 (progn
 		   (when (not (eq c-promote-possible-types 'just-one))
@@ -9319,7 +9324,9 @@
 		   (when (and c-record-type-identifiers id-range)
 		     (c-record-type-id id-range))
 		   (unless res
-		     (setq res 'found)))
+		     (setq res 'found))
+		   (when (eq res 'prefix)
+		     (setq res t)))
 	       (setq res (if (c-check-qualified-type id-start)
 			     ;; It's an identifier that has been used as
 			     ;; a type somewhere else.

-- 
Alan Mackenzie (Nuremberg, Germany).