commit 7b1de3eb9ed3f8dde54732d88520292c5ad1157d Author: Jonathan Wakely Date: Thu Aug 5 13:34:00 2021 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 requires foo [[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 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 --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> || __member_begin<_Tp> || __adl_begin<_Tp> - [[nodiscard]] constexpr auto operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + [[nodiscard]] { if constexpr (is_array_v>) { @@ -162,9 +162,9 @@ namespace ranges template<__maybe_borrowed_range _Tp> requires is_bounded_array_v> || __member_end<_Tp> || __adl_end<_Tp> - [[nodiscard]] constexpr auto operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + [[nodiscard]] { if constexpr (is_bounded_array_v>) { @@ -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 requires is_bounded_array_v> || __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>) return extent_v>; @@ -437,9 +437,9 @@ namespace ranges // 3403. Domain of ranges::ssize(E) doesn't match ranges::size(E) template 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 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 requires requires (_IteratorL __lhs, _IteratorR __rhs) { { __lhs == __rhs } -> std::convertible_to; } - [[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 - [[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 _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 _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 _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> || __detail::__can_ref_view<_Range> || __detail::__can_subrange<_Range> - [[nodiscard]] constexpr auto operator()(_Range&& __r) const noexcept(_S_noexcept<_Range>()) + [[nodiscard]] { if constexpr (view>) return std::forward<_Range>(__r); @@ -1553,9 +1553,9 @@ namespace views::__adaptor { template 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 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 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 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 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 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 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 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 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 - [[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 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> || __detail::__is_reversible_subrange> || __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 requires __detail::__can_elements_view<_Nm, _Range> - [[nodiscard]] constexpr auto operator()(_Range&& __r) const + [[nodiscard]] { return elements_view, _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 +#include +#include