Subject: bug#72695: closed (Re: bug#72695: CC Mode 5.35.2 (C++//l); c++-mode misindents 'if constexpr' inside lambdas)

From: [email-masked] (GNU bug Tracking System)
Date: Sat, 28 Sep 2024 10:45:02 +0000

Your bug report

#72695: CC Mode 5.35.2 (C++//l); c++-mode misindents 'if constexpr' inside lambdas

which was filed against the cc-mode package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
72695: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=72695
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#72695: CC Mode 5.35.2 (C++//l); c++-mode misindents 'if constexpr' inside lambdas
From: Alan Mackenzie <[email-masked]>
To: Arsen Arsenović <[email-masked]>
Cc: [email-masked], [email-masked]
Date: Sat, 28 Sep 2024 10:43:55 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

Bug#72695 has been fixed.  Closing.

-- 
Alan Mackenzie (Nuremberg, Germany).

Subject: CC Mode 5.35.2 (C++//l); c++-mode misindents 'if constexpr' inside lambdas
From: Arsen Arsenović <[email-masked]>
To: [email-masked]
Date: Sun, 18 Aug 2024 11:50:32 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

Package: cc-mode

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

CC-mode appears to misindent the following C++ snippet:

  void f()
  {
    auto data_printer = [] <typename T>
      (const T& data)
      {
        if constexpr (true)
        {
          if constexpr (std::same_as<T, std::string>)
          std::println (" data: \"{}\"", data);
          else
            std::println (" data: {}", data);
        }
        else
          std::println ("");
      };
  
    if constexpr (false)
      {
        foo ();
      }
  }

This example is supposed to be formatted in accordance to the default
GNU style, but the 'if constexpr' in the lambda expression are
misindented.

This might be the case because the inline-open of the lambda gets
mis-interpreted as statement-cont, so the statements in the body are
indented as brace-list-intro and brace-entry-open rather than
statement-block-intro and substatement-open.

WRT lambda indentation generally, CC-mode appears to format lambdas in
GNU style so that their '{' aligns with their '[' (i.e. aligns their
compound-statement with their lambda-introducer per ISO parlance).
Maybe we should consider indenting them less.  For instance, that
indentation leads to:

  std::visit ([] <typename T>
              (const T& data)
              {
                if constexpr (!std::same_as<T, std::monostate>)
                  {
                    if constexpr (std::same_as<T, std::string>)
                      std::println (" data: \"{}\"", data);
                    else
                      std::println (" data: {}", data);
                  }
                else
                  std::println ("");
              }, tok.data);

... which is /really/ aggressive.  Maybe it'd be better to do something
like:

  std::visit ([]
    (args)
    {
      body
    },
    visit-args-cont);

I realize this is a bit inconsistent with the rest of the style, but
given that placing the introducer (and generally function arguments) on
a new line does not work in the GNU C/++ style as it does in Lisp:

  function_name (
                 arg1,
                 arg2);

... versus:

  (function-name
   arg1
   arg2)

Anyway, thanks in advance!

Have a most 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-13
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ć