[gcc r12-2766] libstdc++: Move attributes that follow requires-clauses [PR101782]

Jonathan Wakely redi@gcc.gnu.org
Thu Aug 5 14:17:29 GMT 2021


https://gcc.gnu.org/g:7b1de3eb9ed3f8dde54732d88520292c5ad1157d

commit r12-2766-g7b1de3eb9ed3f8dde54732d88520292c5ad1157d
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Aug 5 13:34:00 2021 +0100

    libstdc++: Move attributes that follow requires-clauses [PR101782]
    
    As explained in the PR, the grammar in the Concepts TS means that a [
    token following a requires-clause is parsed as part of the
    logical-or-expression rather than the start of an attribute. That makes
    the following ill-formed when using -fconcepts-ts:
    
      template<typename T> requires foo<T> [[nodiscard]] int f(T);
    
    This change moves all attributes that follow a requires-clause to the
    end of the function declarator.
    
    Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/101782
            * include/bits/ranges_base.h (ranges::begin, ranges::end)
            (ranges::rbegin, ranges::rend, ranges::size, ranges::ssize)
            (ranges::empty, ranges::data): Move attribute to the end of
            the declarator.
            * include/bits/stl_iterator.h (__gnu_cxx::__normal_iterator)
            (common_iterator): Likewise for non-member operator functions.
            * include/std/ranges (views::all, views::filter)
            (views::transform, views::take, views::take_while, views::drop)
            (views::drop_while, views::join, views::lazy_split)
            (views::split, views::counted, views::common, views::reverse)
            (views::elements): Likewise.
            * testsuite/std/ranges/access/101782.cc: New test.

Diff:
---
 libstdc++-v3/include/bits/ranges_base.h            | 16 ++++++-------
 libstdc++-v3/include/bits/stl_iterator.h           | 10 ++++----
 libstdc++-v3/include/std/ranges                    | 28 +++++++++++-----------
 libstdc++-v3/testsuite/std/ranges/access/101782.cc |  9 +++++++
 4 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h
index 614b6edf9df..1dac9680b4f 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -110,9 +110,9 @@ namespace ranges
       template<__maybe_borrowed_range _Tp>
 	requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp>
 	  || __adl_begin<_Tp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
+	[[nodiscard]]
 	{
 	  if constexpr (is_array_v<remove_reference_t<_Tp>>)
 	    {
@@ -162,9 +162,9 @@ namespace ranges
       template<__maybe_borrowed_range _Tp>
 	requires is_bounded_array_v<remove_reference_t<_Tp>>
 	  || __member_end<_Tp> || __adl_end<_Tp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
+	[[nodiscard]]
 	{
 	  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
 	    {
@@ -267,10 +267,10 @@ namespace ranges
     public:
       template<__maybe_borrowed_range _Tp>
 	requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Tp&& __t) const
 	noexcept(_S_noexcept<_Tp&>())
+	[[nodiscard]]
 	{
 	  if constexpr (__member_rbegin<_Tp>)
 	    return __t.rbegin();
@@ -326,10 +326,10 @@ namespace ranges
     public:
       template<__maybe_borrowed_range _Tp>
 	requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Tp&& __t) const
 	noexcept(_S_noexcept<_Tp&>())
+	[[nodiscard]]
 	{
 	  if constexpr (__member_rend<_Tp>)
 	    return __t.rend();
@@ -416,9 +416,9 @@ namespace ranges
       template<typename _Tp>
 	requires is_bounded_array_v<remove_reference_t<_Tp>>
 	  || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
+	[[nodiscard]]
 	{
 	  if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>)
 	    return extent_v<remove_reference_t<_Tp>>;
@@ -437,9 +437,9 @@ namespace ranges
       // 3403. Domain of ranges::ssize(E) doesn't match ranges::size(E)
       template<typename _Tp>
 	requires requires (_Tp& __t) { _Size{}(__t); }
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Tp&& __t) const noexcept(noexcept(_Size{}(__t)))
+	[[nodiscard]]
 	{
 	  auto __size = _Size{}(__t);
 	  using __size_type = decltype(__size);
@@ -497,9 +497,9 @@ namespace ranges
       template<typename _Tp>
 	requires __member_empty<_Tp> || __size0_empty<_Tp>
 	  || __eq_iter_empty<_Tp>
-	[[nodiscard]]
 	constexpr bool
 	operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>())
+	[[nodiscard]]
 	{
 	  if constexpr (__member_empty<_Tp>)
 	    return bool(__t.empty());
@@ -539,9 +539,9 @@ namespace ranges
     public:
       template<__maybe_borrowed_range _Tp>
 	requires __member_data<_Tp> || __begin_data<_Tp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>())
+	[[nodiscard]]
 	{
 	  if constexpr (__member_data<_Tp>)
 	    return __t.data();
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index 3773d600b8f..053ae41e9c3 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -1120,19 +1120,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _IteratorL, typename _IteratorR, typename _Container>
     requires requires (_IteratorL __lhs, _IteratorR __rhs)
     { { __lhs == __rhs } -> std::convertible_to<bool>; }
-    [[nodiscard]]
     constexpr bool
     operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
 	       const __normal_iterator<_IteratorR, _Container>& __rhs)
     noexcept(noexcept(__lhs.base() == __rhs.base()))
+    [[nodiscard]]
     { return __lhs.base() == __rhs.base(); }
 
   template<typename _IteratorL, typename _IteratorR, typename _Container>
-    [[nodiscard]]
     constexpr std::__detail::__synth3way_t<_IteratorR, _IteratorL>
     operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs,
 		const __normal_iterator<_IteratorR, _Container>& __rhs)
     noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base())))
+    [[nodiscard]]
     { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); }
 #else
    // Forward iterator requirements
@@ -1984,10 +1984,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     template<typename _It2, sentinel_for<_It> _Sent2>
       requires sentinel_for<_Sent, _It2>
-      [[nodiscard]]
       friend bool
       operator==(const common_iterator& __x,
 		 const common_iterator<_It2, _Sent2>& __y)
+      [[nodiscard]]
       {
 	switch(__x._M_index << 2 | __y._M_index)
 	  {
@@ -2007,10 +2007,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     template<typename _It2, sentinel_for<_It> _Sent2>
       requires sentinel_for<_Sent, _It2> && equality_comparable_with<_It, _It2>
-      [[nodiscard]]
       friend bool
       operator==(const common_iterator& __x,
 		 const common_iterator<_It2, _Sent2>& __y)
+      [[nodiscard]]
       {
 	switch(__x._M_index << 2 | __y._M_index)
 	  {
@@ -2031,10 +2031,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     template<sized_sentinel_for<_It> _It2, sized_sentinel_for<_It> _Sent2>
       requires sized_sentinel_for<_Sent, _It2>
-      [[nodiscard]]
       friend iter_difference_t<_It2>
       operator-(const common_iterator& __x,
 		const common_iterator<_It2, _Sent2>& __y)
+      [[nodiscard]]
       {
 	switch(__x._M_index << 2 | __y._M_index)
 	  {
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 03a3778bb52..71b7dc7d295 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1126,10 +1126,10 @@ namespace views::__adaptor
 	requires view<decay_t<_Range>>
 	  || __detail::__can_ref_view<_Range>
 	  || __detail::__can_subrange<_Range>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r) const
 	noexcept(_S_noexcept<_Range>())
+	[[nodiscard]]
 	{
 	  if constexpr (view<decay_t<_Range>>)
 	    return std::forward<_Range>(__r);
@@ -1553,9 +1553,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range, typename _Pred>
 	requires __detail::__can_filter_view<_Range, _Pred>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r, _Pred&& __p) const
+	[[nodiscard]]
 	{
 	  return filter_view(std::forward<_Range>(__r), std::forward<_Pred>(__p));
 	}
@@ -1931,9 +1931,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range, typename _Fp>
 	requires __detail::__can_transform_view<_Range, _Fp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r, _Fp&& __f) const
+	[[nodiscard]]
 	{
 	  return transform_view(std::forward<_Range>(__r), std::forward<_Fp>(__f));
 	}
@@ -2113,9 +2113,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range, typename _Tp>
 	requires __detail::__can_take_view<_Range, _Tp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r, _Tp&& __n) const
+	[[nodiscard]]
 	{
 	  return take_view(std::forward<_Range>(__r), std::forward<_Tp>(__n));
 	}
@@ -2241,9 +2241,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range, typename _Pred>
 	requires __detail::__can_take_while_view<_Range, _Pred>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r, _Pred&& __p) const
+	[[nodiscard]]
 	{
 	  return take_while_view(std::forward<_Range>(__r), std::forward<_Pred>(__p));
 	}
@@ -2362,9 +2362,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range, typename _Tp>
 	requires __detail::__can_drop_view<_Range, _Tp>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r, _Tp&& __n) const
+	[[nodiscard]]
 	{
 	  return drop_view(std::forward<_Range>(__r), std::forward<_Tp>(__n));
 	}
@@ -2451,9 +2451,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range, typename _Pred>
 	requires __detail::__can_drop_while_view<_Range, _Pred>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r, _Pred&& __p) const
+	[[nodiscard]]
 	{
 	  return drop_while_view(std::forward<_Range>(__r),
 				 std::forward<_Pred>(__p));
@@ -2814,9 +2814,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range>
 	requires __detail::__can_join_view<_Range>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r) const
+	[[nodiscard]]
 	{
 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
 	  // 3474. Nesting join_views is broken because of CTAD
@@ -3266,9 +3266,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range, typename _Pattern>
 	requires __detail::__can_lazy_split_view<_Range, _Pattern>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r, _Pattern&& __f) const
+	[[nodiscard]]
 	{
 	  return lazy_split_view(std::forward<_Range>(__r), std::forward<_Pattern>(__f));
 	}
@@ -3475,9 +3475,9 @@ namespace views::__adaptor
     {
       template<viewable_range _Range, typename _Pattern>
 	requires __detail::__can_split_view<_Range, _Pattern>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r, _Pattern&& __f) const
+	[[nodiscard]]
 	{
 	  return split_view(std::forward<_Range>(__r), std::forward<_Pattern>(__f));
 	}
@@ -3497,9 +3497,9 @@ namespace views::__adaptor
     struct _Counted
     {
       template<input_or_output_iterator _Iter>
-      [[nodiscard]]
       constexpr auto
       operator()(_Iter __i, iter_difference_t<_Iter> __n) const
+      [[nodiscard]]
       {
 	if constexpr (random_access_iterator<_Iter>)
 	  return subrange(__i, __i + __n);
@@ -3619,9 +3619,9 @@ namespace views::__adaptor
       template<viewable_range _Range>
 	requires __detail::__already_common<_Range>
 	  || __detail::__can_common_view<_Range>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r) const
+	[[nodiscard]]
 	{
 	  if constexpr (__detail::__already_common<_Range>)
 	    return views::all(std::forward<_Range>(__r));
@@ -3742,9 +3742,9 @@ namespace views::__adaptor
 	requires __detail::__is_reverse_view<remove_cvref_t<_Range>>
 	  || __detail::__is_reversible_subrange<remove_cvref_t<_Range>>
 	  || __detail::__can_reverse_view<_Range>
-	[[nodiscard]]
 	constexpr auto
 	operator()(_Range&& __r) const
+	[[nodiscard]]
 	{
 	  using _Tp = remove_cvref_t<_Range>;
 	  if constexpr (__detail::__is_reverse_view<_Tp>)
@@ -4141,9 +4141,9 @@ namespace views::__adaptor
       {
 	template<viewable_range _Range>
 	  requires __detail::__can_elements_view<_Nm, _Range>
-	  [[nodiscard]]
 	  constexpr auto
 	  operator()(_Range&& __r) const
+	  [[nodiscard]]
 	  {
 	    return elements_view<all_t<_Range>, _Nm>{std::forward<_Range>(__r)};
 	  }
diff --git a/libstdc++-v3/testsuite/std/ranges/access/101782.cc b/libstdc++-v3/testsuite/std/ranges/access/101782.cc
new file mode 100644
index 00000000000..abb0c8dab0f
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/access/101782.cc
@@ -0,0 +1,9 @@
+// { dg-options "-std=gnu++20 -fconcepts-ts" }
+// { dg-do compile { target c++20 } }
+
+// PR testsuite/101782
+// attribute-specifier-seq cannot follow requires-clause with -fconcepts-ts
+
+#include <algorithm>
+#include <iterator>
+#include <ranges>


More information about the Libstdc++-cvs mailing list