Subject: Re: bug#24377: 25.1; CC-Mode (C++) uses font-lock-type-face for ordinary variable

From: Bastian Beischer <[email-masked]>
Date: Tue, 13 Sep 2016 22:24:40 +0200

Hello Alan,

First of all, thanks for the patch - it's appreciated. My comments
below:

Alan Mackenzie <[email-masked]> writes:

> Hello, Bastian.
>
> In article <[email-masked]> you wrote:
>
>> This piece of C++ code is wrongly fontified by CC-Mode:
>
>> int b = 5;
>> int a = (b*3);
>
>> Reproduce as follows:
>
>> 1) emacs -Q
>> 2) Open file "test.C"
>> 3) Paste snippet in buffer
>> 4) Place cursor over "b" in second line
>> 5) M-x describe-face -> font-lock-type-face
>
>> This appears to be correlated with the presence of the opening
>> parentheses and the '*' character, because:
>
>> 1) int a = b*3;
>> does not have this problem
>
>> 2) "b" gets fontified incorrectly after entering the '*' character:
>> int a = (b*
>
> Thanks for this bug report, and thanks even more for taking the trouble
> to reduce the test case to just two lines.
>
>> In GNU Emacs 25.1.2 (x86_64-unknown-linux-gnu, GTK+ Version 2.24.30)
>>  of 2016-08-30 built on beischer-w520
>> Repository revision: 17197d0ae9eac100b56078b2a48964b29710b76e
>> Windowing system distributor 'The X.Org Foundation', version 11.0.11804000
>> Configured using:
>>  'configure --prefix=/usr --sysconfdir=/etc --libexecdir=/usr/lib
>>  --localstatedir=/var --mandir=/usr/share/man --with-gameuser=:games
>>  --with-sound=alsa --with-xft --with-modules --with-x-toolkit=gtk2
>>  --with-gconf --without-gsettings 'CFLAGS=-march=native -O2 -pipe
>>  -fstack-protector-strong' CPPFLAGS=-D_FORTIFY_SOURCE=2
>>  LDFLAGS=-Wl,-O1,--sort-common,--as-needed,-z,relro'
>
> [ .... ]
>
> Yes, the CC Mode fontification code was confusing the "*" with an
> indirection operator, such as you might get in "int (*b) (....);"
>
> The solution seems to be to recognise the case where an arithmetic
> operator (including "=") precedes the open parenthesis.  This is what the
> following patch does.  Would you please try out this patch on real code,
> and let me know whether the problem is completely fixed, and if not,
> what's still going wrong.  Thanks!
>

Yes this helps in the example above, but I'm not sure this is a fully
correct solution. One can write something like this:

void f(int arg)  {
     printf("%d\n", arg)
}

f(a*5);

Another example:

int d(a*5)

In both cases a is also wrongly fontified (and still is after applying
the patch).

> After applying the patch, plese recompile all of CC Mode, since the
> change is partly in Lisp macros, which need to propagate to other files.
>
> Here's the patch:
>

Thanks a lot again!

On Tue, Sep 13, 2016 at 8:35 PM, Alan Mackenzie <[email-masked]> wrote:
> Hello, Bastian.
>
> In article <[email-masked]> you wrote:
>
>> This piece of C++ code is wrongly fontified by CC-Mode:
>
>> int b = 5;
>> int a = (b*3);
>
>> Reproduce as follows:
>
>> 1) emacs -Q
>> 2) Open file "test.C"
>> 3) Paste snippet in buffer
>> 4) Place cursor over "b" in second line
>> 5) M-x describe-face -> font-lock-type-face
>
>> This appears to be correlated with the presence of the opening
>> parentheses and the '*' character, because:
>
>> 1) int a = b*3;
>> does not have this problem
>
>> 2) "b" gets fontified incorrectly after entering the '*' character:
>> int a = (b*
>
> Thanks for this bug report, and thanks even more for taking the trouble
> to reduce the test case to just two lines.
>
>> In GNU Emacs 25.1.2 (x86_64-unknown-linux-gnu, GTK+ Version 2.24.30)
>>  of 2016-08-30 built on beischer-w520
>> Repository revision: 17197d0ae9eac100b56078b2a48964b29710b76e
>> Windowing system distributor 'The X.Org Foundation', version 11.0.11804000
>> Configured using:
>>  'configure --prefix=/usr --sysconfdir=/etc --libexecdir=/usr/lib
>>  --localstatedir=/var --mandir=/usr/share/man --with-gameuser=:games
>>  --with-sound=alsa --with-xft --with-modules --with-x-toolkit=gtk2
>>  --with-gconf --without-gsettings 'CFLAGS=-march=native -O2 -pipe
>>  -fstack-protector-strong' CPPFLAGS=-D_FORTIFY_SOURCE=2
>>  LDFLAGS=-Wl,-O1,--sort-common,--as-needed,-z,relro'
>
> [ .... ]
>
> Yes, the CC Mode fontification code was confusing the "*" with an
> indirection operator, such as you might get in "int (*b) (....);"
>
> The solution seems to be to recognise the case where an arithmetic
> operator (including "=") precedes the open parenthesis.  This is what the
> following patch does.  Would you please try out this patch on real code,
> and let me know whether the problem is completely fixed, and if not,
> what's still going wrong.  Thanks!
>
> After applying the patch, plese recompile all of CC Mode, since the
> change is partly in Lisp macros, which need to propagate to other files.
>
> Here's the patch:
>
>
>
> diff -r 9ff65a2d07bd cc-fonts.el
> --- a/cc-fonts.el       Sun Sep 11 20:46:35 2016 +0000
> +++ b/cc-fonts.el       Tue Sep 13 18:22:17 2016 +0000
> @@ -1310,6 +1310,13 @@
>                      ;; multiline declaration.
>                      (c-put-char-property (1- match-pos)
>                                           'c-type 'c-decl-arg-start))
> +                   ;; Got an open paren preceded by an arith operator.
> +                   ((and (eq (char-before match-pos) ?\()
> +                         (save-excursion
> +                           (and (zerop (c-backward-token-2 2))
> +                                (looking-at c-arithmetic-op-regexp))))
> +                    (setq context nil
> +                          c-restricted-<>-arglists nil))
>                     (t (setq context 'arglist
>                              c-restricted-<>-arglists t))))
>
> diff -r 9ff65a2d07bd cc-langs.el
> --- a/cc-langs.el       Sun Sep 11 20:46:35 2016 +0000
> +++ b/cc-langs.el       Tue Sep 13 18:22:17 2016 +0000
> @@ -1231,6 +1231,22 @@
>  (c-lang-defvar c-assignment-op-regexp
>    (c-lang-const c-assignment-op-regexp))
>
> +(c-lang-defconst c-arithmetic-operators
> +  "List of all arithmetic operators, including \"+=\", etc."
> +  ;; Note: in the following, there are too many operators for AWK and IDL.
> +  t (append (c-lang-const c-assignment-operators)
> +           '("+" "-" "*" "/" "%"
> +             "<<" ">>"
> +             "<" ">" "<=" ">="
> +             "==" "!="
> +             "&" "^" "|"
> +             "&&" "||")))
> +
> +(c-lang-defconst c-arithmetic-op-regexp
> +  t (c-make-keywords-re nil
> +      (c-lang-const c-arithmetic-operators)))
> +(c-lang-defvar c-arithmetic-op-regexp (c-lang-const c-arithmetic-op-regexp))
> +
>  (c-lang-defconst c-:$-multichar-token-regexp
>    ;; Regexp matching all tokens ending in ":" which are longer than one char.
>    ;; Currently (2016-01-07) only used in C++ Mode.
>
>
>
> --
> Alan Mackenzie (Nuremberg, Germany).
>

-- 
Bastian Beischer
RWTH Aachen University of Technology

@CERN
Office: Bdg 32-4-B12
Phone: +41-22-76-75750
E-mail: [email-masked]
Address: CERN, CH-1211 Geneve 23

@RWTH Aachen
Office: 28 C 203
Phone: +49-241-80-27205
E-mail: [email-masked]
Address: I. Physikalisches Institut B, Sommerfeldstr. 14, D-52074 Aachen