GNU bug report logs - #66911
CC Mode 5.35.2 (C++//l); Noise macro being taken as anchor to class-open

Previous Next

Package: cc-mode;

Reported by: Arsen Arsenović <arsen <at> aarsen.me>

Date: Fri, 3 Nov 2023 10:24:02 UTC

Severity: normal

Done: Alan Mackenzie <acm <at> muc.de>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 66911 in the body.
You can then email your comments to 66911 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Fri, 03 Nov 2023 10:24:03 GMT) Full text and rfc822 format available.

Acknowledgement sent to Arsen Arsenović <arsen <at> aarsen.me>:
New bug report received and forwarded. Copy sent to bug-cc-mode <at> gnu.org. (Fri, 03 Nov 2023 10:24:03 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Arsen Arsenović <arsen <at> aarsen.me>
To: bug-gnu-emacs <at> gnu.org
Subject: CC Mode 5.35.2 (C++//l); Noise macro being taken as anchor to
 class-open
Date: Fri, 03 Nov 2023 10:51:32 +0100
Package: cc-mode

<#secure method=pgpmime mode=sign>
Package: cc-mode

In the example below:

namespace a {
_BEGIN

  template<>
    struct foo
    { /* HERE */
    };
}

// Local Variables:
// c-noise-macro-names: ("_BEGIN")
// End:

Pressing C-c C-s on the stat of the line marked HERE shows ((class-open
15)), which is the '_' of the '_BEGIN'.  This appears to be wrong, as
the anchor should be the 'class' keyword on the line above, I believe.

Anchoring '{' on the class/struct/union that precedes it would also
enable implementing the GNU libstdc++ code style (as, AFAICT, it is
currently impossible to indent a class with a basic-offset added to the
column the 'template' keyword sits on).

Emacs  : GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.38, cairo version 1.17.8)
 of 2023-09-24
Package: CC Mode 5.35.2 (C++//l)
Buffer Style: gnu
c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties category-properties 1-bit)

current state:
==============
(setq
 c-basic-offset 2
 c-comment-only-line-offset '(0 . 0)
 c-indent-comment-alist '((anchored-comment column . 0) (end-block space . 1)
			  (cpp-end-block space . 2))
 c-indent-comments-syntactically-p nil
 c-block-comment-prefix ""
 c-comment-prefix-regexp '((pike-mode . "//+!?\\|\\**") (awk-mode . "#+")
			   (other . "//+\\|\\**"))
 c-doc-comment-style '((java-mode . javadoc) (pike-mode . autodoc) (c-mode
 . gtkdoc)
		       (c++-mode . gtkdoc))
 c-cleanup-list '(scope-operator)
 c-hanging-braces-alist '((substatement-open before after) (arglist-cont-nonempty))
 c-hanging-colons-alist nil
 c-hanging-semi&comma-criteria '(c-semi&comma-inside-parenlist)
 c-backslash-column 48
 c-backslash-max-column 72
 c-special-indent-hook '(t c-gnu-impose-minimum)
 c-label-minimum-indentation 1
 c-offsets-alist '((inexpr-class . +)
		   (inexpr-statement . +)
		   (lambda-intro-cont . +)
		   (inlambda . 0)
		   (template-args-cont
		    c-lineup-template-args
		    c-lineup-template-args-indented-from-margin
		    )
		   (incomposition . +)
		   (inmodule . +)
		   (innamespace . +)
		   (inextern-lang . +)
		   (composition-close . 0)
		   (module-close . 0)
		   (namespace-close . 0)
		   (extern-lang-close . 0)
		   (composition-open . 0)
		   (module-open . 0)
		   (namespace-open . 0)
		   (extern-lang-open . 0)
		   (objc-method-call-cont
		    c-lineup-ObjC-method-call-colons
		    c-lineup-ObjC-method-call
		    +
		    )
		   (objc-method-args-cont . c-lineup-ObjC-method-args)
		   (objc-method-intro . [0])
		   (friend . 0)
		   (cpp-define-intro c-lineup-cpp-define +)
		   (cpp-macro-cont . +)
		   (cpp-macro . [0])
		   (inclass . +)
		   (stream-op . c-lineup-streamop)
		   (arglist-cont-nonempty c-lineup-gcc-asm-reg
 c-lineup-arglist)
		   (arglist-cont c-lineup-gcc-asm-reg 0)
		   (comment-intro c-lineup-knr-region-comment c-lineup-comment)
		   (catch-clause . 0)
		   (else-clause . 0)
		   (do-while-closure . 0)
		   (access-label . -)
		   (case-label . 0)
		   (substatement . +)
		   (statement-case-intro . +)
		   (statement . 0)
		   (brace-entry-open . 0)
		   (brace-list-entry . 0)
		   (brace-list-close . 0)
		   (block-close . 0)
		   (block-open . 0)
		   (inher-cont . c-lineup-multi-inher)
		   (inher-intro . +)
		   (member-init-cont . c-lineup-multi-inher)
		   (member-init-intro . +)
		   (annotation-var-cont . +)
		   (annotation-top-cont . 0)
		   (constraint-cont . +)
		   (topmost-intro . 0)
		   (knr-argdecl . 0)
		   (func-decl-cont . +)
		   (inline-close . 0)
		   (class-close . 0)
		   (class-open . 0)
		   (defun-block-intro . +)
		   (defun-close . 0)
		   (defun-open . 0)
		   (c . c-lineup-C-comments)
		   (string . c-lineup-dont-change)
		   (topmost-intro-cont
		    first
		    c-lineup-topmost-intro-cont
		    c-lineup-gnu-DEFUN-intro-cont
		    )
		   (brace-list-intro
		    first
		    c-lineup-2nd-brace-entry-in-arglist
		    c-lineup-class-decl-init-+
		    +
		    )
		   (brace-list-open . +)
		   (inline-open . 0)
		   (arglist-close . c-lineup-arglist)
		   (arglist-intro . c-lineup-arglist-intro-after-paren)
		   (statement-cont . +)
		   (statement-case-open . +)
		   (label . 0)
		   (substatement-label . 0)
		   (substatement-open . +)
		   (knr-argdecl-intro . 5)
		   (statement-block-intro . +)
		   )
 c-buffer-is-cc-mode 'c++-mode
 c-tab-always-indent t
 c-syntactic-indentation t
 c-syntactic-indentation-in-macros t
 c-ignore-auto-fill '(string cpp code)
 c-auto-align-backslashes t
 c-backspace-function 'backward-delete-char-untabify
 c-delete-function 'delete-char
 c-electric-pound-behavior nil
 c-default-style '((java-mode . "java") (awk-mode . "awk") (other . "gnu"))
 c-enable-xemacs-performance-kludge-p nil
 c-old-style-variable-behavior nil
 defun-prompt-regexp nil
 tab-width 8
 comment-column 32
 parse-sexp-ignore-comments t
 parse-sexp-lookup-properties t
 auto-fill-function 'c-do-auto-fill
 comment-multi-line t
 comment-start-skip "\\(?://+\\|/\\*+\\)\\s *"
 fill-prefix nil
 fill-column 79
 paragraph-start "[ 	]*\\(//+\\|\\**\\)[ 	]*$\\|^\f"
 adaptive-fill-mode t
 adaptive-fill-regexp "[ 	]*\\(//+\\|\\**\\)[ 	]*\\([ 	]*\\([-–!|#%;>*·•‣⁃◦]+[ 	]*\\)*\\)"
 )

-- 
Arsen Arsenović




Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Mon, 06 Nov 2023 10:48:02 GMT) Full text and rfc822 format available.

Message #8 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Arsen Arsenović <arsen <at> aarsen.me>
Cc: acm <at> muc.de, 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Mon, 6 Nov 2023 10:47:03 +0000
Hello, Arsen.

Thanks for taking the trouble to report this bug, and thanks even more
for such a high quality bug report!

On Fri, Nov 03, 2023 at 10:51:32 +0100, Arsen Arsenović via CC-Mode-help wrote:
> Package: cc-mode

> <#secure method=pgpmime mode=sign>
> Package: cc-mode

> In the example below:

> namespace a {
> _BEGIN

>   template<>
>     struct foo
>     { /* HERE */
>     };
> }

> // Local Variables:
> // c-noise-macro-names: ("_BEGIN")
> // End:

> Pressing C-c C-s on the stat of the line marked HERE shows ((class-open
> 15)), which is the '_' of the '_BEGIN'.  This appears to be wrong, as
> the anchor should be the 'class' keyword on the line above, I believe.

> Anchoring '{' on the class/struct/union that precedes it would also
> enable implementing the GNU libstdc++ code style (as, AFAICT, it is
> currently impossible to indent a class with a basic-offset added to the
> column the 'template' keyword sits on).

Yes, in function c-looking-at-decl-block, the handling of template
constructs and noise macros was somewhat careless.  This should be fixed
by the patch below.

Even so, it's worth noting that noise macros with parentheses (set with
the buffer local variable c-noise-macro-with-parens-names) are currently
not handled correctly, here.  This was a decision taken some years ago,
to avoid slowing down CC Mode for a construct which is rarer than the
noise macros without parens.  I'm thinking of taking another look at
this.

Would you please apply the patch, byte compile cc-engine.el (or all of
CC Mode), load it into your Emacs and try it out on your real C++ code.
The patch should apply cleanly to the Emacs master branch.  Then please
confirm that it is actually fixes the bug, or tell me what's still not
working properly.  (If you want any help applying the patch or compiling
the file, feel free to send me private email.)

> Emacs  : GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.38, cairo version 1.17.8)
>  of 2023-09-24
> Package: CC Mode 5.35.2 (C++//l)
> Buffer Style: gnu
> c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties category-properties 1-bit)

[ .... ]

diff -r 2760aada61fa cc-engine.el
--- a/cc-engine.el	Sun Oct 15 10:44:22 2023 +0000
+++ b/cc-engine.el	Mon Nov 06 10:26:34 2023 +0000
@@ -12633,31 +12633,27 @@
   (let ((open-brace (point)) kwd-start first-specifier-pos)
     (c-syntactic-skip-backward c-block-prefix-charset limit t)
 
-    (when (and c-recognize-<>-arglists
-	       (eq (char-before) ?>))
-      ;; Could be at the end of a template arglist.
-      (let ((c-parse-and-markup-<>-arglists t))
-	(while (and
-		(c-backward-<>-arglist nil limit)
-		(progn
-		  (c-syntactic-skip-backward c-block-prefix-charset limit t)
-		  (eq (char-before) ?>))))))
-
-    ;; Skip back over noise clauses.
-    (while (and
-	    c-opt-cpp-prefix
-	    (eq (char-before) ?\))
-	    (let ((after-paren (point)))
-	      (if (and (c-go-list-backward)
-		       (progn (c-backward-syntactic-ws)
-			      (c-simple-skip-symbol-backward))
-		       (or (looking-at c-paren-nontype-key)
-			   (looking-at c-noise-macro-with-parens-name-re)))
-		  (progn
-		    (c-syntactic-skip-backward c-block-prefix-charset limit t)
-		    t)
-		(goto-char after-paren)
-		nil))))
+    (while
+	(or 
+	 ;; Could be after a template arglist....
+	 (and c-recognize-<>-arglists
+	      (eq (char-before) ?>)
+	      (let ((c-parse-and-markup-<>-arglists t))
+		(c-backward-<>-arglist nil limit)))
+	 ;; .... or after a noise clause with parens.
+	 (and c-opt-cpp-prefix
+	      (let ((after-paren (point)))
+		(if (eq (char-before) ?\))
+		    (and
+		     (c-go-list-backward)
+		     (eq (char-after) ?\()
+		     (progn (c-backward-syntactic-ws)
+			    (c-simple-skip-symbol-backward))
+		     (or (looking-at c-paren-nontype-key) ; e.g. __attribute__
+			 (looking-at c-noise-macro-with-parens-name-re)))
+		  (goto-char after-paren)
+		  nil))))
+      (c-syntactic-skip-backward c-block-prefix-charset limit t))
 
     ;; Note: Can't get bogus hits inside template arglists below since they
     ;; have gotten paren syntax above.
@@ -12667,10 +12663,18 @@
 	   ;; The `c-decl-block-key' search continues from there since
 	   ;; we know it can't match earlier.
 	   (if goto-start
-	       (when (c-syntactic-re-search-forward c-symbol-start
-						    open-brace t t)
-		 (goto-char (setq first-specifier-pos (match-beginning 0)))
-		 t)
+	       (progn
+		 (while
+		     (and
+		      (c-syntactic-re-search-forward c-symbol-start
+						     open-brace t t)
+		      (goto-char (match-beginning 0))
+		      (if (or (looking-at c-noise-macro-name-re)
+			      (looking-at c-noise-macro-with-parens-name-re))
+			  (c-forward-noise-clause)
+			(setq first-specifier-pos (match-beginning 0))
+			nil)))
+		 first-specifier-pos)
 	     t)
 
 	   (cond
@@ -12739,34 +12743,39 @@
 	    (goto-char first-specifier-pos)
 
 	    (while (< (point) kwd-start)
-	      (if (looking-at c-symbol-key)
-		  ;; Accept any plain symbol token on the ground that
-		  ;; it's a specifier masked through a macro (just
-		  ;; like `c-forward-decl-or-cast-1' skip forward over
-		  ;; such tokens).
-		  ;;
-		  ;; Could be more restrictive wrt invalid keywords,
-		  ;; but that'd only occur in invalid code so there's
-		  ;; no use spending effort on it.
-		  (let ((end (match-end 0))
-			(kwd-sym (c-keyword-sym (match-string 0))))
-		    (unless
-			(and kwd-sym
-			     ;; Moving over a protection kwd and the following
-			     ;; ":" (in C++ Mode) to the next token could take
-			     ;; us all the way up to `kwd-start', leaving us
-			     ;; no chance to update `first-specifier-pos'.
-			     (not (c-keyword-member kwd-sym 'c-protection-kwds))
-			     (c-forward-keyword-clause 0))
-		      (goto-char end)
-		      (c-forward-syntactic-ws)))
-
+	      (cond
+	       ((or (looking-at c-noise-macro-name-re)
+		    (looking-at c-noise-macro-with-parens-name-re))
+		(c-forward-noise-clause))
+	       ((looking-at c-symbol-key)
+		;; Accept any plain symbol token on the ground that
+		;; it's a specifier masked through a macro (just
+		;; like `c-forward-decl-or-cast-1' skips forward over
+		;; such tokens).
+		;;
+		;; Could be more restrictive wrt invalid keywords,
+		;; but that'd only occur in invalid code so there's
+		;; no use spending effort on it.
+		(let ((end (match-end 0))
+		      (kwd-sym (c-keyword-sym (match-string 0))))
+		  (unless
+		      (and kwd-sym
+			   ;; Moving over a protection kwd and the following
+			   ;; ":" (in C++ Mode) to the next token could take
+			   ;; us all the way up to `kwd-start', leaving us
+			   ;; no chance to update `first-specifier-pos'.
+			   (not (c-keyword-member kwd-sym 'c-protection-kwds))
+			   (c-forward-keyword-clause 0))
+		    (goto-char end)
+		    (c-forward-syntactic-ws))))
+
+	       ((c-syntactic-re-search-forward c-symbol-start
+					       kwd-start 'move t)
 		;; Can't parse a declaration preamble and is still
 		;; before `kwd-start'.  That means `first-specifier-pos'
 		;; was in some earlier construct.  Search again.
-		(if (c-syntactic-re-search-forward c-symbol-start
-						   kwd-start 'move t)
-		    (goto-char (setq first-specifier-pos (match-beginning 0)))
+		(goto-char (setq first-specifier-pos (match-beginning 0))))
+	       (t
 		  ;; Got no preamble before the block declaration keyword.
 		  (setq first-specifier-pos kwd-start))))
 

> -- 
> Arsen Arsenović

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Mon, 06 Nov 2023 12:01:01 GMT) Full text and rfc822 format available.

Message #11 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Arsen Arsenović <arsen <at> aarsen.me>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Mon, 06 Nov 2023 12:38:36 +0100
[Message part 1 (text/plain, inline)]
Hi Alan,

Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Arsen.
>
> Thanks for taking the trouble to report this bug, and thanks even more
> for such a high quality bug report!
>
> On Fri, Nov 03, 2023 at 10:51:32 +0100, Arsen Arsenović via CC-Mode-help wrote:
>> Package: cc-mode
>
>> <#secure method=pgpmime mode=sign>
>> Package: cc-mode
>
>> In the example below:
>
>> namespace a {
>> _BEGIN
>
>>   template<>
>>     struct foo
>>     { /* HERE */
>>     };
>> }
>
>> // Local Variables:
>> // c-noise-macro-names: ("_BEGIN")
>> // End:
>
>> Pressing C-c C-s on the stat of the line marked HERE shows ((class-open
>> 15)), which is the '_' of the '_BEGIN'.  This appears to be wrong, as
>> the anchor should be the 'class' keyword on the line above, I believe.
>
>> Anchoring '{' on the class/struct/union that precedes it would also
>> enable implementing the GNU libstdc++ code style (as, AFAICT, it is
>> currently impossible to indent a class with a basic-offset added to the
>> column the 'template' keyword sits on).
>
> Yes, in function c-looking-at-decl-block, the handling of template
> constructs and noise macros was somewhat careless.  This should be fixed
> by the patch below.
>
> Even so, it's worth noting that noise macros with parentheses (set with
> the buffer local variable c-noise-macro-with-parens-names) are currently
> not handled correctly, here.  This was a decision taken some years ago,
> to avoid slowing down CC Mode for a construct which is rarer than the
> noise macros without parens.  I'm thinking of taking another look at
> this.
>
> Would you please apply the patch, byte compile cc-engine.el (or all of
> CC Mode), load it into your Emacs and try it out on your real C++ code.
> The patch should apply cleanly to the Emacs master branch.  Then please
> confirm that it is actually fixes the bug, or tell me what's still not
> working properly.  (If you want any help applying the patch or compiling
> the file, feel free to send me private email.)

That indeed appears to have fixed it.  I built emacs 30.0.50 from git
(94807b6896191245ff3bef44a0ec21efb918232f) and applied your patch, then
compared the analysis and indentation before and after on libstdc++es
<bitset>, and it worked as expected (the noise macro stopped confusing
it).

Though, the anchor still anchors on the template<> line rather than the
struct line in:

  template<size_t _Nw>
  struct _Base_bitset
  {

... making it impossible (AFAICT) to create a style that implements:

  template<size_t _Nw>
    struct _Base_bitset
    {
    };

  struct foo
  {
  };

instead, the former gets formatted as:

  template<size_t _Nw>
    struct _Base_bitset
  {
  };

Is this intended?

>> Emacs  : GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.38, cairo version 1.17.8)
>>  of 2023-09-24
>> Package: CC Mode 5.35.2 (C++//l)
>> Buffer Style: gnu
>> c-emacs-features: (pps-extended-state col-0-paren posix-char-classes
>> gen-string-delim gen-comment-delim syntax-properties category-properties
>> 1-bit)
>
> [ .... ]
>
> diff -r 2760aada61fa cc-engine.el
> --- a/cc-engine.el	Sun Oct 15 10:44:22 2023 +0000
> +++ b/cc-engine.el	Mon Nov 06 10:26:34 2023 +0000
> @@ -12633,31 +12633,27 @@
>    (let ((open-brace (point)) kwd-start first-specifier-pos)
>      (c-syntactic-skip-backward c-block-prefix-charset limit t)
>  
> -    (when (and c-recognize-<>-arglists
> -	       (eq (char-before) ?>))
> -      ;; Could be at the end of a template arglist.
> -      (let ((c-parse-and-markup-<>-arglists t))
> -	(while (and
> -		(c-backward-<>-arglist nil limit)
> -		(progn
> -		  (c-syntactic-skip-backward c-block-prefix-charset limit t)
> -		  (eq (char-before) ?>))))))
> -
> -    ;; Skip back over noise clauses.
> -    (while (and
> -	    c-opt-cpp-prefix
> -	    (eq (char-before) ?\))
> -	    (let ((after-paren (point)))
> -	      (if (and (c-go-list-backward)
> -		       (progn (c-backward-syntactic-ws)
> -			      (c-simple-skip-symbol-backward))
> -		       (or (looking-at c-paren-nontype-key)
> -			   (looking-at c-noise-macro-with-parens-name-re)))
> -		  (progn
> -		    (c-syntactic-skip-backward c-block-prefix-charset limit t)
> -		    t)
> -		(goto-char after-paren)
> -		nil))))
> +    (while
> +	(or 
> +	 ;; Could be after a template arglist....
> +	 (and c-recognize-<>-arglists
> +	      (eq (char-before) ?>)
> +	      (let ((c-parse-and-markup-<>-arglists t))
> +		(c-backward-<>-arglist nil limit)))
> +	 ;; .... or after a noise clause with parens.
> +	 (and c-opt-cpp-prefix
> +	      (let ((after-paren (point)))
> +		(if (eq (char-before) ?\))
> +		    (and
> +		     (c-go-list-backward)
> +		     (eq (char-after) ?\()
> +		     (progn (c-backward-syntactic-ws)
> +			    (c-simple-skip-symbol-backward))
> +		     (or (looking-at c-paren-nontype-key) ; e.g. __attribute__
> +			 (looking-at c-noise-macro-with-parens-name-re)))
> +		  (goto-char after-paren)
> +		  nil))))
> +      (c-syntactic-skip-backward c-block-prefix-charset limit t))
>  
>      ;; Note: Can't get bogus hits inside template arglists below since they
>      ;; have gotten paren syntax above.
> @@ -12667,10 +12663,18 @@
>  	   ;; The `c-decl-block-key' search continues from there since
>  	   ;; we know it can't match earlier.
>  	   (if goto-start
> -	       (when (c-syntactic-re-search-forward c-symbol-start
> -						    open-brace t t)
> -		 (goto-char (setq first-specifier-pos (match-beginning 0)))
> -		 t)
> +	       (progn
> +		 (while
> +		     (and
> +		      (c-syntactic-re-search-forward c-symbol-start
> +						     open-brace t t)
> +		      (goto-char (match-beginning 0))
> +		      (if (or (looking-at c-noise-macro-name-re)
> +			      (looking-at c-noise-macro-with-parens-name-re))
> +			  (c-forward-noise-clause)
> +			(setq first-specifier-pos (match-beginning 0))
> +			nil)))
> +		 first-specifier-pos)
>  	     t)
>  
>  	   (cond
> @@ -12739,34 +12743,39 @@
>  	    (goto-char first-specifier-pos)
>  
>  	    (while (< (point) kwd-start)
> -	      (if (looking-at c-symbol-key)
> -		  ;; Accept any plain symbol token on the ground that
> -		  ;; it's a specifier masked through a macro (just
> -		  ;; like `c-forward-decl-or-cast-1' skip forward over
> -		  ;; such tokens).
> -		  ;;
> -		  ;; Could be more restrictive wrt invalid keywords,
> -		  ;; but that'd only occur in invalid code so there's
> -		  ;; no use spending effort on it.
> -		  (let ((end (match-end 0))
> -			(kwd-sym (c-keyword-sym (match-string 0))))
> -		    (unless
> -			(and kwd-sym
> -			     ;; Moving over a protection kwd and the following
> -			     ;; ":" (in C++ Mode) to the next token could take
> -			     ;; us all the way up to `kwd-start', leaving us
> -			     ;; no chance to update `first-specifier-pos'.
> -			     (not (c-keyword-member kwd-sym 'c-protection-kwds))
> -			     (c-forward-keyword-clause 0))
> -		      (goto-char end)
> -		      (c-forward-syntactic-ws)))
> -
> +	      (cond
> +	       ((or (looking-at c-noise-macro-name-re)
> +		    (looking-at c-noise-macro-with-parens-name-re))
> +		(c-forward-noise-clause))
> +	       ((looking-at c-symbol-key)
> +		;; Accept any plain symbol token on the ground that
> +		;; it's a specifier masked through a macro (just
> +		;; like `c-forward-decl-or-cast-1' skips forward over
> +		;; such tokens).
> +		;;
> +		;; Could be more restrictive wrt invalid keywords,
> +		;; but that'd only occur in invalid code so there's
> +		;; no use spending effort on it.
> +		(let ((end (match-end 0))
> +		      (kwd-sym (c-keyword-sym (match-string 0))))
> +		  (unless
> +		      (and kwd-sym
> +			   ;; Moving over a protection kwd and the following
> +			   ;; ":" (in C++ Mode) to the next token could take
> +			   ;; us all the way up to `kwd-start', leaving us
> +			   ;; no chance to update `first-specifier-pos'.
> +			   (not (c-keyword-member kwd-sym 'c-protection-kwds))
> +			   (c-forward-keyword-clause 0))
> +		    (goto-char end)
> +		    (c-forward-syntactic-ws))))
> +
> +	       ((c-syntactic-re-search-forward c-symbol-start
> +					       kwd-start 'move t)
>  		;; Can't parse a declaration preamble and is still
>  		;; before `kwd-start'.  That means `first-specifier-pos'
>  		;; was in some earlier construct.  Search again.
> -		(if (c-syntactic-re-search-forward c-symbol-start
> -						   kwd-start 'move t)
> -		    (goto-char (setq first-specifier-pos (match-beginning 0)))
> +		(goto-char (setq first-specifier-pos (match-beginning 0))))
> +	       (t
>  		  ;; Got no preamble before the block declaration keyword.
>  		  (setq first-specifier-pos kwd-start))))
>  
>
>> -- 
>> Arsen Arsenović


-- 
Arsen Arsenović
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Mon, 06 Nov 2023 13:49:02 GMT) Full text and rfc822 format available.

Message #14 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Arsen Arsenović <arsen <at> aarsen.me>
Cc: acm <at> muc.de, 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Mon, 6 Nov 2023 13:47:39 +0000
Hello, Arsen.

On Mon, Nov 06, 2023 at 12:38:36 +0100, Arsen Arsenović wrote:
> Hi Alan,

> Alan Mackenzie <acm <at> muc.de> writes:

> > On Fri, Nov 03, 2023 at 10:51:32 +0100, Arsen Arsenović via CC-Mode-help wrote:
> >> Package: cc-mode

[ .... ]

> > Would you please apply the patch, byte compile cc-engine.el (or all of
> > CC Mode), load it into your Emacs and try it out on your real C++ code.
> > The patch should apply cleanly to the Emacs master branch.  Then please
> > confirm that it is actually fixes the bug, or tell me what's still not
> > working properly.  (If you want any help applying the patch or compiling
> > the file, feel free to send me private email.)

> That indeed appears to have fixed it.  I built emacs 30.0.50 from git
> (94807b6896191245ff3bef44a0ec21efb918232f) and applied your patch, then
> compared the analysis and indentation before and after on libstdc++es
> <bitset>, and it worked as expected (the noise macro stopped confusing
> it).

Thanks!  Time to commit the patch, then.

> Though, the anchor still anchors on the template<> line rather than the
> struct line in:

>   template<size_t _Nw>
>   struct _Base_bitset
>   {

> ... making it impossible (AFAICT) to create a style that implements:

>   template<size_t _Nw>
>     struct _Base_bitset
>     {
>     };

>   struct foo
>   {
>   };

> instead, the former gets formatted as:

>   template<size_t _Nw>
>     struct _Base_bitset
>   {
>   };

> Is this intended?

Apologies.  I missed this second point in your original bug report.

This should be fixable, but will be more work to fix than the other
point.

I think something like the following would do it: we could add a second
anchor point to topmost-intro-cont forms, that second point pointing at
struct.  In languages without templates/generics, or in constructs
lacking template components, both anchor points would be the same.

So you could write an alignment function which would use that second
anchor point for class-open lines and the like.  Or, just possibly, we
might be able to make that second point the default for class-open.  This
should keep backward compatibility.  I'll have to think about this.

And of course, the manual and test programs will need amending, too.  ;-)

> >> Emacs  : GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.38, cairo version 1.17.8)
> >>  of 2023-09-24
> >> Package: CC Mode 5.35.2 (C++//l)
> >> Buffer Style: gnu
> >> c-emacs-features: (pps-extended-state col-0-paren posix-char-classes
> >> gen-string-delim gen-comment-delim syntax-properties category-properties
> >> 1-bit)

[ .... ]

> -- 
> Arsen Arsenović

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Mon, 06 Nov 2023 15:14:01 GMT) Full text and rfc822 format available.

Message #17 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Arsen Arsenović <arsen <at> aarsen.me>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Mon, 06 Nov 2023 16:07:05 +0100
[Message part 1 (text/plain, inline)]
Alan Mackenzie <acm <at> muc.de> writes:

>> Though, the anchor still anchors on the template<> line rather than the
>> struct line in:
>
>>   template<size_t _Nw>
>>   struct _Base_bitset
>>   {
>
>> ... making it impossible (AFAICT) to create a style that implements:
>
>>   template<size_t _Nw>
>>     struct _Base_bitset
>>     {
>>     };
>
>>   struct foo
>>   {
>>   };
>
>> instead, the former gets formatted as:
>
>>   template<size_t _Nw>
>>     struct _Base_bitset
>>   {
>>   };
>
>> Is this intended?
>
> Apologies.  I missed this second point in your original bug report.

Admittedly, I had considered making it two bug reports because the
issues seemed separate to me, but I wasn't sure if one caused the other
or vice-versa.  So, I don't blame you :-)

> This should be fixable, but will be more work to fix than the other
> point.
>
> I think something like the following would do it: we could add a second
> anchor point to topmost-intro-cont forms, that second point pointing at
> struct.  In languages without templates/generics, or in constructs
> lacking template components, both anchor points would be the same.
>
> So you could write an alignment function which would use that second
> anchor point for class-open lines and the like.  Or, just possibly, we
> might be able to make that second point the default for class-open.  This
> should keep backward compatibility.  I'll have to think about this.
>
> And of course, the manual and test programs will need amending, too.  ;-)

That sounds lovely - thanks in advance, if you do, indeed, decide to do
it.  For now, I can get this patch implemented with some manual
indenting.

Thanks for the quick fix, have a lovely day :-)
-- 
Arsen Arsenović
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Thu, 16 Nov 2023 19:22:01 GMT) Full text and rfc822 format available.

Message #20 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Arsen Arsenović <arsen <at> aarsen.me>
Cc: acm <at> muc.de, 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Thu, 16 Nov 2023 19:21:21 +0000
Hello again, Arsen.

On Mon, Nov 06, 2023 at 16:07:05 +0100, Arsen Arsenović wrote:

> Alan Mackenzie <acm <at> muc.de> writes:

> >> Though, the anchor still anchors on the template<> line rather than the
> >> struct line in:

> >>   template<size_t _Nw>
> >>   struct _Base_bitset
> >>   {

> >> ... making it impossible (AFAICT) to create a style that implements:

> >>   template<size_t _Nw>
> >>     struct _Base_bitset
> >>     {
> >>     };

> >>   struct foo
> >>   {
> >>   };

> >> instead, the former gets formatted as:

> >>   template<size_t _Nw>
> >>     struct _Base_bitset
> >>   {
> >>   };

> >> Is this intended?

> > Apologies.  I missed this second point in your original bug report.

> Admittedly, I had considered making it two bug reports because the
> issues seemed separate to me, but I wasn't sure if one caused the other
> or vice-versa.  So, I don't blame you :-)

> > This should be fixable, but will be more work to fix than the other
> > point.

> > I think something like the following would do it: we could add a second
> > anchor point to topmost-intro-cont forms, that second point pointing at
> > struct.  In languages without templates/generics, or in constructs
> > lacking template components, both anchor points would be the same.

That was a mistake - the second anchor point is needed on class-open
lines, not topmost-intro-cont ones.

I've coded up this patch, which I include below.  Actually, only the last
two smallish hunks of the patch are new, the rest is what you've seen
before, so it will be necessary to start from a clean copy of
cc-engine.el again.

The syntactical context of the HERE line (the opening brace of that
class) is now something like:

    ((class-open 76 107))

, where 76 is the position of the template keyword and 107 that of the
class keyword.  When there's no template, both of these anchor points are
the same.  Actually, that's not quite accurate: the 107 is the point
after the indentation of the line that class is on; it just seemed better
that way.

> > So you could write an alignment function which would use that second
> > anchor point for class-open lines and the like.  Or, just possibly, we
> > might be able to make that second point the default for class-open.  This
> > should keep backward compatibility.  I'll have to think about this.

So, again, please let me know how you get on with this patch.  Is the
extra anchor point sufficient to write an alignment function to get the
indentation you want?

> > And of course, the manual and test programs will need amending, too.  ;-)

They still need amending.  On running the test suite, there were 81 files
where the new class-open syntactic symbol was different from the recorded
old symbol.  So I've got 81 files to regenerate.  Fortunately, I can do
this with a script, even if it will take me a couple of hours to write
the script.

> That sounds lovely - thanks in advance, if you do, indeed, decide to do
> it.  For now, I can get this patch implemented with some manual
> indenting.

> Thanks for the quick fix, have a lovely day :-)

Thank you indeed!  Have fun with the patch.



diff -r 2760aada61fa cc-engine.el
--- a/cc-engine.el	Sun Oct 15 10:44:22 2023 +0000
+++ b/cc-engine.el	Thu Nov 16 18:58:33 2023 +0000
@@ -12633,31 +12633,27 @@
   (let ((open-brace (point)) kwd-start first-specifier-pos)
     (c-syntactic-skip-backward c-block-prefix-charset limit t)
 
-    (when (and c-recognize-<>-arglists
-	       (eq (char-before) ?>))
-      ;; Could be at the end of a template arglist.
-      (let ((c-parse-and-markup-<>-arglists t))
-	(while (and
-		(c-backward-<>-arglist nil limit)
-		(progn
-		  (c-syntactic-skip-backward c-block-prefix-charset limit t)
-		  (eq (char-before) ?>))))))
-
-    ;; Skip back over noise clauses.
-    (while (and
-	    c-opt-cpp-prefix
-	    (eq (char-before) ?\))
-	    (let ((after-paren (point)))
-	      (if (and (c-go-list-backward)
-		       (progn (c-backward-syntactic-ws)
-			      (c-simple-skip-symbol-backward))
-		       (or (looking-at c-paren-nontype-key)
-			   (looking-at c-noise-macro-with-parens-name-re)))
-		  (progn
-		    (c-syntactic-skip-backward c-block-prefix-charset limit t)
-		    t)
-		(goto-char after-paren)
-		nil))))
+    (while
+	(or
+	 ;; Could be after a template arglist....
+	 (and c-recognize-<>-arglists
+	      (eq (char-before) ?>)
+	      (let ((c-parse-and-markup-<>-arglists t))
+		(c-backward-<>-arglist nil limit)))
+	 ;; .... or after a noise clause with parens.
+	 (and c-opt-cpp-prefix
+	      (let ((after-paren (point)))
+		(if (eq (char-before) ?\))
+		    (and
+		     (c-go-list-backward)
+		     (eq (char-after) ?\()
+		     (progn (c-backward-syntactic-ws)
+			    (c-simple-skip-symbol-backward))
+		     (or (looking-at c-paren-nontype-key) ; e.g. __attribute__
+			 (looking-at c-noise-macro-with-parens-name-re)))
+		  (goto-char after-paren)
+		  nil))))
+      (c-syntactic-skip-backward c-block-prefix-charset limit t))
 
     ;; Note: Can't get bogus hits inside template arglists below since they
     ;; have gotten paren syntax above.
@@ -12667,10 +12663,18 @@
 	   ;; The `c-decl-block-key' search continues from there since
 	   ;; we know it can't match earlier.
 	   (if goto-start
-	       (when (c-syntactic-re-search-forward c-symbol-start
-						    open-brace t t)
-		 (goto-char (setq first-specifier-pos (match-beginning 0)))
-		 t)
+	       (progn
+		 (while
+		     (and
+		      (c-syntactic-re-search-forward c-symbol-start
+						     open-brace t t)
+		      (goto-char (match-beginning 0))
+		      (if (or (looking-at c-noise-macro-name-re)
+			      (looking-at c-noise-macro-with-parens-name-re))
+			  (c-forward-noise-clause)
+			(setq first-specifier-pos (match-beginning 0))
+			nil)))
+		 first-specifier-pos)
 	     t)
 
 	   (cond
@@ -12739,34 +12743,39 @@
 	    (goto-char first-specifier-pos)
 
 	    (while (< (point) kwd-start)
-	      (if (looking-at c-symbol-key)
-		  ;; Accept any plain symbol token on the ground that
-		  ;; it's a specifier masked through a macro (just
-		  ;; like `c-forward-decl-or-cast-1' skip forward over
-		  ;; such tokens).
-		  ;;
-		  ;; Could be more restrictive wrt invalid keywords,
-		  ;; but that'd only occur in invalid code so there's
-		  ;; no use spending effort on it.
-		  (let ((end (match-end 0))
-			(kwd-sym (c-keyword-sym (match-string 0))))
-		    (unless
-			(and kwd-sym
-			     ;; Moving over a protection kwd and the following
-			     ;; ":" (in C++ Mode) to the next token could take
-			     ;; us all the way up to `kwd-start', leaving us
-			     ;; no chance to update `first-specifier-pos'.
-			     (not (c-keyword-member kwd-sym 'c-protection-kwds))
-			     (c-forward-keyword-clause 0))
-		      (goto-char end)
-		      (c-forward-syntactic-ws)))
-
+	      (cond
+	       ((or (looking-at c-noise-macro-name-re)
+		    (looking-at c-noise-macro-with-parens-name-re))
+		(c-forward-noise-clause))
+	       ((looking-at c-symbol-key)
+		;; Accept any plain symbol token on the ground that
+		;; it's a specifier masked through a macro (just
+		;; like `c-forward-decl-or-cast-1' skips forward over
+		;; such tokens).
+		;;
+		;; Could be more restrictive wrt invalid keywords,
+		;; but that'd only occur in invalid code so there's
+		;; no use spending effort on it.
+		(let ((end (match-end 0))
+		      (kwd-sym (c-keyword-sym (match-string 0))))
+		  (unless
+		      (and kwd-sym
+			   ;; Moving over a protection kwd and the following
+			   ;; ":" (in C++ Mode) to the next token could take
+			   ;; us all the way up to `kwd-start', leaving us
+			   ;; no chance to update `first-specifier-pos'.
+			   (not (c-keyword-member kwd-sym 'c-protection-kwds))
+			   (c-forward-keyword-clause 0))
+		    (goto-char end)
+		    (c-forward-syntactic-ws))))
+
+	       ((c-syntactic-re-search-forward c-symbol-start
+					       kwd-start 'move t)
 		;; Can't parse a declaration preamble and is still
 		;; before `kwd-start'.  That means `first-specifier-pos'
 		;; was in some earlier construct.  Search again.
-		(if (c-syntactic-re-search-forward c-symbol-start
-						   kwd-start 'move t)
-		    (goto-char (setq first-specifier-pos (match-beginning 0)))
+		(goto-char (setq first-specifier-pos (match-beginning 0))))
+	       (t
 		  ;; Got no preamble before the block declaration keyword.
 		  (setq first-specifier-pos kwd-start))))
 
@@ -14727,7 +14736,10 @@
 			    'lambda-intro-cont)))
 	(goto-char (cdr placeholder))
 	(back-to-indentation)
-	(c-add-stmt-syntax tmpsymbol nil t
+	(c-add-stmt-syntax tmpsymbol
+			   (and (eq tmpsymbol 'class-open)
+				(list (point)))
+			   t
 			   (c-most-enclosing-brace state-cache (point))
 			   paren-state)
 	(unless (eq (point) (cdr placeholder))
@@ -14770,9 +14782,10 @@
 	      (goto-char indent-point)
 	      (skip-chars-forward " \t")
 	      (and (eq (char-after) ?{)
-		   (c-looking-at-decl-block t)
+		   (setq tmp-pos (c-looking-at-decl-block t))
 		   (setq placeholder (point))))
-	    (c-add-syntax 'class-open placeholder))
+	    (c-add-syntax 'class-open placeholder
+			  (c-point 'boi tmp-pos)))
 
 	   ;; CASE 5A.3: brace list open
 	   ((save-excursion


> -- 
> Arsen Arsenović

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Thu, 16 Nov 2023 20:44:02 GMT) Full text and rfc822 format available.

Message #23 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Arsen Arsenović <arsen <at> aarsen.me>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Thu, 16 Nov 2023 21:29:29 +0100
[Message part 1 (text/plain, inline)]
Hi Alan,

Thanks for working on this.

Alan Mackenzie <acm <at> muc.de> writes:

> Hello again, Arsen.
>
> On Mon, Nov 06, 2023 at 16:07:05 +0100, Arsen Arsenović wrote:
>
>> Alan Mackenzie <acm <at> muc.de> writes:
>
>> >> Though, the anchor still anchors on the template<> line rather than the
>> >> struct line in:
>
>> >>   template<size_t _Nw>
>> >>   struct _Base_bitset
>> >>   {
>
>> >> ... making it impossible (AFAICT) to create a style that implements:
>
>> >>   template<size_t _Nw>
>> >>     struct _Base_bitset
>> >>     {
>> >>     };
>
>> >>   struct foo
>> >>   {
>> >>   };
>
>> >> instead, the former gets formatted as:
>
>> >>   template<size_t _Nw>
>> >>     struct _Base_bitset
>> >>   {
>> >>   };
>
>> >> Is this intended?
>
>> > Apologies.  I missed this second point in your original bug report.
>
>> Admittedly, I had considered making it two bug reports because the
>> issues seemed separate to me, but I wasn't sure if one caused the other
>> or vice-versa.  So, I don't blame you :-)
>
>> > This should be fixable, but will be more work to fix than the other
>> > point.
>
>> > I think something like the following would do it: we could add a second
>> > anchor point to topmost-intro-cont forms, that second point pointing at
>> > struct.  In languages without templates/generics, or in constructs
>> > lacking template components, both anchor points would be the same.
>
> That was a mistake - the second anchor point is needed on class-open
> lines, not topmost-intro-cont ones.
>
> I've coded up this patch, which I include below.  Actually, only the last
> two smallish hunks of the patch are new, the rest is what you've seen
> before, so it will be necessary to start from a clean copy of
> cc-engine.el again.
>
> The syntactical context of the HERE line (the opening brace of that
> class) is now something like:
>
>     ((class-open 76 107))
>
> , where 76 is the position of the template keyword and 107 that of the
> class keyword.  When there's no template, both of these anchor points are
> the same.  Actually, that's not quite accurate: the 107 is the point
> after the indentation of the line that class is on; it just seemed better
> that way.

This behavior seems reasonable to me at a glance and at a test.  I like
the idea :-)

>> > So you could write an alignment function which would use that second
>> > anchor point for class-open lines and the like.  Or, just possibly, we
>> > might be able to make that second point the default for class-open.  This
>> > should keep backward compatibility.  I'll have to think about this.
>
> So, again, please let me know how you get on with this patch.  Is the
> extra anchor point sufficient to write an alignment function to get the
> indentation you want?

The following did work nicely (after I made c-langelem-2nd-col, by
copying and altering c-langelem-col as is obvious).  I'm not sure if it
is idiomatic or the cleanest solution, though (plus, my Elisp-fu is
poor).

--8<---------------cut here---------------start------------->8---
(defun glibcxx-style/line-up-struct (sym-form)
  "Lines up a class-open with its prior struct line"
  (if (not (eq 'class-open (c-langelem-sym sym-form)))
      nil
    (let ((col (c-langelem-2nd-col c-syntactic-element t)))
      (if col
	  (vector col)
	nil))))
--8<---------------cut here---------------end--------------->8---

... however, I noticed that class-close still anchors on the template
that precedes it, and seems to not have a 2nd-pos to play with, so the
above line-up fn, when set on class-open, produces:

--8<---------------cut here---------------start------------->8---
template<typename foo>
  struct f
  {
};
--8<---------------cut here---------------end--------------->8---

... so, we're getting quite close!

(It could be that I'm missing something, of course..)

Thanks again, have a lovely night (-:

>> > And of course, the manual and test programs will need amending, too.  ;-)
>
> They still need amending.  On running the test suite, there were 81 files
> where the new class-open syntactic symbol was different from the recorded
> old symbol.  So I've got 81 files to regenerate.  Fortunately, I can do
> this with a script, even if it will take me a couple of hours to write
> the script.
>
>> That sounds lovely - thanks in advance, if you do, indeed, decide to do
>> it.  For now, I can get this patch implemented with some manual
>> indenting.
>
>> Thanks for the quick fix, have a lovely day :-)
>
> Thank you indeed!  Have fun with the patch.
>
>
>
> diff -r 2760aada61fa cc-engine.el
> --- a/cc-engine.el	Sun Oct 15 10:44:22 2023 +0000
> +++ b/cc-engine.el	Thu Nov 16 18:58:33 2023 +0000
> @@ -12633,31 +12633,27 @@
>    (let ((open-brace (point)) kwd-start first-specifier-pos)
>      (c-syntactic-skip-backward c-block-prefix-charset limit t)
>  
> -    (when (and c-recognize-<>-arglists
> -	       (eq (char-before) ?>))
> -      ;; Could be at the end of a template arglist.
> -      (let ((c-parse-and-markup-<>-arglists t))
> -	(while (and
> -		(c-backward-<>-arglist nil limit)
> -		(progn
> -		  (c-syntactic-skip-backward c-block-prefix-charset limit t)
> -		  (eq (char-before) ?>))))))
> -
> -    ;; Skip back over noise clauses.
> -    (while (and
> -	    c-opt-cpp-prefix
> -	    (eq (char-before) ?\))
> -	    (let ((after-paren (point)))
> -	      (if (and (c-go-list-backward)
> -		       (progn (c-backward-syntactic-ws)
> -			      (c-simple-skip-symbol-backward))
> -		       (or (looking-at c-paren-nontype-key)
> -			   (looking-at c-noise-macro-with-parens-name-re)))
> -		  (progn
> -		    (c-syntactic-skip-backward c-block-prefix-charset limit t)
> -		    t)
> -		(goto-char after-paren)
> -		nil))))
> +    (while
> +	(or
> +	 ;; Could be after a template arglist....
> +	 (and c-recognize-<>-arglists
> +	      (eq (char-before) ?>)
> +	      (let ((c-parse-and-markup-<>-arglists t))
> +		(c-backward-<>-arglist nil limit)))
> +	 ;; .... or after a noise clause with parens.
> +	 (and c-opt-cpp-prefix
> +	      (let ((after-paren (point)))
> +		(if (eq (char-before) ?\))
> +		    (and
> +		     (c-go-list-backward)
> +		     (eq (char-after) ?\()
> +		     (progn (c-backward-syntactic-ws)
> +			    (c-simple-skip-symbol-backward))
> +		     (or (looking-at c-paren-nontype-key) ; e.g. __attribute__
> +			 (looking-at c-noise-macro-with-parens-name-re)))
> +		  (goto-char after-paren)
> +		  nil))))
> +      (c-syntactic-skip-backward c-block-prefix-charset limit t))
>  
>      ;; Note: Can't get bogus hits inside template arglists below since they
>      ;; have gotten paren syntax above.
> @@ -12667,10 +12663,18 @@
>  	   ;; The `c-decl-block-key' search continues from there since
>  	   ;; we know it can't match earlier.
>  	   (if goto-start
> -	       (when (c-syntactic-re-search-forward c-symbol-start
> -						    open-brace t t)
> -		 (goto-char (setq first-specifier-pos (match-beginning 0)))
> -		 t)
> +	       (progn
> +		 (while
> +		     (and
> +		      (c-syntactic-re-search-forward c-symbol-start
> +						     open-brace t t)
> +		      (goto-char (match-beginning 0))
> +		      (if (or (looking-at c-noise-macro-name-re)
> +			      (looking-at c-noise-macro-with-parens-name-re))
> +			  (c-forward-noise-clause)
> +			(setq first-specifier-pos (match-beginning 0))
> +			nil)))
> +		 first-specifier-pos)
>  	     t)
>  
>  	   (cond
> @@ -12739,34 +12743,39 @@
>  	    (goto-char first-specifier-pos)
>  
>  	    (while (< (point) kwd-start)
> -	      (if (looking-at c-symbol-key)
> -		  ;; Accept any plain symbol token on the ground that
> -		  ;; it's a specifier masked through a macro (just
> -		  ;; like `c-forward-decl-or-cast-1' skip forward over
> -		  ;; such tokens).
> -		  ;;
> -		  ;; Could be more restrictive wrt invalid keywords,
> -		  ;; but that'd only occur in invalid code so there's
> -		  ;; no use spending effort on it.
> -		  (let ((end (match-end 0))
> -			(kwd-sym (c-keyword-sym (match-string 0))))
> -		    (unless
> -			(and kwd-sym
> -			     ;; Moving over a protection kwd and the following
> -			     ;; ":" (in C++ Mode) to the next token could take
> -			     ;; us all the way up to `kwd-start', leaving us
> -			     ;; no chance to update `first-specifier-pos'.
> -			     (not (c-keyword-member kwd-sym 'c-protection-kwds))
> -			     (c-forward-keyword-clause 0))
> -		      (goto-char end)
> -		      (c-forward-syntactic-ws)))
> -
> +	      (cond
> +	       ((or (looking-at c-noise-macro-name-re)
> +		    (looking-at c-noise-macro-with-parens-name-re))
> +		(c-forward-noise-clause))
> +	       ((looking-at c-symbol-key)
> +		;; Accept any plain symbol token on the ground that
> +		;; it's a specifier masked through a macro (just
> +		;; like `c-forward-decl-or-cast-1' skips forward over
> +		;; such tokens).
> +		;;
> +		;; Could be more restrictive wrt invalid keywords,
> +		;; but that'd only occur in invalid code so there's
> +		;; no use spending effort on it.
> +		(let ((end (match-end 0))
> +		      (kwd-sym (c-keyword-sym (match-string 0))))
> +		  (unless
> +		      (and kwd-sym
> +			   ;; Moving over a protection kwd and the following
> +			   ;; ":" (in C++ Mode) to the next token could take
> +			   ;; us all the way up to `kwd-start', leaving us
> +			   ;; no chance to update `first-specifier-pos'.
> +			   (not (c-keyword-member kwd-sym 'c-protection-kwds))
> +			   (c-forward-keyword-clause 0))
> +		    (goto-char end)
> +		    (c-forward-syntactic-ws))))
> +
> +	       ((c-syntactic-re-search-forward c-symbol-start
> +					       kwd-start 'move t)
>  		;; Can't parse a declaration preamble and is still
>  		;; before `kwd-start'.  That means `first-specifier-pos'
>  		;; was in some earlier construct.  Search again.
> -		(if (c-syntactic-re-search-forward c-symbol-start
> -						   kwd-start 'move t)
> -		    (goto-char (setq first-specifier-pos (match-beginning 0)))
> +		(goto-char (setq first-specifier-pos (match-beginning 0))))
> +	       (t
>  		  ;; Got no preamble before the block declaration keyword.
>  		  (setq first-specifier-pos kwd-start))))
>  
> @@ -14727,7 +14736,10 @@
>  			    'lambda-intro-cont)))
>  	(goto-char (cdr placeholder))
>  	(back-to-indentation)
> -	(c-add-stmt-syntax tmpsymbol nil t
> +	(c-add-stmt-syntax tmpsymbol
> +			   (and (eq tmpsymbol 'class-open)
> +				(list (point)))
> +			   t
>  			   (c-most-enclosing-brace state-cache (point))
>  			   paren-state)
>  	(unless (eq (point) (cdr placeholder))
> @@ -14770,9 +14782,10 @@
>  	      (goto-char indent-point)
>  	      (skip-chars-forward " \t")
>  	      (and (eq (char-after) ?{)
> -		   (c-looking-at-decl-block t)
> +		   (setq tmp-pos (c-looking-at-decl-block t))
>  		   (setq placeholder (point))))
> -	    (c-add-syntax 'class-open placeholder))
> +	    (c-add-syntax 'class-open placeholder
> +			  (c-point 'boi tmp-pos)))
>  
>  	   ;; CASE 5A.3: brace list open
>  	   ((save-excursion
>
>
>> -- 
>> Arsen Arsenović


-- 
Arsen Arsenović
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Fri, 17 Nov 2023 12:10:02 GMT) Full text and rfc822 format available.

Message #26 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Arsen Arsenović <arsen <at> aarsen.me>
Cc: acm <at> muc.de, 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Fri, 17 Nov 2023 12:09:28 +0000
Hello, Arsen.

On Thu, Nov 16, 2023 at 21:29:29 +0100, Arsen Arsenović wrote:
> Hi Alan,

> Thanks for working on this.

> Alan Mackenzie <acm <at> muc.de> writes:

[ .... ]

> > That was a mistake - the second anchor point is needed on class-open
> > lines, not topmost-intro-cont ones.

> > I've coded up this patch, which I include below.  Actually, only the last
> > two smallish hunks of the patch are new, the rest is what you've seen
> > before, so it will be necessary to start from a clean copy of
> > cc-engine.el again.

> > The syntactical context of the HERE line (the opening brace of that
> > class) is now something like:

> >     ((class-open 76 107))

> > , where 76 is the position of the template keyword and 107 that of the
> > class keyword.  When there's no template, both of these anchor points are
> > the same.  Actually, that's not quite accurate: the 107 is the point
> > after the indentation of the line that class is on; it just seemed better
> > that way.

> This behavior seems reasonable to me at a glance and at a test.  I like
> the idea :-)

[ .... ]

> > So, again, please let me know how you get on with this patch.  Is the
> > extra anchor point sufficient to write an alignment function to get the
> > indentation you want?

> The following did work nicely (after I made c-langelem-2nd-col, by
> copying and altering c-langelem-col as is obvious).  I'm not sure if it
> is idiomatic or the cleanest solution, though (plus, my Elisp-fu is
> poor).

> --8<---------------cut here---------------start------------->8---
> (defun glibcxx-style/line-up-struct (sym-form)
>   "Lines up a class-open with its prior struct line"
>   (if (not (eq 'class-open (c-langelem-sym sym-form)))
>       nil
>     (let ((col (c-langelem-2nd-col c-syntactic-element t)))
>       (if col
> 	  (vector col)
> 	nil))))
> --8<---------------cut here---------------end--------------->8---

> ... however, I noticed that class-close still anchors on the template
> that precedes it, and seems to not have a 2nd-pos to play with, so the
> above line-up fn, when set on class-open, produces:

> --8<---------------cut here---------------start------------->8---
> template<typename foo>
>   struct f
>   {
> };
> --8<---------------cut here---------------end--------------->8---

Yes.  I should have noticed this myself.  :-(

> ... so, we're getting quite close!

So, please try out the new patch (below) which supplies the second anchor
point to class-close too.  The patch applies cleanly to the Emacs master
branch.  Again, please start off with a clean cc-engine.el before
applying the new patch, not the version with the previous patch applied.

[ .... ]


diff -r 2760aada61fa cc-engine.el
--- a/cc-engine.el	Sun Oct 15 10:44:22 2023 +0000
+++ b/cc-engine.el	Fri Nov 17 11:49:55 2023 +0000
@@ -12633,31 +12633,27 @@
   (let ((open-brace (point)) kwd-start first-specifier-pos)
     (c-syntactic-skip-backward c-block-prefix-charset limit t)
 
-    (when (and c-recognize-<>-arglists
-	       (eq (char-before) ?>))
-      ;; Could be at the end of a template arglist.
-      (let ((c-parse-and-markup-<>-arglists t))
-	(while (and
-		(c-backward-<>-arglist nil limit)
-		(progn
-		  (c-syntactic-skip-backward c-block-prefix-charset limit t)
-		  (eq (char-before) ?>))))))
-
-    ;; Skip back over noise clauses.
-    (while (and
-	    c-opt-cpp-prefix
-	    (eq (char-before) ?\))
-	    (let ((after-paren (point)))
-	      (if (and (c-go-list-backward)
-		       (progn (c-backward-syntactic-ws)
-			      (c-simple-skip-symbol-backward))
-		       (or (looking-at c-paren-nontype-key)
-			   (looking-at c-noise-macro-with-parens-name-re)))
-		  (progn
-		    (c-syntactic-skip-backward c-block-prefix-charset limit t)
-		    t)
-		(goto-char after-paren)
-		nil))))
+    (while
+	(or
+	 ;; Could be after a template arglist....
+	 (and c-recognize-<>-arglists
+	      (eq (char-before) ?>)
+	      (let ((c-parse-and-markup-<>-arglists t))
+		(c-backward-<>-arglist nil limit)))
+	 ;; .... or after a noise clause with parens.
+	 (and c-opt-cpp-prefix
+	      (let ((after-paren (point)))
+		(if (eq (char-before) ?\))
+		    (and
+		     (c-go-list-backward)
+		     (eq (char-after) ?\()
+		     (progn (c-backward-syntactic-ws)
+			    (c-simple-skip-symbol-backward))
+		     (or (looking-at c-paren-nontype-key) ; e.g. __attribute__
+			 (looking-at c-noise-macro-with-parens-name-re)))
+		  (goto-char after-paren)
+		  nil))))
+      (c-syntactic-skip-backward c-block-prefix-charset limit t))
 
     ;; Note: Can't get bogus hits inside template arglists below since they
     ;; have gotten paren syntax above.
@@ -12667,10 +12663,18 @@
 	   ;; The `c-decl-block-key' search continues from there since
 	   ;; we know it can't match earlier.
 	   (if goto-start
-	       (when (c-syntactic-re-search-forward c-symbol-start
-						    open-brace t t)
-		 (goto-char (setq first-specifier-pos (match-beginning 0)))
-		 t)
+	       (progn
+		 (while
+		     (and
+		      (c-syntactic-re-search-forward c-symbol-start
+						     open-brace t t)
+		      (goto-char (match-beginning 0))
+		      (if (or (looking-at c-noise-macro-name-re)
+			      (looking-at c-noise-macro-with-parens-name-re))
+			  (c-forward-noise-clause)
+			(setq first-specifier-pos (match-beginning 0))
+			nil)))
+		 first-specifier-pos)
 	     t)
 
 	   (cond
@@ -12739,34 +12743,39 @@
 	    (goto-char first-specifier-pos)
 
 	    (while (< (point) kwd-start)
-	      (if (looking-at c-symbol-key)
-		  ;; Accept any plain symbol token on the ground that
-		  ;; it's a specifier masked through a macro (just
-		  ;; like `c-forward-decl-or-cast-1' skip forward over
-		  ;; such tokens).
-		  ;;
-		  ;; Could be more restrictive wrt invalid keywords,
-		  ;; but that'd only occur in invalid code so there's
-		  ;; no use spending effort on it.
-		  (let ((end (match-end 0))
-			(kwd-sym (c-keyword-sym (match-string 0))))
-		    (unless
-			(and kwd-sym
-			     ;; Moving over a protection kwd and the following
-			     ;; ":" (in C++ Mode) to the next token could take
-			     ;; us all the way up to `kwd-start', leaving us
-			     ;; no chance to update `first-specifier-pos'.
-			     (not (c-keyword-member kwd-sym 'c-protection-kwds))
-			     (c-forward-keyword-clause 0))
-		      (goto-char end)
-		      (c-forward-syntactic-ws)))
-
+	      (cond
+	       ((or (looking-at c-noise-macro-name-re)
+		    (looking-at c-noise-macro-with-parens-name-re))
+		(c-forward-noise-clause))
+	       ((looking-at c-symbol-key)
+		;; Accept any plain symbol token on the ground that
+		;; it's a specifier masked through a macro (just
+		;; like `c-forward-decl-or-cast-1' skips forward over
+		;; such tokens).
+		;;
+		;; Could be more restrictive wrt invalid keywords,
+		;; but that'd only occur in invalid code so there's
+		;; no use spending effort on it.
+		(let ((end (match-end 0))
+		      (kwd-sym (c-keyword-sym (match-string 0))))
+		  (unless
+		      (and kwd-sym
+			   ;; Moving over a protection kwd and the following
+			   ;; ":" (in C++ Mode) to the next token could take
+			   ;; us all the way up to `kwd-start', leaving us
+			   ;; no chance to update `first-specifier-pos'.
+			   (not (c-keyword-member kwd-sym 'c-protection-kwds))
+			   (c-forward-keyword-clause 0))
+		    (goto-char end)
+		    (c-forward-syntactic-ws))))
+
+	       ((c-syntactic-re-search-forward c-symbol-start
+					       kwd-start 'move t)
 		;; Can't parse a declaration preamble and is still
 		;; before `kwd-start'.  That means `first-specifier-pos'
 		;; was in some earlier construct.  Search again.
-		(if (c-syntactic-re-search-forward c-symbol-start
-						   kwd-start 'move t)
-		    (goto-char (setq first-specifier-pos (match-beginning 0)))
+		(goto-char (setq first-specifier-pos (match-beginning 0))))
+	       (t
 		  ;; Got no preamble before the block declaration keyword.
 		  (setq first-specifier-pos kwd-start))))
 
@@ -14181,7 +14190,8 @@
 (defun c-add-class-syntax (symbol
 			   containing-decl-open
 			   containing-decl-start
-			   containing-decl-kwd)
+			   containing-decl-kwd
+			   &rest args)
   ;; The inclass and class-close syntactic symbols are added in
   ;; several places and some work is needed to fix everything.
   ;; Therefore it's collected here.
@@ -14196,7 +14206,7 @@
     ;; Ought to use `c-add-stmt-syntax' instead of backing up to boi
     ;; here, but we have to do like this for compatibility.
     (back-to-indentation)
-    (c-add-syntax symbol (point))
+    (apply #'c-add-syntax symbol (point) args)
     (if (and (c-keyword-member containing-decl-kwd
 			       'c-inexpr-class-kwds)
 	     (/= containing-decl-start (c-point 'boi containing-decl-start)))
@@ -14230,9 +14240,10 @@
        ;; CASE B.1: class-open
        ((save-excursion
 	  (and (eq (char-after) ?{)
-	       (c-looking-at-decl-block t)
+	       (setq placeholder (c-looking-at-decl-block t))
 	       (setq beg-of-same-or-containing-stmt (point))))
-	(c-add-syntax 'class-open beg-of-same-or-containing-stmt))
+	(c-add-syntax 'class-open beg-of-same-or-containing-stmt
+		      (c-point 'boi placeholder)))
 
        ;; CASE B.2: brace-list-open
        ((or (consp special-brace-list)
@@ -14727,7 +14738,10 @@
 			    'lambda-intro-cont)))
 	(goto-char (cdr placeholder))
 	(back-to-indentation)
-	(c-add-stmt-syntax tmpsymbol nil t
+	(c-add-stmt-syntax tmpsymbol
+			   (and (eq tmpsymbol 'class-open)
+				(list (point)))
+			   t
 			   (c-most-enclosing-brace state-cache (point))
 			   paren-state)
 	(unless (eq (point) (cdr placeholder))
@@ -14770,9 +14784,10 @@
 	      (goto-char indent-point)
 	      (skip-chars-forward " \t")
 	      (and (eq (char-after) ?{)
-		   (c-looking-at-decl-block t)
+		   (setq tmp-pos (c-looking-at-decl-block t))
 		   (setq placeholder (point))))
-	    (c-add-syntax 'class-open placeholder))
+	    (c-add-syntax 'class-open placeholder
+			  (c-point 'boi tmp-pos)))
 
 	   ;; CASE 5A.3: brace list open
 	   ((save-excursion
@@ -15170,10 +15185,14 @@
 	 ((and containing-sexp
 	       (eq char-after-ip ?})
 	       (eq containing-decl-open containing-sexp))
+	  (save-excursion
+	    (goto-char containing-decl-open)
+	    (setq tmp-pos (c-looking-at-decl-block t)))
 	  (c-add-class-syntax 'class-close
 			      containing-decl-open
 			      containing-decl-start
-			      containing-decl-kwd))
+			      containing-decl-kwd
+			      (c-point 'boi tmp-pos)))
 
 	 ;; CASE 5H: we could be looking at subsequent knr-argdecls
 	 ((and c-recognize-knr-p


> -- 
> Arsen Arsenović

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Fri, 17 Nov 2023 19:36:01 GMT) Full text and rfc822 format available.

Message #29 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Arsen Arsenović <arsen <at> aarsen.me>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Fri, 17 Nov 2023 20:16:31 +0100
[Message part 1 (text/plain, inline)]
Hi Alan,

Thanks (again!) for working on this.

Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Arsen.
>
> On Thu, Nov 16, 2023 at 21:29:29 +0100, Arsen Arsenović wrote:
>> Hi Alan,
>
>> Thanks for working on this.
>
>> Alan Mackenzie <acm <at> muc.de> writes:
>
> [ .... ]
>
>> > That was a mistake - the second anchor point is needed on class-open
>> > lines, not topmost-intro-cont ones.
>
>> > I've coded up this patch, which I include below.  Actually, only the last
>> > two smallish hunks of the patch are new, the rest is what you've seen
>> > before, so it will be necessary to start from a clean copy of
>> > cc-engine.el again.
>
>> > The syntactical context of the HERE line (the opening brace of that
>> > class) is now something like:
>
>> >     ((class-open 76 107))
>
>> > , where 76 is the position of the template keyword and 107 that of the
>> > class keyword.  When there's no template, both of these anchor points are
>> > the same.  Actually, that's not quite accurate: the 107 is the point
>> > after the indentation of the line that class is on; it just seemed better
>> > that way.
>
>> This behavior seems reasonable to me at a glance and at a test.  I like
>> the idea :-)
>
> [ .... ]
>
>> > So, again, please let me know how you get on with this patch.  Is the
>> > extra anchor point sufficient to write an alignment function to get the
>> > indentation you want?
>
>> The following did work nicely (after I made c-langelem-2nd-col, by
>> copying and altering c-langelem-col as is obvious).  I'm not sure if it
>> is idiomatic or the cleanest solution, though (plus, my Elisp-fu is
>> poor).
>
>> --8<---------------cut here---------------start------------->8---
>> (defun glibcxx-style/line-up-struct (sym-form)
>>   "Lines up a class-open with its prior struct line"
>>   (if (not (eq 'class-open (c-langelem-sym sym-form)))
>>       nil
>>     (let ((col (c-langelem-2nd-col c-syntactic-element t)))
>>       (if col
>> 	  (vector col)
>> 	nil))))
>> --8<---------------cut here---------------end--------------->8---
>
>> ... however, I noticed that class-close still anchors on the template
>> that precedes it, and seems to not have a 2nd-pos to play with, so the
>> above line-up fn, when set on class-open, produces:
>
>> --8<---------------cut here---------------start------------->8---
>> template<typename foo>
>>   struct f
>>   {
>> };
>> --8<---------------cut here---------------end--------------->8---
>
> Yes.  I should have noticed this myself.  :-(
>
>> ... so, we're getting quite close!
>
> So, please try out the new patch (below) which supplies the second anchor
> point to class-close too.  The patch applies cleanly to the Emacs master
> branch.  Again, please start off with a clean cc-engine.el before
> applying the new patch, not the version with the previous patch applied.

Excellent!  The following did it:

--8<---------------cut here---------------start------------->8---
(defun glibcxx-style/line-up-struct (sym-form)
  "Lines up a class-open/close with its prior struct line"
  (if (not (seq-contains-p '(class-open class-close)
			   (c-langelem-sym sym-form)))
      nil
    (let ((col (c-langelem-2nd-col c-syntactic-element t)))
      (if col
	  (vector col)
	nil))))
--8<---------------cut here---------------end--------------->8---

Again, unsure if it is the most elegant solution, or even if it's a good
one.  But it did work!

I've copied c-langelem-2nd-col again to do the above.  Is that helper
intentionally omitted?  Is there perhaps a more idiomatic solution?

In any case, I'll be sure to use this as soon as it lands in the Emacs
VCS.

Thanks again, have a lovely night!
-- 
Arsen Arsenović
[signature.asc (application/pgp-signature, inline)]

Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Fri, 17 Nov 2023 20:19:01 GMT) Full text and rfc822 format available.

Message #32 received at 66911 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Arsen Arsenović <arsen <at> aarsen.me>
Cc: acm <at> muc.de, 66911 <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Fri, 17 Nov 2023 20:17:47 +0000
Hello, Arsen.

On Fri, Nov 17, 2023 at 20:16:31 +0100, Arsen Arsenović wrote:
> Hi Alan,

> Thanks (again!) for working on this.

Appreciated!

> Alan Mackenzie <acm <at> muc.de> writes:

> > On Thu, Nov 16, 2023 at 21:29:29 +0100, Arsen Arsenović wrote:

> >> The following did work nicely (after I made c-langelem-2nd-col, by
> >> copying and altering c-langelem-col as is obvious).  I'm not sure if it
> >> is idiomatic or the cleanest solution, though (plus, my Elisp-fu is
> >> poor).

I think c-langelem-2nd-col is as good as anything else.  It's better to
have it as a function than open coding it everywhere it's used.

> >> --8<---------------cut here---------------start------------->8---
> >> (defun glibcxx-style/line-up-struct (sym-form)
> >>   "Lines up a class-open with its prior struct line"
> >>   (if (not (eq 'class-open (c-langelem-sym sym-form)))
> >>       nil
> >>     (let ((col (c-langelem-2nd-col c-syntactic-element t)))
> >>       (if col
> >> 	  (vector col)
> >> 	nil))))
> >> --8<---------------cut here---------------end--------------->8---

> >> ... however, I noticed that class-close still anchors on the template
> >> that precedes it, and seems to not have a 2nd-pos to play with, so the
> >> above line-up fn, when set on class-open, produces:

> >> --8<---------------cut here---------------start------------->8---
> >> template<typename foo>
> >>   struct f
> >>   {
> >> };
> >> --8<---------------cut here---------------end--------------->8---

> > Yes.  I should have noticed this myself.  :-(

> >> ... so, we're getting quite close!

> > So, please try out the new patch (below) which supplies the second anchor
> > point to class-close too.  The patch applies cleanly to the Emacs master
> > branch.  Again, please start off with a clean cc-engine.el before
> > applying the new patch, not the version with the previous patch applied.

> Excellent!  The following did it:

> --8<---------------cut here---------------start------------->8---
> (defun glibcxx-style/line-up-struct (sym-form)
>   "Lines up a class-open/close with its prior struct line"
>   (if (not (seq-contains-p '(class-open class-close)
> 			   (c-langelem-sym sym-form)))
>       nil
>     (let ((col (c-langelem-2nd-col c-syntactic-element t)))
>       (if col
> 	  (vector col)
> 	nil))))
> --8<---------------cut here---------------end--------------->8---

> Again, unsure if it is the most elegant solution, or even if it's a good
> one.  But it did work!

Working is rather more important than elegance.  ;-)

> I've copied c-langelem-2nd-col again to do the above.  Is that helper
> intentionally omitted?  Is there perhaps a more idiomatic solution?

I don't think so.

> In any case, I'll be sure to use this as soon as it lands in the Emacs
> VCS.

This might take a few days - I've still got to amend the (stand alone CC
Mode) test suite and the documentation.  And I've got quite a lot on in
Real Life in the next few days.

> Thanks again, have a lovely night!

Thanks.  You too!

> -- 
> Arsen Arsenović

-- 
Alan Mackenzie (Nuremberg, Germany).




Reply sent to Alan Mackenzie <acm <at> muc.de>:
You have taken responsibility. (Fri, 24 Nov 2023 10:15:03 GMT) Full text and rfc822 format available.

Notification sent to Arsen Arsenović <arsen <at> aarsen.me>:
bug acknowledged by developer. (Fri, 24 Nov 2023 10:15:03 GMT) Full text and rfc822 format available.

Message #37 received at 66911-done <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Arsen Arsenović <arsen <at> aarsen.me>
Cc: acm <at> muc.de, 66911-done <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Fri, 24 Nov 2023 10:14:45 +0000
Hello, Arsen.

On Fri, Nov 17, 2023 at 20:17:47 +0000, Alan Mackenzie wrote:
> On Fri, Nov 17, 2023 at 20:16:31 +0100, Arsen Arsenović wrote:
> > Hi Alan,

[ .... ]

> > > So, please try out the new patch (below) which supplies the second anchor
> > > point to class-close too.  The patch applies cleanly to the Emacs master
> > > branch.  Again, please start off with a clean cc-engine.el before
> > > applying the new patch, not the version with the previous patch applied.

[ .... ]

> > In any case, I'll be sure to use this as soon as it lands in the Emacs
> > VCS.

> This might take a few days - I've still got to amend the (stand alone CC
> Mode) test suite and the documentation.  And I've got quite a lot on in
> Real Life in the next few days.

I've now amended the test suite and cc-mode.texi.  I've committed the
enhancement to all the usual places, including the Emacs master branch,
so I'm closing the bug with this post.

> > -- 
> > Arsen Arsenović

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#66911; Package cc-mode. (Fri, 24 Nov 2023 18:13:01 GMT) Full text and rfc822 format available.

Message #40 received at 66911-done <at> debbugs.gnu.org (full text, mbox):

From: Arsen Arsenović <arsen <at> aarsen.me>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 66911-done <at> debbugs.gnu.org
Subject: Re: bug#66911: CC Mode 5.35.2 (C++//l); Noise macro being taken as
 anchor to class-open
Date: Fri, 24 Nov 2023 19:09:44 +0100
[Message part 1 (text/plain, inline)]
Hi Alan,

Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Arsen.
>
> On Fri, Nov 17, 2023 at 20:17:47 +0000, Alan Mackenzie wrote:
>> On Fri, Nov 17, 2023 at 20:16:31 +0100, Arsen Arsenović wrote:
>> > Hi Alan,
>
> [ .... ]
>
>> > > So, please try out the new patch (below) which supplies the second anchor
>> > > point to class-close too.  The patch applies cleanly to the Emacs master
>> > > branch.  Again, please start off with a clean cc-engine.el before
>> > > applying the new patch, not the version with the previous patch applied.
>
> [ .... ]
>
>> > In any case, I'll be sure to use this as soon as it lands in the Emacs
>> > VCS.
>
>> This might take a few days - I've still got to amend the (stand alone CC
>> Mode) test suite and the documentation.  And I've got quite a lot on in
>> Real Life in the next few days.
>
> I've now amended the test suite and cc-mode.texi.  I've committed the
> enhancement to all the usual places, including the Emacs master branch,
> so I'm closing the bug with this post.

Thank you very much!  I shall update Emacs today, then.

Would you be interested in adding the GNU-derived libstdc++ style into
CC-mode proper?  After I give it a further test-drive and possibly more
bug squashing.

Have a lovely night!

>> > -- 
>> > Arsen Arsenović


-- 
Arsen Arsenović
[signature.asc (application/pgp-signature, inline)]

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sat, 23 Dec 2023 12:24:05 GMT) Full text and rfc822 format available.

This bug report was last modified 1 year and 174 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.