Subject: Re: bug#39409: CC Mode 5.33.1 (C/*l); Wrong fontification of "foo * sizeof"

From: Alan Mackenzie <[email-masked]>
Date: Thu, 6 Feb 2020 20:21:41 +0000

Hello again, Benjamin.

Apologies for answering your original post rather hastily.  CC Mode 5.34
does indeed leave wrong fontifications as you have noted below.  I'd
forgotten a particular patch I'd made since 5.34 which has a bearing on
these fontifications.  This was

changeset:   6660:19eb4ddc766b
tag:         2019-09-16-dix-m
user:        Alan Mackenzie <[email-masked]>
date:        Sat Sep 21 12:11:27 2019 +0000
files:       cc-engine.el tests/statement-29.cc tests/statement-29.face
description:
CC Mode: Fix wrong fontification of FOO in ASSERT (FOO && !BAR)

from the CC Mode Mercurial repository at SourceForge.

Could I ask you, please, to apply this patch to your copy of CC Mode
5.34:

diff -r a5dbcca7730b -r 19eb4ddc766b cc-engine.el
--- a/cc-engine.el	Sat Sep 21 12:09:54 2019 +0000
+++ b/cc-engine.el	Sat Sep 21 12:11:27 2019 +0000
@@ -10109,7 +10109,8 @@
 		     (throw 'at-decl-or-cast t)))))
 
 	   ;; CASE 18
-	   (when (and (not (memq context '(nil top)))
+	   (when (and at-decl-end
+		      (not (memq context '(nil top)))
 		      (or (and got-prefix (not got-number))
 			  (and (eq context 'decl)
 			       (not c-recognize-paren-inits)

On Wed, Feb 05, 2020 at 23:57:13 +0000, Benjamin Moody wrote:
> Hi,

> Thank you for all your work on CC Mode.  And yeah, I know C syntax can
> get pretty hairy. :)

> The curious thing is, though, this issue doesn't seem to occur with
> "foo * bar(baz)".  What I'm seeing seems to happen specifically when
> the "function" is actually a keyword (like sizeof), and the expression
> is enclosed in parentheses:

With the above patch in place and cc-engine.el recompiled, the
fontification of your test file from yesterday seems to be correct.  In
particular:

> void foo()
> {
>   xxx(xxx * xxx(xxx));          /* correct */
>   xxx(ttt * sizeof(xxx));       /* wrong */

>   xxx(xxx, xxx * xxx(xxx));     /* correct */
>   xxx(xxx, ttt * sizeof(xxx));  /* wrong */

These two "wrong" lines are now fontified correctly.

>   ttt * fff(xxx);               /* ambiguous, but logical */

Indeed.  Being at the "top level", this can only be a declaration.  If
you put "foo = " in front of that line, turning it into a statement, the
fontifications on ttt and fff disappear.

>   xxx * sizeof(xxx);            /* correct */

>   (xxx * xxx(xxx));             /* correct */
>   (ttt * sizeof(xxx));          /* wrong */

This one is now correct.

>   xxx = xxx * xxx(xxx);         /* correct */
>   xxx = xxx * sizeof(xxx);      /* correct */

>   xxx = (ttt * fff(xxx));       /* wrong (I think) */
>   xxx = (xxx * sizeof(xxx));    /* correct */

Here ttt gets type face because a previous ttt has been recognised as a
type and entered into CC Mode's "found types" mechanism.  If you change
this ttt into tttt, the wrong fontification disappears, since tttt is
not registered as a "found type".

> }

> (In these examples, 'xxx' uses the default face, 'ttt' uses
> font-lock-type-face, 'fff' uses font-lock-function-name-face, and of
> course 'sizeof' uses font-lock-keyword-face.)

> I tried the standalone version (cc-mode-5.34.tar.gz) and it appears to
> give the same results as above.

Yes.  Sorry once again for not being more careful in my first reply.

> Benjamin

-- 
Alan Mackenzie (Nuremberg, Germany).