On Thu, Sep 11, 2025 at 2:18 PM Jonathan Wakely <jwak...@redhat.com> wrote:
> These _S_noexcept() functions are only used in noexcept-specifiers and > never need to be called at runtime. They can be immediate functions, > i.e. consteval. > > libstdc++-v3/ChangeLog: > > * include/bits/iterator_concepts.h (_IterMove::_S_noexcept) > (_IterSwap::_S_noexcept): Change constexpr to consteval. > * include/bits/ranges_base.h (_Begin::_S_noexcept) > (_End::_S_noexcept, _RBegin::_S_noexcept, _REnd::_S_noexcept) > (_Size::_S_noexcept, _Empty::_S_noexcept, _Data::_S_noexcept): > Likewise. > * include/std/concepts (_Swap::_S_noexcept): Likewise. > --- > > Tested powerpc64-linux. > Also LGTM. Thanks. > > libstdc++-v3/include/bits/iterator_concepts.h | 4 ++-- > libstdc++-v3/include/bits/ranges_base.h | 14 +++++++------- > libstdc++-v3/include/std/concepts | 2 +- > 3 files changed, 10 insertions(+), 10 deletions(-) > > diff --git a/libstdc++-v3/include/bits/iterator_concepts.h > b/libstdc++-v3/include/bits/iterator_concepts.h > index 979039e7da53..fd91b22d75a5 100644 > --- a/libstdc++-v3/include/bits/iterator_concepts.h > +++ b/libstdc++-v3/include/bits/iterator_concepts.h > @@ -141,21 +141,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > { > // Instead of decltype(std::move(*E)) we define the type as the > // return type of std::move, i.e. > remove_reference_t<iter_ref>&&. > // N.B. the use of decltype(declval<X>()) instead of just X&& > is > // needed for function reference types, see PR > libstdc++/119469. > using type > = > decltype(std::declval<remove_reference_t<__iter_ref_t<_Tp>>>()); > }; > > template<typename _Tp> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (__adl_imove<_Tp>) > return noexcept(iter_move(std::declval<_Tp>())); > else > return noexcept(*std::declval<_Tp>()); > } > > public: > // The result type of iter_move(std::declval<_Tp>()) > @@ -877,21 +877,21 @@ namespace ranges > { > iter_value_t<_Xp> __old_value(iter_move(__x)); > *__x = iter_move(__y); > return __old_value; > } > > struct _IterSwap > { > private: > template<typename _Tp, typename _Up> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (__adl_iswap<_Tp, _Up>) > return noexcept(iter_swap(std::declval<_Tp>(), > std::declval<_Up>())); > else if constexpr (indirectly_readable<_Tp> > && indirectly_readable<_Up> > && swappable_with<iter_reference_t<_Tp>, > iter_reference_t<_Up>>) > return noexcept(ranges::swap(*std::declval<_Tp>(), > *std::declval<_Up>())); > diff --git a/libstdc++-v3/include/bits/ranges_base.h > b/libstdc++-v3/include/bits/ranges_base.h > index c1a9f6a90009..1c4bf432c8f4 100644 > --- a/libstdc++-v3/include/bits/ranges_base.h > +++ b/libstdc++-v3/include/bits/ranges_base.h > @@ -99,21 +99,21 @@ namespace ranges > // Namespace for helpers for the <ranges> customization points. > namespace __access > { > using std::ranges::__detail::__maybe_borrowed_range; > using std::__detail::__range_iter_t; > > struct _Begin > { > private: > template<typename _Tp> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (is_array_v<remove_reference_t<_Tp>>) > return true; > else if constexpr (__member_begin<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().begin())); > else > return > noexcept(_GLIBCXX_AUTO_CAST(begin(std::declval<_Tp&>()))); > } > > @@ -150,21 +150,21 @@ namespace ranges > concept __adl_end = __class_or_enum<remove_reference_t<_Tp>> > && requires(_Tp& __t) > { > { _GLIBCXX_AUTO_CAST(end(__t)) } -> > sentinel_for<__range_iter_t<_Tp>>; > }; > > struct _End > { > private: > template<typename _Tp> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) > return true; > else if constexpr (__member_end<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().end())); > else > return noexcept(_GLIBCXX_AUTO_CAST(end(std::declval<_Tp&>()))); > } > > @@ -207,21 +207,21 @@ namespace ranges > concept __reversable = requires(_Tp& __t) > { > { _Begin{}(__t) } -> bidirectional_iterator; > { _End{}(__t) } -> same_as<decltype(_Begin{}(__t))>; > }; > > struct _RBegin > { > private: > template<typename _Tp> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (__member_rbegin<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rbegin())); > else if constexpr (__adl_rbegin<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(rbegin(std::declval<_Tp&>()))); > else > { > if constexpr (noexcept(_End{}(std::declval<_Tp&>()))) > { > @@ -265,21 +265,21 @@ namespace ranges > && requires(_Tp& __t) > { > { _GLIBCXX_AUTO_CAST(rend(__t)) } > -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>; > }; > > struct _REnd > { > private: > template<typename _Tp> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (__member_rend<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rend())); > else if constexpr (__adl_rend<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(rend(std::declval<_Tp&>()))); > else > { > if constexpr (noexcept(_Begin{}(std::declval<_Tp&>()))) > { > @@ -335,21 +335,21 @@ namespace ranges > > { _End{}(__t) } -> sized_sentinel_for<decltype(_Begin{}(__t))>; > > __detail::__to_unsigned_like(_End{}(__t) - _Begin{}(__t)); > }; > > struct _Size > { > private: > template<typename _Tp> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) > return true; > else if constexpr (__member_size<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().size())); > else if constexpr (__adl_size<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(size(std::declval<_Tp&>()))); > else if constexpr (__sentinel_size<_Tp>) > return noexcept(_End{}(std::declval<_Tp&>()) > @@ -415,21 +415,21 @@ namespace ranges > > { _Begin{}(__t) } -> forward_iterator; > > bool(_Begin{}(__t) == _End{}(__t)); > }; > > struct _Empty > { > private: > template<typename _Tp> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (__member_empty<_Tp>) > return noexcept(bool(std::declval<_Tp&>().empty())); > else if constexpr (__size0_empty<_Tp>) > return noexcept(_Size{}(std::declval<_Tp&>()) == 0); > else > return noexcept(bool(_Begin{}(std::declval<_Tp&>()) > == _End{}(std::declval<_Tp&>()))); > } > @@ -461,21 +461,21 @@ namespace ranges > { _GLIBCXX_AUTO_CAST(__t.data()) } -> __pointer_to_object; > }; > > template<typename _Tp> > concept __begin_data = contiguous_iterator<__range_iter_t<_Tp>>; > > struct _Data > { > private: > template<typename _Tp> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (__member_data<_Tp>) > return > noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().data())); > else > return noexcept(_Begin{}(std::declval<_Tp&>())); > } > > public: > template<__maybe_borrowed_range _Tp> > diff --git a/libstdc++-v3/include/std/concepts > b/libstdc++-v3/include/std/concepts > index 5899f032434a..d9920a8f20a8 100644 > --- a/libstdc++-v3/include/std/concepts > +++ b/libstdc++-v3/include/std/concepts > @@ -197,21 +197,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > = (std::__detail::__class_or_enum<remove_reference_t<_Tp>> > || std::__detail::__class_or_enum<remove_reference_t<_Up>>) > && requires(_Tp&& __t, _Up&& __u) { > swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); > }; > > struct _Swap > { > private: > template<typename _Tp, typename _Up> > - static constexpr bool > + static consteval bool > _S_noexcept() > { > if constexpr (__adl_swap<_Tp, _Up>) > return noexcept(swap(std::declval<_Tp>(), > std::declval<_Up>())); > else > return > is_nothrow_move_constructible_v<remove_reference_t<_Tp>> > && > is_nothrow_move_assignable_v<remove_reference_t<_Tp>>; > } > > public: > -- > 2.51.0 > >