GNU bug report logs - #73340
CC Mode 5.35.2 (C++//l); inline-open lacks associated position, making it hard to express the libstdc++ indent style

Previous Next

Package: cc-mode;

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

Date: Wed, 18 Sep 2024 23:49:01 UTC

Severity: normal

To reply to this bug, email your comments to 73340 AT debbugs.gnu.org.

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#73340; Package cc-mode. (Wed, 18 Sep 2024 23:49:01 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. (Wed, 18 Sep 2024 23:49:01 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); inline-open lacks associated position,
 making it hard to express the libstdc++ indent style
Date: Thu, 19 Sep 2024 01:48:01 +0200
Package: cc-mode

Hi!

In the following snippet, which is intentionally misindented on the
template line:

  struct s
  {
      template<typename>
      void
      f()
    {}
  };

CC-mode seems to not be able to deduce that {} should line up with f().

This is troublesome in a real mode example of libstdc++, whose code
style mandates that templates receive an extra level of indentation:

  template<>
    void
    f()
    {
      // this is OK
    }
  
  struct s
  {
    template<>
      void
      f()
    {
      // this is not OK
    }
  };

Now, this style required some special handling so far, of course:

--8<---------------cut here---------------start------------->8---
(defun glibcxx/lineup-template-cont (sym-form)
  "Indents sym-forms with a single level if they are a continuation of a
template.  Implements rules 4 and 5 (Template class indentation,
Template function indentation)."
  (save-excursion
      (goto-char (c-langelem-pos sym-form))
      (if (looking-at-p "\\<template\\>")
          '+
        nil)))

(defun glibcxx/2nd-col ()
  "Returns the second positions column from the current `c-langelem-sym'."
  (save-excursion
    (let ((pos (c-langelem-2nd-pos c-syntactic-element)))
      (if (not pos)
          nil
        (goto-char pos)
        (current-column)))))

(defun glibcxx/lineup-class-open-close (sym-form)
  "Indents class-open/class-close lines with their corresponding class/struct
lines."
  (if (not (seq-contains-p '(class-open class-close)
                           (c-langelem-sym sym-form)))
      nil
    (let ((col (glibcxx/2nd-col)))
      (if col
          (vector col)
        nil))))

(defconst glibcxx/cc-style
  '("gnu"
    (c-offsets-alist . ((topmost-intro-cont
                         . (first glibcxx/lineup-template-cont
                                  c-lineup-topmost-intro-cont
                                  c-lineup-gnu-DEFUN-intro-cont))
                        (defun-open . glibcxx/lineup-template-cont)
                        (class-open . glibcxx/lineup-class-open-close)
                        (class-close . glibcxx/lineup-class-open-close)
                        ;; 07. Member initialization lists
                        (member-init-intro . 0))))
  "Code style used by the GNU C++ Standard Library")
--8<---------------cut here---------------end--------------->8---

... but the trouble arose when I went to add the same styling to inline
functions, since inline-open does not have a position relative to the
template; for s::f above, syntactic analysis gives us: ((inclass 61)
(inline-open)).  As a result, the definition must be relative to the
class definition itself, but it is not in the case of member templates.

The full libstdc++ code style is presented here:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/source_code_style.html
I'd also like to ask if you'd like to have it in-tree (I'd be happy to
work on it).  Really, the code style is a bit strange IMO, but it is
what it is.

Thank you in advance, and sorry to bother you again so soon :-/

Have a lovely day.

Emacs  : GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.42, cairo version 1.18.0)
 of 2024-08-31
Package: CC Mode 5.35.2 (C++//l)
Buffer Style: glibcxx
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 . 0)
		   (annotation-var-cont . +)
		   (annotation-top-cont . 0)
		   (constraint-cont . +)
		   (topmost-intro . 0)
		   (knr-argdecl . 0)
		   (func-decl-cont . +)
		   (inline-close . 0)
		   (class-close . glibcxx/lineup-class-open-close)
		   (class-open . glibcxx/lineup-class-open-close)
		   (defun-block-intro . +)
		   (defun-close . 0)
		   (defun-open . glibcxx/lineup-template-cont)
		   (c . c-lineup-C-comments)
		   (string . c-lineup-dont-change)
		   (topmost-intro-cont first glibcxx/lineup-template-cont
 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ć




This bug report was last modified 269 days ago.

Previous Next


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