https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108490

--- Comment #8 from Jonathan Wakely <redi at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #5)
> (In reply to Jonathan Wakely from comment #2)
> > Yes. The attribute has to be there, so it's a Circle bug if it doesn't
> > support that grammar.
> 
> Why can't it be before the friend specifier?
>     template<typename _It2, sentinel_for<_It> _Sent2>
>       requires sentinel_for<_Sent, _It2>
>       [[nodiscard]] friend constexpr bool
>       operator== (const common_iterator& __x,
>                   const common_iterator<_It2, _Sent2>& __y)
>     {
>       ...
>     }
> I mean, at least
> struct S
> {
>   template <typename T>
>   friend constexpr bool foo [[nodiscard]] (const S &, const T &) { return
> true; }
>   template <typename T>
>   [[nodiscard]] friend constexpr bool bar (const S &, const T &) { return
> true; }

The problem is an ambiguity in the grammar for the requires-clause, and this
example doesn't have any requires-clause.


Try:

  template <typename T> requires C<T>
  [[nodiscard]] friend constexpr bool bar (const S &, const T &) { return true;
}

And then compile with -fconcepts-ts

f.cc:7:3: error: two consecutive '[' shall only introduce an attribute before
'[' token
    7 |   [[nodiscard]] friend constexpr bool bar (const S &, const T &) {
return true; }
      |   ^

See PR101782 where you figured out the problem in the grammar :-)

The libstdc++ code is not written that way because I *like* putting the
attribute in that position, but because it's necessary. And it's valid C++, so
this is a Circle bug.

Reply via email to