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
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.Arsen Arsenović <arsen <at> aarsen.me>
: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ć
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).
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)]
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).
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)]
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).
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)]
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).
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)]
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).
Alan Mackenzie <acm <at> muc.de>
:Arsen Arsenović <arsen <at> aarsen.me>
: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).
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)]
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.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.