Subject: Re: bug#69293: 30.0.50; cc-mode doesn't support "if consteval"

From: Herman, Géza <[email-masked]>
Date: Mon, 25 Mar 2024 10:37:14 +0100

Hi Alan,

I agree, "if consteval" looks weird indeed.

With your patch, "if consteval" indents correctly.  I used cc-mode 
with your patch for a day, haven't noticed any newly introduced 
bugs.

Thank you, and get better!
Géza

Alan Mackenzie <[email-masked]> writes:

> Hello, Géza.
>
> Sorry it's taken a long time to respond.  I've been unwell.
>
> On Tue, Feb 20, 2024 at 21:21:27 +0100, Herman wrote:
>
>> C++ has a new feature, "if consteval". So one can write code 
>> like
>
>> if consteval {
>>     // do something
>> } else {
>>     // do something else
>> }
>
> Yes, indeed.  Maybe I'm the only person to think so, but I think 
> it's a
> horrible distortion of C syntax.  Anyway ...
>
>> The problem is that cc-mode doesn't recognize this construct, 
>> lines
>> are not indented correctly: the "// do something" and the "} 
>> else {"
>> receive an additional level of indentation.
>
> Would you please try out the patch below on your Emacs, then 
> byte
> compile CC Mode in its entirety (there are new macros) then load 
> it into
> a running Emacs (or restart Emacs).  cc-mode is in 
> .../lisp/progmodes.
>
> Then please let me know how well it fixes the bug.  Thanks!
>
>> In GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, cairo 
>> version
>>  1.18.0) of 2023-11-29 built on okoska
>> Repository revision: 47837b3863deba274f16960f1ee9fde4acb9d5a1
>> Repository branch: my-modifications
>> Windowing system distributor 'The X.Org Foundation', version 
>> 11.0.12101008
>> System Description: Debian GNU/Linux trixie/sid
>
> [ .... ]
>
>
>
> diff -r 779141971296 cc-engine.el
> --- a/cc-engine.el	Sun Dec 31 10:45:58 2023 +0000
> +++ b/cc-engine.el	Fri Mar 22 12:54:39 2024 +0000
> @@ -12365,13 +12365,21 @@
>  	     (zerop (c-backward-token-2 1 t lim))
>  	   t)
>  	 (or (looking-at c-block-stmt-1-key)
> -	     (and (eq (char-after) ?\()
> -		  (zerop (c-backward-token-2 1 t lim))
> -		  (if (looking-at c-block-stmt-hangon-key)
> -		      (zerop (c-backward-token-2 1 t lim))
> -		    t)
> -		  (or (looking-at c-block-stmt-2-key)
> -		      (looking-at c-block-stmt-1-2-key))))
> +	     (or
> +	      (and
> +	       (eq (char-after) ?\()
> +	       (zerop (c-backward-token-2 1 t lim))
> +	       (if (looking-at c-block-stmt-hangon-key)
> +		   (zerop (c-backward-token-2 1 t lim))
> +		 t)
> +	       (or (looking-at c-block-stmt-2-key)
> +		   (looking-at c-block-stmt-1-2-key)))
> +	      (and (looking-at c-paren-clause-key)
> +		   (zerop (c-backward-token-2 1 t lim))
> +		   (if (looking-at c-negation-op-re)
> +		       (zerop (c-backward-token-2 1 t lim))
> +		     t)
> +		   (looking-at c-block-stmt-with-key))))
>  	 (point))))
>
>  (defun c-after-special-operator-id (&optional lim)
> diff -r 779141971296 cc-langs.el
> --- a/cc-langs.el	Sun Dec 31 10:45:58 2023 +0000
> +++ b/cc-langs.el	Fri Mar 22 12:54:39 2024 +0000
> @@ -1583,6 +1583,12 @@
>  (c-lang-defvar c-assignment-op-regexp
>    (c-lang-const c-assignment-op-regexp))
>
> +(c-lang-defconst c-negation-op-re
> +  ;; Regexp matching the negation operator.
> +  t "!\\([^=]\\|$\\)")
> +
> +(c-lang-defvar c-negation-op-re (c-lang-const 
> c-negation-op-re))
> +
>  (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.
> @@ -3149,6 +3155,30 @@
>  		  (c-lang-const c-block-stmt-2-kwds)))))
>  (c-lang-defvar c-opt-block-stmt-key (c-lang-const 
>  c-opt-block-stmt-key))
>
> +(c-lang-defconst c-paren-clause-kwds
> +  "Keywords which can stand in the place of paren sexps in 
> conditionals.
> +This applies only to conditionals in `c-block-stmt-with-kwds'."
> +  t nil
> +  c++ '("consteval"))
> +
> +(c-lang-defconst c-paren-clause-key
> +  ;; Regexp matching a keyword in `c-paren-clause-kwds'.
> +  t (c-make-keywords-re t
> +      (c-lang-const c-paren-clause-kwds)))
> +(c-lang-defvar c-paren-clause-key (c-lang-const 
> c-paren-clause-key))
> +
> +(c-lang-defconst c-block-stmt-with-kwds
> +  "Statement keywords which can be followed by a keyword 
> instead of a parens.
> +Such a keyword is a member of `c-paren-clause-kwds."
> +  t nil
> +  c++ '("if"))
> +
> +(c-lang-defconst c-block-stmt-with-key
> +  ;; Regexp matching a keyword in `c-block-stmt-with-kwds'.
> +  t (c-make-keywords-re t
> +      (c-lang-const c-block-stmt-with-kwds)))
> +(c-lang-defvar c-block-stmt-with-key (c-lang-const 
> c-block-stmt-with-key))
> +
>  (c-lang-defconst c-simple-stmt-kwds
>    "Statement keywords followed by an expression or nothing."
>    t    '("break" "continue" "goto" "return")