Subject: bug#62386: CC Mode 5.35.2 (C++//l); C++ concept indentation

From: Michael Welsh Duggan <[email-masked]>
Date: Fri, 24 Mar 2023 14:58:28 -0400

Alan Mackenzie <[email-masked]> writes:

> On Wed, Mar 22, 2023 at 11:58:32 -0400, Michael Welsh Duggan wrote:
>> Package: cc-mode
>
>> Given a concept definition like:
>
>>     template <typename T>
>>     concept Foo =
>>       Bar<T>
>>       && requires (T t) {
>>         { t + t } -> std::same_as<T>;
>>       }
>>       && something_else;
>
>> This is how it actually indents in cc-mode:
>
>>     template <typename T>
>>     concept Foo =
>>     Bar<T>
>>       && requires (T t) {
>>       { t + t } -> std::same_as<T>;
>>     }
>>       && something_else;
>
>> I would expect "Bar<T>" to be statement-cont, but it is
>> topmost-intro-cont instead.  The indentation of "{ t + t }" isn't offset
>> properly with respect to the "requires" clause, and the closing brace is
>> way out of line.

[...]

> I've made an attempt to improve the indentation of code like your test
> case.  Would you please try it out and let me know how well it solves
> the problem.  Thanks!

Better for that test case and a few others.  Here's a few test outliers
as indented by cc:

template <typename T>
concept Foo2 =
requires (T t) {
  *t -> std::same_as<int>; 
  *(t + t) -> std::same_as<int>; 
};
  
template <typename T>
concept Foo5 = 
  Foo<T>
  && requires (T t)
{
    { t++; }
  };

and how I would expect them to be indented:

template <typename T>
concept Foo2 =
  requires (T t) {
    *t -> std::same_as<int>; 
    *(t + t) -> std::same_as<int>; 
  };
  
template <typename T>
concept Foo5 = 
  Foo<T>
  && requires (T t)
  {
    { t++; }
  };

Here's some requires clause cases outside of concepts:

template <typename T>
requires Bar<T>
&& Baz<T>
int foo();

template <typename T>
requires 
(requires (T t) { ++t; }
&& Baz<T>)
int foo();

and how I would expect them to be indented:

template <typename T>
requires Bar<T>
  && Baz<T>
int foo();

template <typename T>
requires 
  (requires (T t) { ++t; }
   && Baz<T>)
int foo();

The latter of these is especially interesting because TAB on the "&&
Baz<T>)" section causes an "End of buffer" signal.

-- 
Michael Welsh Duggan
([email-masked])