From f0f04e1dffea609cb74ac0b488385401ed7e15a3 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 24 Aug 2022 00:10:59 +0100 Subject: libstdc++: Add check for LWG 3741 problem case This LWG issue was closed as NAD, as it was just a bug in an implementation, not a defect in the standard. Libstdc++ never had that bug and always worked for the problem case. Add a test to ensure we don't regress. The problem occurs when abs is implemented using a ternary expression: return d >= d.zero() ? d : -d; If decltype(-d) is not the same as decltype(d) then this is ambiguous, because each type can be converted to the other, so there is no common type. libstdc++-v3/ChangeLog: * testsuite/20_util/duration_cast/rounding.cc: Check abs with non-reduced duration. --- libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc b/libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc index af6e72d..c5179b6 100644 --- a/libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc +++ b/libstdc++-v3/testsuite/20_util/duration_cast/rounding.cc @@ -58,3 +58,8 @@ static_assert( std::chrono::round(2501ms) == 3s ); static_assert( std::chrono::abs(100ms) == 100ms ); static_assert( std::chrono::abs(-100ms) == 100ms ); + +// LWG 3741. std::chrono::abs(duration) is ill-formed with non-reduced periods +using D1000 = std::chrono::duration>; +static_assert( std::chrono::abs(D1000(-2)) == D1000(2) ); +static_assert( std::is_same_v ); -- cgit v1.1 From 0b7c9254998b3fb2c39f6b86b5b196f415530205 Mon Sep 17 00:00:00 2001 From: Will Hawkins Date: Wed, 24 Aug 2022 02:16:48 -0400 Subject: libstdc++: Optimize operator+(string/char*, char*/string) equally Until now operator+(char*, const string&) and operator+(const string&, char*) had different performance characteristics. The former required a single memory allocation and the latter required two. This patch makes the performance equal. libstdc++-v3/ChangeLog: * include/bits/basic_string.h (operator+(const string&, const char*)): Remove naive implementation. * include/bits/basic_string.tcc (operator+(const string&, const char*)): Add single-allocation implementation. Signed-off-by: Will Hawkins --- libstdc++-v3/include/bits/basic_string.h | 9 ++------- libstdc++-v3/include/bits/basic_string.tcc | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index b04fba9..fa67389 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3521,14 +3521,9 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ template _GLIBCXX20_CONSTEXPR - inline basic_string<_CharT, _Traits, _Alloc> + basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, - const _CharT* __rhs) - { - basic_string<_CharT, _Traits, _Alloc> __str(__lhs); - __str.append(__rhs); - return __str; - } + const _CharT* __rhs); /** * @brief Concatenate string and character. diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index 4563c61..95ba8e5 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -641,6 +641,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR + basic_string<_CharT, _Traits, _Alloc> + operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, + const _CharT* __rhs) + { + __glibcxx_requires_string(__rhs); + typedef basic_string<_CharT, _Traits, _Alloc> __string_type; + typedef typename __string_type::size_type __size_type; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_CharT>::other _Char_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; + const __size_type __len = _Traits::length(__rhs); + __string_type __str(_Alloc_traits::_S_select_on_copy( + __lhs.get_allocator())); + __str.reserve(__len + __lhs.size()); + __str.append(__lhs); + __str.append(__rhs, __len); + return __str; + } + + template _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: -- cgit v1.1 From 530f80451a9e76896a0294e0f4bd59baff1ac27f Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 24 Aug 2022 13:53:27 +0100 Subject: libstdc++: Fix regression in std::stable_sort The recent change to split out the cold path of std::stable_sort caused a regression for some Qt code. The problem is that the library now adds a value of type ptrdiff_t to the iterator, which is ambiguous with -pedantic. The addition could either convert the iterator to a built-in pointer and add the ptrdiff_t to that, or it could convert the ptrdiff_t to the iterator's difference_type and use the iterator's own operator+. The fix is to cast the ptrdiff_t value to the difference type first. libstdc++-v3/ChangeLog: * include/bits/stl_algo.h (__stable_sort): Cast size to iterator's difference type. * testsuite/25_algorithms/stable_sort/4.cc: New test. --- libstdc++-v3/include/bits/stl_algo.h | 5 ++- .../testsuite/25_algorithms/stable_sort/4.cc | 51 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/25_algorithms/stable_sort/4.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index c607805..57fa1c1 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -5026,8 +5026,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO _TmpBuf __buf(__first, (__last - __first + 1) / 2); if (__builtin_expect(__buf.requested_size() == __buf.size(), true)) - std::__stable_sort_adaptive(__first, __first + __buf.size(), __last, - __buf.begin(), __comp); + std::__stable_sort_adaptive(__first, + __first + _DistanceType(__buf.size()), + __last, __buf.begin(), __comp); else if (__builtin_expect(__buf.begin() == 0, false)) std::__inplace_stable_sort(__first, __last, __comp); else diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_sort/4.cc b/libstdc++-v3/testsuite/25_algorithms/stable_sort/4.cc new file mode 100644 index 0000000..b7bda4e --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/stable_sort/4.cc @@ -0,0 +1,51 @@ +// { dg-options "-pedantic" } +// { dg-do compile } + +#include + +/* This type is reduced from QTypedArrayData::iterator which has an implicit + * conversion to its pointer type and a difference type of int. + * The expression Iter() + ptrdiff_t(0) is ambiguous with -pedantic because it + * could either convert the RHS to int and use Iter::operator+(int) + * or it could convert the LHS to pointer and use built-in pointer arithmetic. + */ +struct Iter +{ + struct value_type { bool operator<(value_type) const; }; + typedef value_type* pointer; + typedef value_type& reference; + typedef std::random_access_iterator_tag iterator_category; + typedef int difference_type; + + reference operator*() const; + pointer operator->() const; + + reference operator[](difference_type) const; + + Iter& operator++(); + Iter& operator--(); + Iter operator++(int); + Iter operator--(int); + + Iter& operator+=(difference_type); + Iter& operator-=(difference_type); + + Iter operator+(difference_type) const; + Iter operator-(difference_type) const; + + difference_type operator-(Iter) const; + + operator pointer() const; // XXX this causes the ambiguity + + bool operator==(Iter) const; + bool operator!=(Iter) const; + + bool operator<(Iter) const; +}; + +Iter operator+(Iter::difference_type, Iter); + +int main() +{ + std::stable_sort(Iter(), Iter()); +} -- cgit v1.1 From f46f58e61db3b1e71beb21443c0ca9387bc836e2 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 24 Aug 2022 16:38:45 -0400 Subject: libstdc++: Fix fallout from P2321R2 std::pair/tuple enhancements r13-2159-g72886fcc626953 caused some testsuite regressions in C++23 mode: FAIL: 20_util/pair/requirements/explicit_instantiation/1.cc (test for excess errors) FAIL: 20_util/tuple/53648.cc (test for excess errors) FAIL: 20_util/tuple/cons/noexcept_specs.cc (test for excess errors) FAIL: 20_util/tuple/requirements/explicit_instantiation.cc (test for excess errors) The test noexcept_specs.cc just needs to be updated to consider the additional converting constructors of tuple in C++23 mode, which happen to improve constructing from a const tuple rvalue that has an rvalue reference element (for the better, as far as I can tell). The other three tests fail because they explicitly instantiate a specialization of pair/tuple whose elements are not all const swappable, which in C++23 mode now results in a hard error due to the new const swap member function. Rather than XFAILing the tests in C++23 mode, this patch adds non-standard constraints to this member function so that we continue to accept such explicit instantiations. libstdc++-v3/ChangeLog: * include/bits/stl_pair.h (pair::swap const): Add non-standard is_swappable_v constraints. * include/std/tuple (tuple::swap const): Likewise. * testsuite/20_util/tuple/cons/noexcept_specs.cc: Correct some asserts in C++23 mode. --- libstdc++-v3/include/bits/stl_pair.h | 7 ++++ libstdc++-v3/include/std/tuple | 8 +++++ .../testsuite/20_util/tuple/cons/noexcept_specs.cc | 41 ++++++++++++++++++++++ 3 files changed, 56 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index bffca0d..d0f07b0 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -213,10 +213,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus > 202002L + // As an extension, we constrain the const swap member function in order + // to continue accepting explicit instantiation of pairs whose elements + // are not all const swappable. Without this constraint, such an + // explicit instantiation would also instantiate the ill-formed body of + // this function and yield a hard error. This constraint shouldn't + // affect the behavior of valid programs. constexpr void swap(const pair& __p) const noexcept(__and_v<__is_nothrow_swappable, __is_nothrow_swappable>) + requires is_swappable_v && is_swappable_v { using std::swap; swap(first, __p.first); diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 05433d5..ddd7c22 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -1176,9 +1176,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _Inherited::_M_swap(__in); } #if __cplusplus > 202002L + // As an extension, we constrain the const swap member function in order + // to continue accepting explicit instantiation of tuples whose elements + // are not all const swappable. Without this constraint, such an + // explicit instantiation would also instantiate the ill-formed body of + // this function and yield a hard error. This constraint shouldn't + // affect the behavior of valid programs. constexpr void swap(const tuple& __in) const noexcept(__and_v<__is_nothrow_swappable...>) + requires (is_swappable_v && ...) { _Inherited::_M_swap(__in); } #endif // C++23 }; @@ -1730,6 +1737,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION swap(const tuple& __in) const noexcept(__and_v<__is_nothrow_swappable, __is_nothrow_swappable>) + requires is_swappable_v && is_swappable_v { _Inherited::_M_swap(__in); } #endif // C++23 }; diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc index 6044a37..a326d1b 100644 --- a/libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc +++ b/libstdc++-v3/testsuite/20_util/tuple/cons/noexcept_specs.cc @@ -503,7 +503,17 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(!std::is_nothrow_constructible::value, ""); static_assert(!std::is_nothrow_constructible::value, ""); static_assert(!std::is_nothrow_constructible>::value, ""); +#if __cplusplus > 202002L + // C++23 extended tuple's constructor overload set as part of P2321R2, after + // which its converting constructors more accurately forward the elements + // from a non-const tuple lvalue and from a const tuple rvalue. In particular + // for the below test we now forward int&& as an rvalue reference instead of + // as an lvalue reference, which means we now select the noexcept B(int&&) + // ctor instead of the non-noexcept B(const int&) ctor. + static_assert(std::is_nothrow_constructible>::value, ""); +#else static_assert(!std::is_nothrow_constructible>::value, ""); +#endif static_assert(test_trait::is_nothrow_convertible::value,""); static_assert(!test_trait::is_nothrow_convertible::value,""); @@ -515,7 +525,13 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(!test_trait::is_nothrow_convertible::value,""); static_assert(!test_trait::is_nothrow_convertible::value,""); static_assert(!test_trait::is_nothrow_convertible,BT>::value,""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(test_trait::is_nothrow_convertible,BT>::value,""); +#else static_assert(!test_trait::is_nothrow_convertible,BT>::value,""); +#endif + static_assert(!std::is_nothrow_constructible::value, ""); @@ -528,7 +544,12 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(std::is_nothrow_constructible::value, ""); static_assert(std::is_nothrow_constructible::value, ""); static_assert(std::is_nothrow_constructible>::value, ""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(!std::is_nothrow_constructible>::value, ""); +#else static_assert(std::is_nothrow_constructible>::value, ""); +#endif static_assert(!test_trait::is_nothrow_convertible::value,""); static_assert(test_trait::is_nothrow_convertible::value,""); @@ -540,7 +561,12 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(test_trait::is_nothrow_convertible::value,""); static_assert(test_trait::is_nothrow_convertible::value,""); static_assert(test_trait::is_nothrow_convertible,BT>::value,""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(!test_trait::is_nothrow_convertible,BT>::value,""); +#else static_assert(test_trait::is_nothrow_convertible,BT>::value,""); +#endif /* explicit */ static_assert(std::is_nothrow_constructible::value, ""); @@ -553,7 +579,12 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(!std::is_nothrow_constructible::value, ""); static_assert(!std::is_nothrow_constructible::value, ""); static_assert(!std::is_nothrow_constructible>::value, ""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(std::is_nothrow_constructible>::value, ""); +#else static_assert(!std::is_nothrow_constructible>::value, ""); +#endif static_assert(!std::is_nothrow_constructible::value, ""); static_assert(std::is_nothrow_constructible::value, ""); @@ -565,7 +596,12 @@ namespace NothrowCopyThrowMoveThrowCopyConversionNothrowMoveConversion static_assert(std::is_nothrow_constructible::value, ""); static_assert(std::is_nothrow_constructible::value, ""); static_assert(std::is_nothrow_constructible>::value, ""); +#if __cplusplus > 202002L + // See note about P2321R2 above. + static_assert(!std::is_nothrow_constructible>::value, ""); +#else static_assert(std::is_nothrow_constructible>::value, ""); +#endif static_assert(!test_trait::is_nothrow_convertible::value,""); static_assert(test_trait::is_nothrow_convertible::value,""); @@ -884,7 +920,12 @@ namespace ThrowMoveNothrowConversion static_assert(std::is_nothrow_constructible::value, ""); static_assert(std::is_nothrow_constructible::value, ""); static_assert(std::is_nothrow_constructible>::value, ""); +#if __cplusplus > 202002L + // See the note about P2321R2 above. + static_assert(!std::is_nothrow_constructible>::value, ""); +#else static_assert(std::is_nothrow_constructible>::value, ""); +#endif static_assert(test_trait::is_nothrow_convertible::value,""); static_assert(test_trait::is_nothrow_convertible::value,""); -- cgit v1.1 From e5428086c2c8daf69e5916dd5016d1e7b85d3f0d Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 24 Aug 2022 23:47:43 +0100 Subject: Revert "libstdc++: Optimize operator+(string/char*, char*/string) equally" This reverts commit 0b7c9254998b3fb2c39f6b86b5b196f415530205. --- libstdc++-v3/include/bits/basic_string.h | 9 +++++++-- libstdc++-v3/include/bits/basic_string.tcc | 21 --------------------- 2 files changed, 7 insertions(+), 23 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index fa67389..b04fba9 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3521,9 +3521,14 @@ _GLIBCXX_END_NAMESPACE_CXX11 */ template _GLIBCXX20_CONSTEXPR - basic_string<_CharT, _Traits, _Alloc> + inline basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, - const _CharT* __rhs); + const _CharT* __rhs) + { + basic_string<_CharT, _Traits, _Alloc> __str(__lhs); + __str.append(__rhs); + return __str; + } /** * @brief Concatenate string and character. diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index 95ba8e5..4563c61 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -641,27 +641,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template - _GLIBCXX20_CONSTEXPR - basic_string<_CharT, _Traits, _Alloc> - operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, - const _CharT* __rhs) - { - __glibcxx_requires_string(__rhs); - typedef basic_string<_CharT, _Traits, _Alloc> __string_type; - typedef typename __string_type::size_type __size_type; - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_CharT>::other _Char_alloc_type; - typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; - const __size_type __len = _Traits::length(__rhs); - __string_type __str(_Alloc_traits::_S_select_on_copy( - __lhs.get_allocator())); - __str.reserve(__len + __lhs.size()); - __str.append(__lhs); - __str.append(__rhs, __len); - return __str; - } - - template _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: -- cgit v1.1 From 49e25d3e29aa1b56e6e82654de1a452a6cedc265 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 24 Aug 2022 19:17:27 -0400 Subject: libstdc++: Implement ranges::zip_view from P2321R2 libstdc++-v3/ChangeLog: * include/bits/ranges_algo.h (__min_fn, min): Move to ... * include/bits/ranges_util.h: ... here, in order to avoid including all of ranges_algo.h from . * include/std/ranges (__detail::__zip_is_common): Define for C++23 as per P2321R2. (__detail::__tuple_or_pair): Likewise. (__detail::__tuple_or_pair_t): Likewise. (__detail::__tuple_transform): Likewise. (__detail::__tuple_for_each): Likewise. (zip_view): Likewise. (enable_borrowed_range): Likewise. (__detail::__all_random_access): Likewise. (__detail::__all_bidirectional): Likewise. (__detail::__all_forward): Likewise. (__detail::__zip_view_iter_cat): Likewise. (zip_view::_Iterator): Likewise. (zip_view::_Sentinel): Likewise. * testsuite/std/ranges/zip/1.cc: New test. --- libstdc++-v3/include/bits/ranges_algo.h | 54 +--- libstdc++-v3/include/bits/ranges_util.h | 55 ++++ libstdc++-v3/include/std/ranges | 442 +++++++++++++++++++++++++++++ libstdc++-v3/testsuite/std/ranges/zip/1.cc | 111 ++++++++ 4 files changed, 609 insertions(+), 53 deletions(-) create mode 100644 libstdc++-v3/testsuite/std/ranges/zip/1.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index 3d30fb1..2a11636 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -2902,59 +2902,7 @@ namespace ranges inline constexpr __set_symmetric_difference_fn set_symmetric_difference{}; - struct __min_fn - { - template> - _Comp = ranges::less> - constexpr const _Tp& - operator()(const _Tp& __a, const _Tp& __b, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (std::__invoke(__comp, - std::__invoke(__proj, __b), - std::__invoke(__proj, __a))) - return __b; - else - return __a; - } - - template, _Proj>> - _Comp = ranges::less> - requires indirectly_copyable_storable, - range_value_t<_Range>*> - constexpr range_value_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - __glibcxx_assert(__first != __last); - auto __result = *__first; - while (++__first != __last) - { - auto __tmp = *__first; - if (std::__invoke(__comp, - std::__invoke(__proj, __tmp), - std::__invoke(__proj, __result))) - __result = std::move(__tmp); - } - return __result; - } - - template> - _Comp = ranges::less> - constexpr _Tp - operator()(initializer_list<_Tp> __r, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::subrange(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __min_fn min{}; + // min is defined in . struct __max_fn { diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 37d7bc8..bb56dee 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -649,6 +649,61 @@ namespace ranges }; inline constexpr __search_fn search{}; + + struct __min_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(__comp, + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_fn min{}; + } // namespace ranges using ranges::get; diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 3e71ecb..c600bad6 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -4352,6 +4352,448 @@ namespace views::__adaptor inline constexpr auto values = elements<1>; } // namespace views +#if __cplusplus > 202002L + namespace __detail + { + template + concept __zip_is_common = (sizeof...(_Rs) == 1 && (common_range<_Rs> && ...)) + || (!(bidirectional_range<_Rs> && ...) && (common_range<_Rs> && ...)) + || ((random_access_range<_Rs> && ...) && (sized_range<_Rs> && ...)); + + template + struct __tuple_or_pair + { using type = std::tuple<_Ts...>; }; + + template + struct __tuple_or_pair<_Tp, _Up> + { using type = pair<_Tp, _Up>; }; + + template + using __tuple_or_pair_t = typename __tuple_or_pair<_Ts...>::type; + + template + constexpr auto + __tuple_transform(_Fp&& __f, _Tuple&& __tuple) + { + return std::apply([&](_Ts&&... __elts) { + return __tuple_or_pair_t...> + (std::__invoke(__f, std::forward<_Ts>(__elts))...); + }, std::forward<_Tuple>(__tuple)); + } + + template + constexpr void + __tuple_for_each(_Fp&& __f, _Tuple&& __tuple) + { + std::apply([&](_Ts&&... __elts) { + (std::__invoke(__f, std::forward<_Ts>(__elts)), ...); + }, std::forward<_Tuple>(__tuple)); + } + } // namespace __detail + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + class zip_view : public view_interface> + { + tuple<_Vs...> _M_views; + + template class _Iterator; + template class _Sentinel; + + public: + zip_view() = default; + + constexpr explicit + zip_view(_Vs... __views) + : _M_views(std::move(__views)...) + { } + + constexpr auto + begin() requires (!(__detail::__simple_view<_Vs> && ...)) + { return _Iterator(__detail::__tuple_transform(ranges::begin, _M_views)); } + + constexpr auto + begin() const requires (range && ...) + { return _Iterator(__detail::__tuple_transform(ranges::begin, _M_views)); } + + constexpr auto + end() requires (!(__detail::__simple_view<_Vs> && ...)) + { + if constexpr (!__detail::__zip_is_common<_Vs...>) + return _Sentinel(__detail::__tuple_transform(ranges::end, _M_views)); + else if constexpr ((random_access_range<_Vs> && ...)) + return begin() + iter_difference_t<_Iterator>(size()); + else + return _Iterator(__detail::__tuple_transform(ranges::end, _M_views)); + } + + constexpr auto + end() const requires (range && ...) + { + if constexpr (!__detail::__zip_is_common) + return _Sentinel(__detail::__tuple_transform(ranges::end, _M_views)); + else if constexpr ((random_access_range && ...)) + return begin() + iter_difference_t<_Iterator>(size()); + else + return _Iterator(__detail::__tuple_transform(ranges::end, _M_views)); + } + + constexpr auto + size() requires (sized_range<_Vs> && ...) + { + return std::apply([](auto... sizes) { + using _CT = __detail::__make_unsigned_like_t>; + return ranges::min({_CT(sizes)...}); + }, __detail::__tuple_transform(ranges::size, _M_views)); + } + + constexpr auto + size() const requires (sized_range && ...) + { + return std::apply([](auto... sizes) { + using _CT = __detail::__make_unsigned_like_t>; + return ranges::min({_CT(sizes)...}); + }, __detail::__tuple_transform(ranges::size, _M_views)); + } + }; + + template + zip_view(_Rs&&...) -> zip_view...>; + + template + inline constexpr bool enable_borrowed_range> + = (enable_borrowed_range<_Views> && ...); + + namespace __detail + { + template + concept __all_random_access + = (random_access_range<__maybe_const_t<_Const, _Vs>> && ...); + + template + concept __all_bidirectional + = (bidirectional_range<__maybe_const_t<_Const, _Vs>> && ...); + + template + concept __all_forward + = (forward_range<__maybe_const_t<_Const, _Vs>> && ...); + + template + struct __zip_view_iter_cat + { }; + + template + requires __all_forward<_Const, _Views...> + struct __zip_view_iter_cat<_Const, _Views...> + { using iterator_category = input_iterator_tag; }; + } // namespace __detail + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + template + class zip_view<_Vs...>::_Iterator + : public __detail::__zip_view_iter_cat<_Const, _Vs...> + { + __detail::__tuple_or_pair_t>...> _M_current; + + constexpr explicit + _Iterator(decltype(_M_current) __current) + : _M_current(std::move(__current)) + { } + + static auto + _S_iter_concept() + { + if constexpr (__detail::__all_random_access<_Const, _Vs...>) + return random_access_iterator_tag{}; + else if constexpr (__detail::__all_bidirectional<_Const, _Vs...>) + return bidirectional_iterator_tag{}; + else if constexpr (__detail::__all_forward<_Const, _Vs...>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + public: + // iterator_category defined in __zip_view_iter_cat + using iterator_concept = decltype(_S_iter_concept()); + using value_type + = __detail::__tuple_or_pair_t>...>; + using difference_type + = common_type_t>...>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const + && (convertible_to, + iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + : _M_current(std::move(__i._M_current)) + { } + + constexpr auto + operator*() const + { + auto __f = [](auto& __i) -> decltype(auto) { + return *__i; + }; + return __detail::__tuple_transform(__f, _M_current); + } + + constexpr _Iterator& + operator++() + { + __detail::__tuple_for_each([](auto& __i) { ++__i; }, _M_current); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) + requires __detail::__all_forward<_Const, _Vs...> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires __detail::__all_bidirectional<_Const, _Vs...> + { + __detail::__tuple_for_each([](auto& __i) { --__i; }, _M_current); + return *this; + } + + constexpr _Iterator + operator--(int) + requires __detail::__all_bidirectional<_Const, _Vs...> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&](_It& __i) { + __i += iter_difference_t<_It>(__x); + }; + __detail::__tuple_for_each(__f, _M_current); + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&](_It& __i) { + __i -= iter_difference_t<_It>(__x); + }; + __detail::__tuple_for_each(__f, _M_current); + return *this; + } + + constexpr auto + operator[](difference_type __n) const + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __f = [&](_It& __i) -> decltype(auto) { + return __i[iter_difference_t<_It>(__n)]; + }; + return __detail::__tuple_transform(__f, _M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires (equality_comparable>> && ...) + { + if constexpr (__detail::__all_bidirectional<_Const, _Vs...>) + return __x._M_current == __y._M_current; + else + return [&](index_sequence<_Is...>) { + return ((std::get<_Is>(__x._M_current) == std::get<_Is>(__y._M_current)) || ...); + }(make_index_sequence{}); + } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _Vs...> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _Vs...> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _Vs...> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _Vs...> + { return !(__x < __y); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires __detail::__all_random_access<_Const, _Vs...> + && (three_way_comparable>> && ...) + { return __x._M_current <=> __y._M_current; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires __detail::__all_random_access<_Const, _Vs...> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires (sized_sentinel_for>, + iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + { + return [&](index_sequence<_Is...>) { + return ranges::min({difference_type(std::get<_Is>(__x._M_current) + - std::get<_Is>(__y._M_current))...}, + ranges::less{}, + [](difference_type __i) -> make_unsigned_t { + return __i < 0 ? -__i : __i; + }); + }(make_index_sequence{}); + } + + friend constexpr auto + iter_move(const _Iterator& __i) + { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __l, const _Iterator& __r) + requires (indirectly_swappable>> && ...) + { + [&](index_sequence<_Is...>) { + (ranges::iter_swap(std::get<_Is>(__l._M_current), std::get<_Is>(__r._M_current)), ...); + }(make_index_sequence{}); + } + + friend class zip_view; + }; + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) + template + class zip_view<_Vs...>::_Sentinel + { + __detail::__tuple_or_pair_t>...> _M_end; + + constexpr explicit + _Sentinel(decltype(_M_end) __end) + : _M_end(__end) + { } + + friend class zip_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __i) + requires _Const + && (convertible_to, + sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...) + : _M_end(std::move(__i._M_end)) + { } + + template + requires (sentinel_for>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { + return [&](index_sequence<_Is...>) { + return ((std::get<_Is>(__x._M_current) == std::get<_Is>(__y._M_end)) || ...); + }(make_index_sequence{}); + } + + template + requires (sized_sentinel_for>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr auto + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { + using _Ret + = common_type_t>...>; + return [&](index_sequence<_Is...>) { + return ranges::min({_Ret(std::get<_Is>(__x._M_current) - std::get<_Is>(__y._M_end))...}, + ranges::less{}, + [](_Ret __i) -> make_unsigned_t<_Ret> { + return __i < 0 ? -__i : __i; + }); + }(make_index_sequence{}); + } + + template + requires (sized_sentinel_for>, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...) + friend constexpr auto + operator-(const _Sentinel& __y, const _Iterator<_OtherConst>& __x) + { return -(__x - __y); } + }; + + namespace views + { + namespace __detail + { + template + concept __can_zip_view + = requires { zip_view...>(std::declval<_Ts>()...); }; + } + + struct _Zip + { + template + requires (sizeof...(_Ts) == 0 || __detail::__can_zip_view<_Ts...>) + [[nodiscard]] + constexpr auto + operator()(_Ts&&... __ts) const + { + if constexpr (sizeof...(_Ts) == 0) + return views::empty>; + else + return zip_view...>(std::forward<_Ts>(__ts)...); + } + }; + + inline constexpr _Zip zip; + } +#endif // C++23 } // namespace ranges namespace views = ranges::views; diff --git a/libstdc++-v3/testsuite/std/ranges/zip/1.cc b/libstdc++-v3/testsuite/std/ranges/zip/1.cc new file mode 100644 index 0000000..0113efd --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/zip/1.cc @@ -0,0 +1,111 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include +#include +#include +#include +#include +#include + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + static_assert(ranges::empty(views::zip())); + static_assert(ranges::empty(views::empty)); + + auto z1 = views::zip(std::array{1, 2}); + const auto i0 = z1.begin(), i1 = z1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < z1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( z1.end() - i1 == 1 ); + VERIFY( i1 - z1.end() == -1 ); + ranges::iter_swap(i0, i1); + VERIFY( ranges::equal(std::move(z1) | views::keys, (int[]){2, 1}) ); + + auto z2 = views::zip(std::array{1, 2}, std::array{3, 4, 5}); + auto i2 = z2.begin(); + i2 += 1; + i2 -= -1; + VERIFY( i2 == z2.end() ); + VERIFY( ranges::size(z2) == 2 ); + VERIFY( ranges::size(std::as_const(z2)) == 2 ); + VERIFY( z2[0].first == 1 && z2[0].second == 3 ); + VERIFY( z2[1].first == 2 && z2[1].second == 4 ); + for (const auto [x, y] : z2) + { + VERIFY( y - x == 2 ); + std::swap(x, y); + } + + int x[2] = {1, 2}, y[2] = {3, 4}, z[2] = {5, 6}; + const auto z3 = views::zip(x, y, z); + VERIFY( ranges::size(z3) == 2 ); + for (int i = 0; i < ranges::size(x); i++) + { + VERIFY( &std::get<0>(z3[i]) == &x[i] ); + VERIFY( &std::get<1>(z3[i]) == &y[i] ); + VERIFY( &std::get<2>(z3[i]) == &z[i] ); + } + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::zip_view>, + views::all_t>>; + static_assert(ranges::forward_range); + static_assert(!ranges::random_access_range); + static_assert(!ranges::sized_range); + + using ty2 = ranges::zip_view>, + views::all_t>, + views::all_t>>; + static_assert(ranges::input_range); + static_assert(!ranges::forward_range); + static_assert(!ranges::sized_range); + + return true; +} + +constexpr bool +test03() +{ + int u[] = {1, 2, 3, 4}, v[] = {4, 5, 6}, w[] = {7, 8, 9, 10}; + auto z = views::zip(u | views::filter([](auto) { return true; }), v, w); + using ty = decltype(z); + static_assert(ranges::forward_range); + static_assert(!ranges::common_range); + static_assert(!ranges::sized_range); + VERIFY( z.begin() == z.begin() ); + VERIFY( z.begin() != z.end() ); + VERIFY( ranges::next(z.begin(), 3) == z.end() ); + auto it = z.begin(); + ++it; + it++; + it--; + --it; + VERIFY( it == z.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +} -- cgit v1.1 From e8fc33aabcfd8f4a4e384e022e4812caca556e0e Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 25 Aug 2022 00:16:33 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index d88ffec..4c78614 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,60 @@ +2022-08-24 Patrick Palka + + * include/bits/ranges_algo.h (__min_fn, min): Move to ... + * include/bits/ranges_util.h: ... here, in order to avoid + including all of ranges_algo.h from . + * include/std/ranges (__detail::__zip_is_common): Define for + C++23 as per P2321R2. + (__detail::__tuple_or_pair): Likewise. + (__detail::__tuple_or_pair_t): Likewise. + (__detail::__tuple_transform): Likewise. + (__detail::__tuple_for_each): Likewise. + (zip_view): Likewise. + (enable_borrowed_range): Likewise. + (__detail::__all_random_access): Likewise. + (__detail::__all_bidirectional): Likewise. + (__detail::__all_forward): Likewise. + (__detail::__zip_view_iter_cat): Likewise. + (zip_view::_Iterator): Likewise. + (zip_view::_Sentinel): Likewise. + * testsuite/std/ranges/zip/1.cc: New test. + +2022-08-24 Jonathan Wakely + + Revert: + 2022-08-24 Will Hawkins + + * include/bits/basic_string.h (operator+(const string&, const char*)): + Remove naive implementation. + * include/bits/basic_string.tcc (operator+(const string&, const char*)): + Add single-allocation implementation. + +2022-08-24 Patrick Palka + + * include/bits/stl_pair.h (pair::swap const): Add non-standard + is_swappable_v constraints. + * include/std/tuple (tuple::swap const): Likewise. + * testsuite/20_util/tuple/cons/noexcept_specs.cc: Correct some + asserts in C++23 mode. + +2022-08-24 Jonathan Wakely + + * include/bits/stl_algo.h (__stable_sort): Cast size to + iterator's difference type. + * testsuite/25_algorithms/stable_sort/4.cc: New test. + +2022-08-24 Will Hawkins + + * include/bits/basic_string.h (operator+(const string&, const char*)): + Remove naive implementation. + * include/bits/basic_string.tcc (operator+(const string&, const char*)): + Add single-allocation implementation. + +2022-08-24 Jonathan Wakely + + * testsuite/20_util/duration_cast/rounding.cc: Check abs with + non-reduced duration. + 2022-08-23 Patrick Palka * include/bits/stl_bvector.h (_Bit_reference::operator=): Define -- cgit v1.1 From 980e0aa0ce3bdfec61ca766a71a31a89c12f882e Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Thu, 25 Aug 2022 11:11:04 -0400 Subject: libstdc++: Some minor cleanups libstdc++-v3/ChangeLog: * include/std/ranges (lazy_split_view::_OuterIter::_M_current): Remove redundant comment. (lazy_split_view::_M_current): Likewise. (common_view::common_view): Remove commented out view-converting constructor as per LWG3405. (elements_view::_Iterator::_Iterator): Uglify 'current' and 'i'. --- libstdc++-v3/include/std/ranges | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index c600bad6..fb815c4 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -3116,7 +3116,6 @@ namespace views::__adaptor _Parent* _M_parent = nullptr; - // XXX: _M_current is present only if "V models forward_range" [[no_unique_address]] __detail::__maybe_present_t, iterator_t<_Base>> _M_current; @@ -3370,7 +3369,6 @@ namespace views::__adaptor _Vp _M_base = _Vp(); _Pattern _M_pattern = _Pattern(); - // XXX: _M_current is "present only if !forward_range" [[no_unique_address]] __detail::__maybe_present_t, __detail::__non_propagating_cache>> _M_current; @@ -3725,16 +3723,6 @@ namespace views::__adaptor : _M_base(std::move(__r)) { } - /* XXX: LWG 3280 didn't remove this constructor, but I think it should? - template - requires (!common_range<_Range>) - && constructible_from<_Vp, views::all_t<_Range>> - constexpr explicit - common_view(_Range&& __r) - : _M_base(views::all(std::forward<_Range>(__r))) - { } - */ - constexpr _Vp base() const& requires copy_constructible<_Vp> { return _M_base; } @@ -4115,14 +4103,14 @@ namespace views::__adaptor _Iterator() requires default_initializable> = default; constexpr explicit - _Iterator(iterator_t<_Base> current) - : _M_current(std::move(current)) + _Iterator(iterator_t<_Base> __current) + : _M_current(std::move(__current)) { } constexpr - _Iterator(_Iterator i) + _Iterator(_Iterator __i) requires _Const && convertible_to, iterator_t<_Base>> - : _M_current(std::move(i._M_current)) + : _M_current(std::move(__i._M_current)) { } constexpr const iterator_t<_Base>& -- cgit v1.1 From 5d4389dc913269cc6a6fd6ee38abc78b1fb7dbe8 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 26 Aug 2022 00:16:21 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4c78614..1b20d4e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2022-08-25 Patrick Palka + + * include/std/ranges (lazy_split_view::_OuterIter::_M_current): + Remove redundant comment. + (lazy_split_view::_M_current): Likewise. + (common_view::common_view): Remove commented out view-converting + constructor as per LWG3405. + (elements_view::_Iterator::_Iterator): Uglify 'current' and 'i'. + 2022-08-24 Patrick Palka * include/bits/ranges_algo.h (__min_fn, min): Move to ... -- cgit v1.1 From 1b0b969df794d0401ccb9279d44302d1e4729f15 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 26 Aug 2022 09:43:32 +0100 Subject: libstdc++: Add nonnull to starts_with/ends_with/contains string members Ideally this wouldn't be needed, because eventually these pointers all get passed to either the basic_string_view(const CharT*) constructor, or to basic_string_view::find(const CharT*), both of which already have the attribute. But for that to work requires optimization, so that the null value gets propagated through the call chain. Adding it explicitly to each member that requires a non-null pointer makes the diagnostics more reliable even without optimization. It's better to give a diagnostic earlier anyway, at the actual problematic call in the user's code. libstdc++-v3/ChangeLog: * include/bits/basic_string.h (starts_with, ends_with, contains): Add nonnull attribute. * include/bits/cow_string.h (starts_with, ends_with, contains): Likewise. * include/std/string_view (starts_with, ends_with, contains): Likewise. * testsuite/21_strings/basic_string/operations/contains/nonnull.cc * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc * testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc * testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc * testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc --- libstdc++-v3/include/bits/basic_string.h | 3 +++ libstdc++-v3/include/bits/cow_string.h | 3 +++ libstdc++-v3/include/std/string_view | 3 +++ .../21_strings/basic_string/operations/contains/nonnull.cc | 12 ++++++++++++ .../21_strings/basic_string/operations/ends_with/nonnull.cc | 12 ++++++++++++ .../basic_string/operations/starts_with/nonnull.cc | 12 ++++++++++++ .../basic_string_view/operations/contains/nonnull.cc | 12 ++++++++++++ .../basic_string_view/operations/ends_with/nonnull.cc | 12 ++++++++++++ .../basic_string_view/operations/starts_with/nonnull.cc | 12 ++++++++++++ 9 files changed, 81 insertions(+) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index b04fba9..9d8b415 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3400,6 +3400,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 starts_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } + [[__gnu__::__nonnull__]] constexpr bool starts_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } @@ -3412,6 +3413,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ends_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } + [[__gnu__::__nonnull__]] constexpr bool ends_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } @@ -3426,6 +3428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 contains(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } + [[__gnu__::__nonnull__]] constexpr bool contains(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index f16e33a..f5f0333 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -3012,6 +3012,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION starts_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } + [[__gnu__::__nonnull__]] bool starts_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } @@ -3024,6 +3025,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ends_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } + [[__gnu__::__nonnull__]] bool ends_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } @@ -3038,6 +3040,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION contains(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } + [[__gnu__::__nonnull__]] bool contains(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index 30ff136..5b96ffe 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -360,6 +360,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION starts_with(_CharT __x) const noexcept { return !this->empty() && traits_type::eq(this->front(), __x); } + [[__gnu__::__nonnull__]] constexpr bool starts_with(const _CharT* __x) const noexcept { return this->starts_with(basic_string_view(__x)); } @@ -377,6 +378,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ends_with(_CharT __x) const noexcept { return !this->empty() && traits_type::eq(this->back(), __x); } + [[__gnu__::__nonnull__]] constexpr bool ends_with(const _CharT* __x) const noexcept { return this->ends_with(basic_string_view(__x)); } @@ -392,6 +394,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION contains(_CharT __x) const noexcept { return this->find(__x) != npos; } + [[__gnu__::__nonnull__]] constexpr bool contains(const _CharT* __x) const noexcept { return this->find(__x) != npos; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc new file mode 100644 index 0000000..e987cb7 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++23 -Wnonnull -O0" } +// { dg-do compile { target c++23 } } + +#include + +void +test01(const std::string& s) +{ + s.contains((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.contains((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.contains(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc new file mode 100644 index 0000000..1f2a156 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++20 -Wnonnull -O0" } +// { dg-do compile { target c++20 } } + +#include + +void +test01(const std::string& s) +{ + s.ends_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.ends_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.ends_with(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc new file mode 100644 index 0000000..8514359 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++20 -Wnonnull -O0" } +// { dg-do compile { target c++20 } } + +#include + +void +test01(const std::string& s) +{ + s.starts_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.starts_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.starts_with(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc new file mode 100644 index 0000000..c0d274f --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++23 -Wnonnull -O0" } +// { dg-do compile { target c++23 } } + +#include + +void +test01(std::string_view s) +{ + s.contains((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.contains((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.contains(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc new file mode 100644 index 0000000..09a9997 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++20 -Wnonnull -O0" } +// { dg-do compile { target c++20 } } + +#include + +void +test01(std::string_view s) +{ + s.ends_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.ends_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.ends_with(nullptr); // { dg-warning "\\\[-Wnonnull" } +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc new file mode 100644 index 0000000..c47f1da --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc @@ -0,0 +1,12 @@ +// { dg-options "-std=gnu++20 -Wnonnull -O0" } +// { dg-do compile { target c++20 } } + +#include + +void +test01(std::string_view s) +{ + s.starts_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.starts_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } + s.starts_with(nullptr); // { dg-warning "\\\[-Wnonnull" } +} -- cgit v1.1 From 1c0288065b8184e0051d846b0940027b97ea0eb4 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 26 Aug 2022 12:55:02 +0100 Subject: libstdc++: Simplify std::error_code and std::error_condition This removes the redundant operator=(E) from std::error_code and std::error_condition. Without that overload, assignment from a custom type will use the templated constructor to create a temporary and then use the trivial copy assignment operator. With the overloaded assignment, we have to check the constraints twice as often, because that overload and its constraints are checked for simple copy assignments (including the one in the overloaded assignment operator itself!) Also add tests that ADL is used as per LWG 3629. libstdc++-v3/ChangeLog: * include/std/system_error (error_code::_Check): New alias template for constructor SFINAE constraint. (error_code::error_code(ErrorCodeEnum)): Use it. (error_code::operator=(ErrorCodeEnum)): Remove. (error_condition::_Check): New alias template for constraint. (error_condition::error_condition(ErrorConditionEnum)): Use it. (error_condition::operator=(ErrorConditionEnum)): Remove. * testsuite/19_diagnostics/error_code/cons/1.cc: Check constructor taking user-defined error enum. * testsuite/19_diagnostics/error_condition/cons/1.cc: Likewise. --- libstdc++-v3/include/std/system_error | 38 ++++++++++++---------- .../testsuite/19_diagnostics/error_code/cons/1.cc | 31 +++++++++++++++--- .../19_diagnostics/error_condition/cons/1.cc | 31 ++++++++++++++++-- 3 files changed, 75 insertions(+), 25 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/system_error b/libstdc++-v3/include/std/system_error index 87cf720..0504394 100644 --- a/libstdc++-v3/include/std/system_error +++ b/libstdc++-v3/include/std/system_error @@ -216,6 +216,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) */ class error_code { + template + using _Check + = __enable_if_t::value>; + public: error_code() noexcept : _M_value(0), _M_cat(&system_category()) { } @@ -223,11 +227,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) error_code(int __v, const error_category& __cat) noexcept : _M_value(__v), _M_cat(&__cat) { } - template::value>::type> + /// Initialize with a user-defined type, by calling make_error_code. + template> error_code(_ErrorCodeEnum __e) noexcept { *this = make_error_code(__e); } + error_code(const error_code&) = default; + error_code& operator=(const error_code&) = default; + void assign(int __v, const error_category& __cat) noexcept { @@ -239,13 +247,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) clear() noexcept { assign(0, system_category()); } - // DR 804. - template - typename enable_if::value, - error_code&>::type - operator=(_ErrorCodeEnum __e) noexcept - { return *this = make_error_code(__e); } - /// The error value. [[__nodiscard__]] int @@ -345,6 +346,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) */ class error_condition { + template + using _Check + = __enable_if_t::value>; + public: /// Initialize with a zero (no error) value and the generic category. error_condition() noexcept @@ -354,11 +359,15 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) error_condition(int __v, const error_category& __cat) noexcept : _M_value(__v), _M_cat(&__cat) { } - template::value>::type> + /// Initialize with a user-defined type, by calling make_error_condition. + template> error_condition(_ErrorConditionEnum __e) noexcept { *this = make_error_condition(__e); } + error_condition(const error_condition&) = default; + error_condition& operator=(const error_condition&) = default; + /// Set the value and category. void assign(int __v, const error_category& __cat) noexcept @@ -367,13 +376,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _M_cat = &__cat; } - // DR 804. - template - typename enable_if::value, error_condition&>::type - operator=(_ErrorConditionEnum __e) noexcept - { return *this = make_error_condition(__e); } - /// Reset the value and category to the default-constructed state. void clear() noexcept diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc b/libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc index f454fc2..d48d5c1 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_code/cons/1.cc @@ -22,23 +22,46 @@ #include #include +namespace adl +{ + struct Error { }; + + const Error err; + + struct category : std::error_category + { + const char* name() const noexcept override { return "adl"; } + std::string message(int) const { return ""; } + }; + + const category cat; + + std::error_code + make_error_code(Error) { return std::error_code(999, cat); } +} + +template<> struct std::is_error_code_enum : std::true_type { }; + int main() { - // 1 + // 1 error_code() std::error_code e1; VERIFY( e1.value() == 0 ); VERIFY( e1.category() == std::system_category() ); - // 2 + // 2 error_code(int, const error_category&) const __gnu_test::test_category cat; std::error_code e2(e1.value(), cat); VERIFY( e2.value() == e1.value() ); VERIFY( e2.category() == cat ); - // 3 + // 3 error_code(const error_code&) std::error_code e3(std::make_error_code(std::errc::operation_not_supported)); VERIFY( e3.value() == int(std::errc::operation_not_supported) ); VERIFY( e3.category() == std::generic_category() ); - return 0; + // 4 error_code(ErrorCodeEnum) + std::error_code e4(adl::err); + VERIFY( e4.value() == 999 ); + VERIFY( e4.category() == adl::cat ); } diff --git a/libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc b/libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc index 1e039c4..c353b02 100644 --- a/libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc +++ b/libstdc++-v3/testsuite/19_diagnostics/error_condition/cons/1.cc @@ -21,23 +21,48 @@ #include #include +namespace adl +{ + struct Error { }; + + const Error err; + + struct category : std::error_category + { + const char* name() const noexcept override { return "adl"; } + std::string message(int) const { return ""; } + }; + + const category cat; + + std::error_condition + make_error_condition(Error) { return std::error_condition(999, cat); } +} + +template<> struct std::is_error_condition_enum : std::true_type { }; + void test01() { - // 1 + // 1 error_condition() std::error_condition e1; VERIFY( e1.value() == 0 ); VERIFY( e1.category() == std::generic_category() ); - // 2 + // 2 error_condition(int, const error_category&) const __gnu_test::test_category cat; std::error_condition e2(e1.value(), cat); VERIFY( e2.value() == e1.value() ); VERIFY( e2.category() == cat ); - // 3 + // 3 error_condition(const error_condition&) std::error_condition e3(std::errc::operation_not_supported); VERIFY( e3.value() == int(std::errc::operation_not_supported) ); VERIFY( e3.category() == std::generic_category() ); + + // 4 error_condition(ErrorConditionEnum) + std::error_condition e4(adl::err); + VERIFY( e4.value() == 999 ); + VERIFY( e4.category() == adl::cat ); } int main() -- cgit v1.1 From 390f94eee1ae694901f896ac45bfb148f8126baa Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 26 Aug 2022 15:10:57 -0400 Subject: libstdc++: Optimize std::con/disjunction, __and_/__or_, etc The internal type-level logical operator traits __and_ and __or_ seem to have high overhead for a couple of reasons: 1. They are drop-in replacements for std::con/disjunction, which are rigidly specified to form a type that derives from the first type argument that caused the overall computation to short-circuit. In practice this inheritance property seems to be rarely needed; usually all we care about is the value of the overall result. 2. Their recursive implementations instantiate O(N) class templates and form an inheritance chain of depth O(N). This patch gets rid of this inheritance property of __and_ and __or_ (which seems to be unneeded in the library except indirectly by std::con/disjunction) which allows us to redefine them non-recursively as alias templates that yield either false_type or true_type via enable_if_t and partial ordering of a pair of function templates (alternatively we could use an equivalent partially specialized class template, but using function templates appears to be slightly more efficient). As for std::con/disjunction, it seems we need to keep implementing them via a recursive class template for sake of the inheritance property. But instead of using inheritance recursion, use a recursive member typedef that gets immediately flattened, so that specializations thereof now have O(1) instead of O(N) inheritance depth. In passing, redefine __not_ as an alias template for consistency with __and_ and __or_, and to remove a layer of indirection. Together these changes have a substantial effect on compile time and memory usage for code that heavily uses these internal type traits. For the following example (which tests constructibility between two compatible 257-element tuple types): #include #define M(x) x, x using ty1 = std::tuple; using ty2 = std::tuple; static_assert(std::is_constructible_v); memory usage improves ~27% from 440MB to 320MB and compile time improves ~20% from ~2s to ~1.6s (with -std=c++23). libstdc++-v3/ChangeLog: * include/std/type_traits (enable_if, __enable_if_t): Define them earlier. (__detail::__first_t): Define. (__detail::__or_fn, __detail::__and_fn): Declare. (__or_, __and_): Redefine as alias templates in terms of __or_fn and __and_fn. (__not_): Redefine as an alias template. (__detail::__disjunction_impl, __detail::__conjunction_impl): Define. (conjuction, disjunction): Redefine in terms of __disjunction_impl and __conjunction_impl. --- libstdc++-v3/include/std/type_traits | 130 +++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 59 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 14b029c..c2f5cb9 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -100,6 +100,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Metaprogramming helper types. + // Primary template. + /// Define a member typedef `type` only if a boolean constant is true. + template + struct enable_if + { }; + + // Partial specialization for true. + template + struct enable_if + { typedef _Tp type; }; + + // __enable_if_t (std::enable_if_t for C++11) + template + using __enable_if_t = typename enable_if<_Cond, _Tp>::type; + template struct __conditional { @@ -127,56 +142,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template using __type_identity_t = typename __type_identity<_Tp>::type; - template - struct __or_; - - template<> - struct __or_<> - : public false_type - { }; - - template - struct __or_<_B1> - : public _B1 - { }; - - template - struct __or_<_B1, _B2> - : public __conditional_t<_B1::value, _B1, _B2> - { }; + namespace __detail + { + // A variadic alias template that resolves to its first argument. + template + using __first_t = _Tp; - template - struct __or_<_B1, _B2, _B3, _Bn...> - : public __conditional_t<_B1::value, _B1, __or_<_B2, _B3, _Bn...>> - { }; + // These are deliberately not defined. + template + auto __or_fn(int) -> __first_t...>; - template - struct __and_; + template + auto __or_fn(...) -> true_type; - template<> - struct __and_<> - : public true_type - { }; + template + auto __and_fn(int) -> __first_t...>; - template - struct __and_<_B1> - : public _B1 - { }; + template + auto __and_fn(...) -> false_type; + } // namespace detail - template - struct __and_<_B1, _B2> - : public __conditional_t<_B1::value, _B2, _B1> - { }; + // Like C++17 std::dis/conjunction, but usable in C++11 and resolves + // to either true_type or false_type which allows for a more efficient + // implementation that avoids recursive class template instantiation. + template + using __or_ = decltype(__detail::__or_fn<_Bn...>(0)); - template - struct __and_<_B1, _B2, _B3, _Bn...> - : public __conditional_t<_B1::value, __and_<_B2, _B3, _Bn...>, _B1> - { }; + template + using __and_ = decltype(__detail::__and_fn<_Bn...>(0)); template - struct __not_ - : public __bool_constant - { }; + using __not_ = __bool_constant; /// @endcond #if __cplusplus >= 201703L @@ -186,18 +184,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline constexpr bool __or_v = __or_<_Bn...>::value; template inline constexpr bool __and_v = __and_<_Bn...>::value; + + namespace __detail + { + template + struct __disjunction_impl + { using type = _B1; }; + + template + struct __disjunction_impl<__enable_if_t, _B1, _B2, _Bn...> + { using type = typename __disjunction_impl::type; }; + + template + struct __conjunction_impl + { using type = _B1; }; + + template + struct __conjunction_impl<__enable_if_t, _B1, _B2, _Bn...> + { using type = typename __conjunction_impl::type; }; + } // namespace __detail /// @endcond #define __cpp_lib_logical_traits 201510L template struct conjunction - : __and_<_Bn...> + : __detail::__conjunction_impl::type + { }; + + template<> + struct conjunction<> + : true_type { }; template struct disjunction - : __or_<_Bn...> + : __detail::__disjunction_impl::type + { }; + + template<> + struct disjunction<> + : false_type { }; template @@ -2219,23 +2246,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>; /// @endcond - // Primary template. - /// Define a member typedef `type` only if a boolean constant is true. - template - struct enable_if - { }; - - // Partial specialization for true. - template - struct enable_if - { typedef _Tp type; }; - /// @cond undocumented - // __enable_if_t (std::enable_if_t for C++11) - template - using __enable_if_t = typename enable_if<_Cond, _Tp>::type; - // Helper for SFINAE constraints template using _Require = __enable_if_t<__and_<_Cond...>::value>; -- cgit v1.1 From 1a93a84b9e01d0dd5156be8d686e8666a6fc45a8 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 26 Aug 2022 18:59:20 -0400 Subject: libstdc++: Implement ranges::zip_transform_view from P2321R2 libstdc++-v3/ChangeLog: * include/std/ranges (zip_view::_Iterator): Befriend zip_transform_view. (__detail::__range_iter_cat): Define. (zip_transform_view): Define. (zip_transform_view::_Iterator): Define. (zip_transform_view::_Sentinel): Define. (views::__detail::__can_zip_transform_view): Define. (views::_ZipTransform): Define. (views::zip_transform): Define. * testsuite/std/ranges/zip_transform/1.cc: New test. --- libstdc++-v3/include/std/ranges | 341 +++++++++++++++++++++ .../testsuite/std/ranges/zip_transform/1.cc | 108 +++++++ 2 files changed, 449 insertions(+) create mode 100644 libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index fb815c4..d4e326a 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -4502,6 +4502,12 @@ namespace views::__adaptor return input_iterator_tag{}; } + template + requires (view<_Ws> && ...) && (sizeof...(_Ws) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Ws>...> + && std::__detail::__can_reference...>> + friend class zip_transform_view; + public: // iterator_category defined in __zip_view_iter_cat using iterator_concept = decltype(_S_iter_concept()); @@ -4781,6 +4787,341 @@ namespace views::__adaptor inline constexpr _Zip zip; } + + namespace __detail + { + template + using __range_iter_cat + = typename iterator_traits>>::iterator_category; + } + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference...>> + class zip_transform_view : public view_interface> + { + [[no_unique_address]] __detail::__box<_Fp> _M_fun; + zip_view<_Vs...> _M_zip; + + using _InnerView = zip_view<_Vs...>; + + template + using __ziperator = iterator_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template + using __zentinel = sentinel_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template + using _Base = __detail::__maybe_const_t<_Const, _InnerView>; + + template + struct __iter_cat + { }; + + template + requires forward_range<_Base<_Const>> + struct __iter_cat<_Const> + { + private: + static auto + _S_iter_cat() + { + using __detail::__maybe_const_t; + using __detail::__range_iter_cat; + using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&, + range_reference_t<__maybe_const_t<_Const, _Vs>>...>; + if constexpr (!is_lvalue_reference_v<_Res>) + return input_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + random_access_iterator_tag> && ...)) + return random_access_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + bidirectional_iterator_tag> && ...)) + return bidirectional_iterator_tag{}; + else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, + forward_iterator_tag> && ...)) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + public: + using iterator_category = decltype(_S_iter_cat()); + }; + + template class _Iterator; + template class _Sentinel; + + public: + zip_transform_view() = default; + + constexpr explicit + zip_transform_view(_Fp __fun, _Vs... __views) + : _M_fun(std::move(__fun)), _M_zip(std::move(__views)...) + { } + + constexpr auto + begin() + { return _Iterator(*this, _M_zip.begin()); } + + constexpr auto + begin() const + requires range + && regular_invocable...> + { return _Iterator(*this, _M_zip.begin()); } + + constexpr auto + end() + { + if constexpr (common_range<_InnerView>) + return _Iterator(*this, _M_zip.end()); + else + return _Sentinel(_M_zip.end()); + } + + constexpr auto + end() const + requires range + && regular_invocable...> + { + if constexpr (common_range) + return _Iterator(*this, _M_zip.end()); + else + return _Sentinel(_M_zip.end()); + } + + constexpr auto + size() requires sized_range<_InnerView> + { return _M_zip.size(); } + + constexpr auto + size() const requires sized_range + { return _M_zip.size(); } + }; + + template + zip_transform_view(_Fp, Rs&&...) -> zip_transform_view<_Fp, views::all_t...>; + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference...>> + template + class zip_transform_view<_Fp, _Vs...>::_Iterator : public __iter_cat<_Const> + { + using _Parent = __detail::__maybe_const_t<_Const, zip_transform_view>; + + _Parent* _M_parent = nullptr; + __ziperator<_Const> _M_inner; + + constexpr + _Iterator(_Parent& __parent, __ziperator<_Const> __inner) + : _M_parent(std::__addressof(__parent)), _M_inner(std::move(__inner)) + { } + + friend class zip_transform_view; + + public: + // iterator_category defined in zip_transform_view::__iter_cat + using iterator_concept = typename __ziperator<_Const>::iterator_concept; + using value_type + = remove_cvref_t&, + range_reference_t<__detail::__maybe_const_t<_Const, _Vs>>...>>; + using difference_type = range_difference_t<_Base<_Const>>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to<__ziperator, __ziperator<_Const>> + : _M_parent(__i._M_parent), _M_inner(std::move(__i._M_inner)) + { } + + constexpr decltype(auto) + operator*() const + { + return std::apply([&](const auto&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, *__iters...); + }, _M_inner._M_current); + } + + constexpr _Iterator& + operator++() + { + ++_M_inner; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base<_Const>> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base<_Const>> + { + --_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base<_Const>> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) requires random_access_range<_Base<_Const>> + { + _M_inner += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) requires random_access_range<_Base<_Const>> + { + _M_inner -= __x; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const requires random_access_range<_Base<_Const>> + { + return std::apply([&](const _Is&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, __iters[iter_difference_t<_Is>(__n)]...); + }, _M_inner._M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<__ziperator<_Const>> + { return __x._M_inner == __y._M_inner; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base<_Const>> + { return __x._M_inner < __y._M_inner; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base<_Const>> + { return __x._M_inner > __y._M_inner; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base<_Const>> + { return __x._M_inner <= __y._M_inner; } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base<_Const>> + { return __x._M_inner >= __y._M_inner; } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base<_Const>> && three_way_comparable<__ziperator<_Const>> + { return __x._M_inner <=> __y._M_inner; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base<_Const>> + { return _Iterator(*__i._M_parent, __i._M_inner + __n); } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base<_Const>> + { return _Iterator(*__i._M_parent, __i._M_inner + __n); } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base<_Const>> + { return _Iterator(*__i._M_parent, __i._M_inner - __n); } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for<__ziperator<_Const>, __ziperator<_Const>> + { return __x._M_inner - __y._M_inner; } + }; + + template + requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0) && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vs>...> + && std::__detail::__can_reference...>> + template + class zip_transform_view<_Fp, _Vs...>::_Sentinel + { + __zentinel<_Const> _M_inner; + + constexpr explicit + _Sentinel(__zentinel<_Const> __inner) + : _M_inner(__inner) + { } + + friend class zip_transform_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __i) + requires _Const && convertible_to<__zentinel, __zentinel<_Const>> + : _M_inner(std::move(__i._M_inner)) + { } + + template + requires sentinel_for<__zentinel<_Const>, __ziperator> + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __x._M_inner == __y._M_inner; } + + template + requires sized_sentinel_for<__zentinel<_Const>, __ziperator> + friend constexpr range_difference_t<__detail::__maybe_const_t> + operator-(const _Iterator& __x, const _Sentinel& __y) + { return __x._M_inner - __y._M_inner; } + + template + requires sized_sentinel_for<__zentinel<_Const>, __ziperator> + friend constexpr range_difference_t<__detail::__maybe_const_t> + operator-(const _Sentinel& __x, const _Iterator& __y) + { return __x._M_inner - __y._M_inner; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_zip_transform_view + = requires { zip_transform_view(std::declval<_Fp>(), std::declval<_Ts>()...); }; + } + + struct _ZipTransform + { + template + requires (sizeof...(_Ts) == 0) || __detail::__can_zip_transform_view<_Fp, _Ts...> + [[nodiscard]] + constexpr auto + operator()(_Fp&& __f, _Ts&&... __ts) const + { + if constexpr (sizeof...(_Ts) == 0) + return views::empty>>; + else + return zip_transform_view(std::forward<_Fp>(__f), std::forward<_Ts>(__ts)...); + } + }; + + inline constexpr _ZipTransform zip_transform; + } #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc b/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc new file mode 100644 index 0000000..5ea24c57 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc @@ -0,0 +1,108 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include +#include +#include +#include +#include + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + static_assert(ranges::empty(views::zip_transform([] { return 0; }))); + + auto z1 = views::zip_transform(std::identity{}, + std::array{1, 2, 3}); + VERIFY( ranges::equal(z1, (int[]){1, 2, 3}) ); + const auto i0 = z1.begin(), i1 = z1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < z1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( z1.end() - i1 == 2 ); + VERIFY( i1 - z1.end() == -2 ); + ranges::iter_swap(i0, i1); + VERIFY( ranges::equal(std::move(z1), (int[]){2, 1, 3}) ); + + auto z2 = views::zip_transform(std::multiplies{}, + std::array{-1, 2}, + std::array{3, 4, 5}); + auto i2 = z2.begin(); + i2 += 1; + i2 -= -1; + VERIFY( i2 == z2.end() ); + VERIFY( ranges::size(z2) == 2 ); + VERIFY( ranges::size(std::as_const(z2)) == 2 ); + VERIFY( ranges::equal(z2, (int[]){-3, 8}) ); + + auto z3 = views::zip_transform([] (auto... xs) { return ranges::max({xs...}); }, + std::array{1, 6, 7, 0, 0}, + std::array{2, 5, 9}, + std::array{3, 4, 8, 0}); + VERIFY( ranges::size(z3) == 3 ); + VERIFY( ranges::equal(z3, (int[]){3, 6, 9}) ); + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::zip_transform_view, + views::all_t>, + views::all_t>>; + static_assert(ranges::forward_range); + static_assert(!ranges::random_access_range); + static_assert(!ranges::sized_range); + + using ty2 = ranges::zip_transform_view>, + views::all_t>, + views::all_t>>; + static_assert(ranges::input_range); + static_assert(!ranges::forward_range); + static_assert(!ranges::sized_range); + + return true; +} + +constexpr bool +test03() +{ + int u[] = {1, 2, 3, 4}, v[] = {4, 5, 6}; + auto z = views::zip_transform(std::plus{}, + u | views::filter([](auto) { return true; }), + v); + using ty = decltype(z); + static_assert(ranges::forward_range); + static_assert(!ranges::common_range); + static_assert(!ranges::sized_range); + VERIFY( z.begin() == z.begin() ); + VERIFY( z.begin() != z.end() ); + VERIFY( ranges::next(z.begin(), 3) == z.end() ); + auto it = z.begin(); + ++it; + it++; + it--; + --it; + VERIFY( it == z.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +} -- cgit v1.1 From d0fd62d0ff4d1e0648e11b650b4f449772663990 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 26 Aug 2022 18:59:36 -0400 Subject: libstdc++: Implement LWG 3692/3702 changes to zip_/zip_transform_view libstdc++-v3/ChangeLog: * include/std/ranges (zip_view::_Iterator::operator<): Remove as per LWG 3692. (zip_view::_Iterator::operator>): Likewise. (zip_view::_Iterator::operator<=): Likewise. (zip_view::_Iterator::operator>=): Likewise. (zip_view::_Iterator::operator<=>): Remove three_way_comparable constraint as per LWG 3692. (zip_transform_view::_Iterator): Ditto as per LWG 3702. --- libstdc++-v3/include/std/ranges | 43 +---------------------------------------- 1 file changed, 1 insertion(+), 42 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index d4e326a..6e2e561 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -4616,30 +4616,9 @@ namespace views::__adaptor }(make_index_sequence{}); } - friend constexpr bool - operator<(const _Iterator& __x, const _Iterator& __y) - requires __detail::__all_random_access<_Const, _Vs...> - { return __x._M_current < __y._M_current; } - - friend constexpr bool - operator>(const _Iterator& __x, const _Iterator& __y) - requires __detail::__all_random_access<_Const, _Vs...> - { return __y < __x; } - - friend constexpr bool - operator<=(const _Iterator& __x, const _Iterator& __y) - requires __detail::__all_random_access<_Const, _Vs...> - { return !(__y < __x); } - - friend constexpr bool - operator>=(const _Iterator& __x, const _Iterator& __y) - requires __detail::__all_random_access<_Const, _Vs...> - { return !(__x < __y); } - friend constexpr auto operator<=>(const _Iterator& __x, const _Iterator& __y) requires __detail::__all_random_access<_Const, _Vs...> - && (three_way_comparable>> && ...) { return __x._M_current <=> __y._M_current; } friend constexpr _Iterator @@ -5006,29 +4985,9 @@ namespace views::__adaptor requires equality_comparable<__ziperator<_Const>> { return __x._M_inner == __y._M_inner; } - friend constexpr bool - operator<(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base<_Const>> - { return __x._M_inner < __y._M_inner; } - - friend constexpr bool - operator>(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base<_Const>> - { return __x._M_inner > __y._M_inner; } - - friend constexpr bool - operator<=(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base<_Const>> - { return __x._M_inner <= __y._M_inner; } - - friend constexpr bool - operator>=(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base<_Const>> - { return __x._M_inner >= __y._M_inner; } - friend constexpr auto operator<=>(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base<_Const>> && three_way_comparable<__ziperator<_Const>> + requires random_access_range<_Base<_Const>> { return __x._M_inner <=> __y._M_inner; } friend constexpr _Iterator -- cgit v1.1 From 16f542d6b866828e23e699e294e617ca428b04ee Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 27 Aug 2022 00:17:09 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 1b20d4e..4ef6242 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,69 @@ +2022-08-26 Patrick Palka + + * include/std/ranges (zip_view::_Iterator::operator<): Remove + as per LWG 3692. + (zip_view::_Iterator::operator>): Likewise. + (zip_view::_Iterator::operator<=): Likewise. + (zip_view::_Iterator::operator>=): Likewise. + (zip_view::_Iterator::operator<=>): Remove three_way_comparable + constraint as per LWG 3692. + (zip_transform_view::_Iterator): Ditto as per LWG 3702. + +2022-08-26 Patrick Palka + + * include/std/ranges (zip_view::_Iterator): Befriend + zip_transform_view. + (__detail::__range_iter_cat): Define. + (zip_transform_view): Define. + (zip_transform_view::_Iterator): Define. + (zip_transform_view::_Sentinel): Define. + (views::__detail::__can_zip_transform_view): Define. + (views::_ZipTransform): Define. + (views::zip_transform): Define. + * testsuite/std/ranges/zip_transform/1.cc: New test. + +2022-08-26 Patrick Palka + + * include/std/type_traits (enable_if, __enable_if_t): Define them + earlier. + (__detail::__first_t): Define. + (__detail::__or_fn, __detail::__and_fn): Declare. + (__or_, __and_): Redefine as alias templates in terms of __or_fn + and __and_fn. + (__not_): Redefine as an alias template. + (__detail::__disjunction_impl, __detail::__conjunction_impl): + Define. + (conjuction, disjunction): Redefine in terms of __disjunction_impl + and __conjunction_impl. + +2022-08-26 Jonathan Wakely + + * include/std/system_error (error_code::_Check): New alias + template for constructor SFINAE constraint. + (error_code::error_code(ErrorCodeEnum)): Use it. + (error_code::operator=(ErrorCodeEnum)): Remove. + (error_condition::_Check): New alias template for constraint. + (error_condition::error_condition(ErrorConditionEnum)): Use it. + (error_condition::operator=(ErrorConditionEnum)): Remove. + * testsuite/19_diagnostics/error_code/cons/1.cc: Check + constructor taking user-defined error enum. + * testsuite/19_diagnostics/error_condition/cons/1.cc: Likewise. + +2022-08-26 Jonathan Wakely + + * include/bits/basic_string.h (starts_with, ends_with, contains): + Add nonnull attribute. + * include/bits/cow_string.h (starts_with, ends_with, contains): + Likewise. + * include/std/string_view (starts_with, ends_with, contains): + Likewise. + * testsuite/21_strings/basic_string/operations/contains/nonnull.cc + * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc + * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc + * testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc + * testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc + * testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc + 2022-08-25 Patrick Palka * include/std/ranges (lazy_split_view::_OuterIter::_M_current): -- cgit v1.1 From cace77f4fb8df18c01dfdf9040cc944eedef1147 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Sat, 27 Aug 2022 10:15:55 -0400 Subject: libstdc++: Add test for std::con/disjunction's base class libstdc++-v3/ChangeLog: * testsuite/20_util/logical_traits/requirements/base_classes.cc: New test. --- .../logical_traits/requirements/base_classes.cc | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 libstdc++-v3/testsuite/20_util/logical_traits/requirements/base_classes.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/base_classes.cc b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/base_classes.cc new file mode 100644 index 0000000..9067a3b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/base_classes.cc @@ -0,0 +1,34 @@ +// { dg-do compile { target c++17 } } + +#include + +template struct T : std::true_type { }; +template struct F : std::false_type { }; + +// [meta.logical]/5: The specialization conjunction has a +// public and unambiguous base that is either: +// - the first type B_i in the list true_type, B_1, ..., B_n for which +// bool(B_i::value) is false, or +// - if there is no such B_i, the last type in the list. + +static_assert(std::is_base_of_v>); +static_assert(std::is_base_of_v, std::conjunction>>); +static_assert(std::is_base_of_v, std::conjunction>>); +static_assert(std::is_base_of_v, std::conjunction, T<1>>>); +static_assert(std::is_base_of_v, std::conjunction, F<1>>>); +static_assert(std::is_base_of_v, std::conjunction, F<0>, F<1>>>); +static_assert(std::is_base_of_v, std::conjunction, F<0>, T<1>, F<1>>>); + +// [meta.logical]/10: The specialization disjunction has a +// public and unambiguous base that is either: +// - the first type B_i in the list false_type, B_1, ..., B_n for which +// bool(B_i::value) is true, or +// - if there is no such B_i, the last type in the list. + +static_assert(std::is_base_of_v>); +static_assert(std::is_base_of_v, std::disjunction>>); +static_assert(std::is_base_of_v, std::disjunction>>); +static_assert(std::is_base_of_v, std::disjunction, T<1>>>); +static_assert(std::is_base_of_v, std::disjunction, F<1>>>); +static_assert(std::is_base_of_v, std::disjunction, F<0>, F<1>>>); +static_assert(std::is_base_of_v, std::disjunction, F<0>, T<1>, F<1>>>); -- cgit v1.1 From 6b226ef735f05264cdb51e3bc754d1b178108e3f Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 28 Aug 2022 00:16:28 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4ef6242..ba5939d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,7 @@ +2022-08-27 Patrick Palka + + * testsuite/20_util/logical_traits/requirements/base_classes.cc: New test. + 2022-08-26 Patrick Palka * include/std/ranges (zip_view::_Iterator::operator<): Remove -- cgit v1.1 From b911ca4231a366ddfd026f190b126bd517f4e640 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 26 Aug 2022 16:22:21 +0100 Subject: libstdc++: Add [[nodiscard]] attribute to and libstdc++-v3/ChangeLog: * include/bits/basic_string.h (basic_string): Add nodiscard attribute to all relevant functions. * include/std/string_view (basic_string_view): Likewise. * testsuite/21_strings/basic_string/capacity/1.cc: Cast unused results to void. * testsuite/21_strings/basic_string/capacity/char/1.cc: Likewise. * testsuite/21_strings/basic_string/capacity/wchar_t/1.cc: Likewise. * testsuite/21_strings/basic_string/cons/char/self_move.cc: Likewise. * testsuite/21_strings/basic_string/element_access/char/1.cc: Likewise. * testsuite/21_strings/basic_string/element_access/char/21674.cc: Likewise. * testsuite/21_strings/basic_string/element_access/wchar_t/1.cc: Likewise. * testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc: Likewise. * testsuite/21_strings/basic_string/lwg2758.cc: Likewise. * testsuite/21_strings/basic_string/lwg2946.cc: Likewise. * testsuite/21_strings/basic_string/operations/contains/nonnull.cc: Add -Wno-unused-result to options. * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc: Likewise. * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc: Likewise. * testsuite/21_strings/basic_string/operators/char/1.cc: Cast unused results to void. * testsuite/21_strings/basic_string/operators/wchar_t/1.cc: Likewise. * testsuite/21_strings/basic_string_view/capacity/1.cc: Likewise. * testsuite/21_strings/basic_string_view/element_access/char/1.cc: Likewise. * testsuite/21_strings/basic_string_view/element_access/char/2.cc: Likewise. * testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc: Likewise. * testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc: Likewise. * testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc: Likewise. Add -Wno-unused-result to options. * testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc: Likewise. * testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc: Likewise. * testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc: Cast unused results to void. * testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc: Likewise. * testsuite/27_io/basic_stringbuf/sungetc/char/1.cc: Likewise. * testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc: Likewise. --- libstdc++-v3/include/bits/basic_string.h | 211 +++++++++++++-------- libstdc++-v3/include/std/string_view | 107 +++++++++-- .../21_strings/basic_string/capacity/1.cc | 2 +- .../21_strings/basic_string/capacity/char/1.cc | 6 +- .../21_strings/basic_string/capacity/wchar_t/1.cc | 6 +- .../21_strings/basic_string/cons/char/self_move.cc | 2 +- .../basic_string/element_access/char/1.cc | 4 +- .../basic_string/element_access/char/21674.cc | 2 +- .../basic_string/element_access/wchar_t/1.cc | 4 +- .../basic_string/element_access/wchar_t/21674.cc | 2 +- .../testsuite/21_strings/basic_string/lwg2758.cc | 4 +- .../testsuite/21_strings/basic_string/lwg2946.cc | 16 +- .../basic_string/operations/contains/nonnull.cc | 2 +- .../basic_string/operations/ends_with/nonnull.cc | 2 +- .../basic_string/operations/starts_with/nonnull.cc | 2 +- .../21_strings/basic_string/operators/char/1.cc | 4 +- .../21_strings/basic_string/operators/wchar_t/1.cc | 4 +- .../21_strings/basic_string_view/capacity/1.cc | 2 +- .../basic_string_view/element_access/char/1.cc | 2 +- .../basic_string_view/element_access/char/2.cc | 2 +- .../basic_string_view/element_access/wchar_t/1.cc | 2 +- .../basic_string_view/element_access/wchar_t/2.cc | 2 +- .../operations/contains/nonnull.cc | 2 +- .../operations/ends_with/nonnull.cc | 2 +- .../operations/starts_with/nonnull.cc | 2 +- .../27_io/basic_stringbuf/sputbackc/char/1.cc | 10 +- .../27_io/basic_stringbuf/sputbackc/wchar_t/1.cc | 10 +- .../27_io/basic_stringbuf/sungetc/char/1.cc | 10 +- .../27_io/basic_stringbuf/sungetc/wchar_t/1.cc | 10 +- 29 files changed, 279 insertions(+), 157 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 9d8b415..0df64ea 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -942,7 +942,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write iterator that points to the first character in * the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR iterator begin() _GLIBCXX_NOEXCEPT { return iterator(_M_data()); } @@ -951,7 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points to the first * character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_iterator begin() const _GLIBCXX_NOEXCEPT { return const_iterator(_M_data()); } @@ -960,7 +960,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write iterator that points one past the last * character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR iterator end() _GLIBCXX_NOEXCEPT { return iterator(_M_data() + this->size()); } @@ -969,7 +969,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points one past the * last character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_iterator end() const _GLIBCXX_NOEXCEPT { return const_iterator(_M_data() + this->size()); } @@ -979,7 +979,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * character in the %string. Iteration is done in reverse element * order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reverse_iterator rbegin() _GLIBCXX_NOEXCEPT { return reverse_iterator(this->end()); } @@ -989,7 +989,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to the last character in the %string. Iteration is done in * reverse element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reverse_iterator rbegin() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(this->end()); } @@ -999,7 +999,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first character in the %string. Iteration is done in reverse * element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reverse_iterator rend() _GLIBCXX_NOEXCEPT { return reverse_iterator(this->begin()); } @@ -1009,7 +1009,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to one before the first character in the %string. Iteration * is done in reverse element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reverse_iterator rend() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(this->begin()); } @@ -1019,7 +1019,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points to the first * character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_iterator cbegin() const noexcept { return const_iterator(this->_M_data()); } @@ -1028,7 +1028,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points one past the * last character in the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_iterator cend() const noexcept { return const_iterator(this->_M_data() + this->size()); } @@ -1038,7 +1038,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to the last character in the %string. Iteration is done in * reverse element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(this->end()); } @@ -1048,7 +1048,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to one before the first character in the %string. Iteration * is done in reverse element order. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reverse_iterator crend() const noexcept { return const_reverse_iterator(this->begin()); } @@ -1058,20 +1058,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // Capacity: /// Returns the number of characters in the string, not including any /// null-termination. - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type size() const _GLIBCXX_NOEXCEPT { return _M_string_length; } /// Returns the number of characters in the string, not including any /// null-termination. - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type length() const _GLIBCXX_NOEXCEPT { return _M_string_length; } /// Returns the size() of the largest possible %string. - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type max_size() const _GLIBCXX_NOEXCEPT { return (_Alloc_traits::max_size(_M_get_allocator()) - 1) / 2; } @@ -1127,7 +1127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns the total number of characters that the %string can hold * before needing to allocate more memory. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type capacity() const _GLIBCXX_NOEXCEPT { @@ -1194,7 +1194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range lookups are not defined. (For checked lookups * see at().) */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reference operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT { @@ -1212,7 +1212,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range lookups are not defined. (For checked lookups * see at().) */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reference operator[](size_type __pos) { @@ -1234,7 +1234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first checked that it is in the range of the string. The function * throws out_of_range if the check fails. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reference at(size_type __n) const { @@ -1256,7 +1256,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first checked that it is in the range of the string. The function * throws out_of_range if the check fails. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reference at(size_type __n) { @@ -1273,7 +1273,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write reference to the data at the first * element of the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reference front() noexcept { @@ -1285,7 +1285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) reference to the data at the first * element of the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reference front() const noexcept { @@ -1297,7 +1297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write reference to the data at the last * element of the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR reference back() noexcept { @@ -1309,7 +1309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) reference to the data at the * last element of the %string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const_reference back() const noexcept { @@ -2549,7 +2549,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This is a handle to internal data. Do not modify or dire things may * happen. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const _CharT* c_str() const _GLIBCXX_NOEXCEPT { return _M_data(); } @@ -2562,7 +2562,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * allows modifying the contents use @c &str[0] instead, * (or in C++17 the non-const @c str.data() overload). */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR const _CharT* data() const _GLIBCXX_NOEXCEPT { return _M_data(); } @@ -2574,7 +2574,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This is a pointer to the character sequence held by the string. * Modifying the characters in the sequence is allowed. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _CharT* data() noexcept { return _M_data(); } @@ -2583,7 +2583,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Return copy of allocator used to construct this string. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return _M_get_allocator(); } @@ -2600,7 +2600,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it begins. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2615,7 +2615,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it begins. If not * found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2629,7 +2629,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of first occurrence. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2649,7 +2649,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * __s within this string. If found, returns the index where * it begins. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { @@ -2667,7 +2667,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT; @@ -2681,7 +2681,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * __str within this string. If found, returns the index where * it begins. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type rfind(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2695,7 +2695,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of last occurrence. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> rfind(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2717,7 +2717,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it begins. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2732,7 +2732,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @a __s within this string. If found, returns the index * where it begins. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type rfind(const _CharT* __s, size_type __pos = npos) const { @@ -2750,7 +2750,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT; @@ -2765,7 +2765,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2780,7 +2780,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of first occurrence. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_first_of(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2802,7 +2802,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * found, returns the index where it was found. If not found, * returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2817,7 +2817,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * characters of @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_of(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2838,7 +2838,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * Note: equivalent to find(__c, __pos). */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { return this->find(__c, __pos); } @@ -2854,7 +2854,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2869,7 +2869,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of last occurrence. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_last_of(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2891,7 +2891,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * found, returns the index where it was found. If not found, * returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2906,7 +2906,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * characters of @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_of(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2927,7 +2927,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * Note: equivalent to rfind(__c, __pos). */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT { return this->rfind(__c, __pos); } @@ -2942,7 +2942,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * in @a __str within this string. If found, returns the index where it * was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2957,8 +2957,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of first occurrence. */ template + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> - _GLIBCXX20_CONSTEXPR find_first_not_of(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) { @@ -2979,7 +2979,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2994,7 +2994,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * contained in @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -3013,7 +3013,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * other than @a __c within this string. If found, returns the * index where it was found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_first_not_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT; @@ -3029,7 +3029,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -3044,7 +3044,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of last occurrence. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_last_not_of(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -3066,7 +3066,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If found, returns the index where it was found. If not found, * returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -3081,7 +3081,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -3100,7 +3100,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @a __c within this string. If found, returns the index where it was * found. If not found, returns npos. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR size_type find_last_not_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT; @@ -3117,7 +3117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * short, use the remainder of the characters. If @a __pos is * beyond the end of the string, out_of_range is thrown. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR basic_string substr(size_type __pos = 0, size_type __n = npos) const { return basic_string(*this, @@ -3137,7 +3137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If the result of the comparison is nonzero returns it, * otherwise the shorter one is ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(const basic_string& __str) const { @@ -3158,7 +3158,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(const _Tp& __svt) const noexcept(is_same<_Tp, __sv_type>::value) @@ -3183,7 +3183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(size_type __pos, size_type __n, const _Tp& __svt) const noexcept(is_same<_Tp, __sv_type>::value) @@ -3203,7 +3203,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) const @@ -3234,7 +3234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * result of the comparison is nonzero returns it, otherwise * the shorter one is ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n, const basic_string& __str) const { @@ -3271,7 +3271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If the result of the comparison is nonzero returns it, * otherwise the shorter one is ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) const @@ -3302,7 +3302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * comparison is nonzero returns it, otherwise the shorter one is * ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT { @@ -3337,7 +3337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * the comparison is nonzero returns it, otherwise the shorter * one is ordered first. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n1, const _CharT* __s) const { @@ -3376,7 +3376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * NB: s must have at least n2 characters, '\\0' has * no special meaning. */ - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2) const @@ -3392,43 +3392,49 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } #if __cplusplus >= 202002L + [[nodiscard]] constexpr bool starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } + [[nodiscard]] constexpr bool starts_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } - [[__gnu__::__nonnull__]] + [[nodiscard, __gnu__::__nonnull__]] constexpr bool starts_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } + [[nodiscard]] constexpr bool ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } + [[nodiscard]] constexpr bool ends_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } - [[__gnu__::__nonnull__]] + [[nodiscard, __gnu__::__nonnull__]] constexpr bool ends_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } #endif // C++20 #if __cplusplus > 202002L + [[nodiscard]] constexpr bool contains(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } + [[nodiscard]] constexpr bool contains(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } - [[__gnu__::__nonnull__]] + [[nodiscard, __gnu__::__nonnull__]] constexpr bool contains(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } @@ -3483,7 +3489,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with value of @a __lhs followed by @a __rhs. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3500,7 +3506,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with value of @a __lhs followed by @a __rhs. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR basic_string<_CharT,_Traits,_Alloc> operator+(const _CharT* __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs); @@ -3512,7 +3518,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR basic_string<_CharT,_Traits,_Alloc> operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs); @@ -3523,7 +3529,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3540,7 +3546,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs) { @@ -3553,7 +3559,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus >= 201103L template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3567,7 +3573,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 { return std::move(__rhs.insert(0, __lhs)); } template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) @@ -3590,28 +3596,28 @@ _GLIBCXX_END_NAMESPACE_CXX11 } template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const _CharT* __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { return std::move(__rhs.insert(0, __lhs)); } template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(_CharT __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { return std::move(__rhs.insert(0, 1, __lhs)); } template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, const _CharT* __rhs) { return std::move(__lhs.append(__rhs)); } template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, _CharT __rhs) @@ -3626,7 +3632,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline bool operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3643,7 +3649,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise. */ template - _GLIBCXX20_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline bool operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3661,6 +3667,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * greater than, or incomparable with `__rhs`. */ template + [[nodiscard]] constexpr auto operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) noexcept @@ -3675,6 +3682,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * greater than, or incomparable with `__rhs`. */ template + [[nodiscard]] constexpr auto operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) noexcept @@ -3688,6 +3696,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __rhs.compare(@a __lhs) == 0. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator==(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3701,6 +3710,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3714,6 +3724,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __rhs.compare(@a __lhs) != 0. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator!=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3726,6 +3737,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) != 0. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3739,6 +3751,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs precedes @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3752,6 +3765,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs precedes @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3764,6 +3778,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs precedes @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator<(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3777,6 +3792,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs follows @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3790,6 +3806,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs follows @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3802,6 +3819,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs follows @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator>(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3815,6 +3833,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3828,6 +3847,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3840,6 +3860,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't follow @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator<=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3853,6 +3874,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3866,6 +3888,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3878,6 +3901,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs doesn't precede @a __rhs. False otherwise. */ template + _GLIBCXX_NODISCARD inline bool operator>=(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -4060,6 +4084,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // DR 1261. Insufficent overloads for to_string / to_wstring + _GLIBCXX_NODISCARD inline string to_string(int __val) #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_INT__) <= 32 @@ -4074,6 +4099,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(unsigned __val) #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_INT__) <= 32 @@ -4085,6 +4111,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(long __val) #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_LONG__) <= 32 @@ -4099,6 +4126,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(unsigned long __val) #if _GLIBCXX_USE_CXX11_ABI && (__CHAR_BIT__ * __SIZEOF_LONG__) <= 32 @@ -4110,6 +4138,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(long long __val) { @@ -4122,6 +4151,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __str; } + _GLIBCXX_NODISCARD inline string to_string(unsigned long long __val) { @@ -4133,6 +4163,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if _GLIBCXX_USE_C99_STDIO // NB: (v)snprintf vs sprintf. + _GLIBCXX_NODISCARD inline string to_string(float __val) { @@ -4142,6 +4173,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 "%f", __val); } + _GLIBCXX_NODISCARD inline string to_string(double __val) { @@ -4151,6 +4183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 "%f", __val); } + _GLIBCXX_NODISCARD inline string to_string(long double __val) { @@ -4202,40 +4235,47 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF // DR 1261. + _GLIBCXX_NODISCARD inline wstring to_wstring(int __val) { return __gnu_cxx::__to_xstring(&std::vswprintf, 4 * sizeof(int), L"%d", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(unsigned __val) { return __gnu_cxx::__to_xstring(&std::vswprintf, 4 * sizeof(unsigned), L"%u", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(long __val) { return __gnu_cxx::__to_xstring(&std::vswprintf, 4 * sizeof(long), L"%ld", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(unsigned long __val) { return __gnu_cxx::__to_xstring(&std::vswprintf, 4 * sizeof(unsigned long), L"%lu", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(long long __val) { return __gnu_cxx::__to_xstring(&std::vswprintf, 4 * sizeof(long long), L"%lld", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(unsigned long long __val) { return __gnu_cxx::__to_xstring(&std::vswprintf, 4 * sizeof(unsigned long long), L"%llu", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(float __val) { @@ -4245,6 +4285,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 L"%f", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(double __val) { @@ -4254,6 +4295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 L"%f", __val); } + _GLIBCXX_NODISCARD inline wstring to_wstring(long double __val) { @@ -4287,6 +4329,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __str_hash_base : public __hash_base { + [[__nodiscard__]] size_t operator()(const _StrT& __s) const noexcept { return _Hash_impl::hash(__s.data(), __s.length() * sizeof(_CharT)); } diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index 5b96ffe..2604af2 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -129,7 +129,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr basic_string_view(const basic_string_view&) noexcept = default; - __attribute__((__nonnull__)) constexpr + [[__gnu__::__nonnull__]] + constexpr basic_string_view(const _CharT* __str) noexcept : _M_len{traits_type::length(__str)}, _M_str{__str} @@ -172,54 +173,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // C++23 #endif // C++20 - constexpr basic_string_view& operator=(const basic_string_view&) noexcept = default; // [string.view.iterators], iterator support + [[nodiscard]] constexpr const_iterator begin() const noexcept { return this->_M_str; } + [[nodiscard]] constexpr const_iterator end() const noexcept { return this->_M_str + this->_M_len; } + [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return this->_M_str; } + [[nodiscard]] constexpr const_iterator cend() const noexcept { return this->_M_str + this->_M_len; } + [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(this->end()); } + [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(this->begin()); } + [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(this->end()); } + [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(this->begin()); } // [string.view.capacity], capacity + [[nodiscard]] constexpr size_type size() const noexcept { return this->_M_len; } + [[nodiscard]] constexpr size_type length() const noexcept { return _M_len; } + [[nodiscard]] constexpr size_type max_size() const noexcept { @@ -227,12 +238,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION / sizeof(value_type) / 4; } - [[nodiscard]] constexpr bool + [[nodiscard]] + constexpr bool empty() const noexcept { return this->_M_len == 0; } // [string.view.access], element access + [[nodiscard]] constexpr const_reference operator[](size_type __pos) const noexcept { @@ -240,6 +253,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_str + __pos); } + [[nodiscard]] constexpr const_reference at(size_type __pos) const { @@ -250,6 +264,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_str + __pos); } + [[nodiscard]] constexpr const_reference front() const noexcept { @@ -257,6 +272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this->_M_str; } + [[nodiscard]] constexpr const_reference back() const noexcept { @@ -264,6 +280,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_str + this->_M_len - 1); } + [[nodiscard]] constexpr const_pointer data() const noexcept { return this->_M_str; } @@ -305,6 +322,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __rlen; } + [[nodiscard]] constexpr basic_string_view substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) { @@ -313,6 +331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return basic_string_view{_M_str + __pos, __rlen}; } + [[nodiscard]] constexpr int compare(basic_string_view __str) const noexcept { @@ -323,10 +342,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __ret; } + [[nodiscard]] constexpr int compare(size_type __pos1, size_type __n1, basic_string_view __str) const { return this->substr(__pos1, __n1).compare(__str); } + [[nodiscard]] constexpr int compare(size_type __pos1, size_type __n1, basic_string_view __str, size_type __pos2, size_type __n2) const @@ -334,14 +355,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); } - __attribute__((__nonnull__)) constexpr int + [[nodiscard, __gnu__::__nonnull__]] + constexpr int compare(const _CharT* __str) const noexcept { return this->compare(basic_string_view{__str}); } - __attribute__((__nonnull__)) constexpr int + [[nodiscard, __gnu__::__nonnull__]] + constexpr int compare(size_type __pos1, size_type __n1, const _CharT* __str) const { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } + [[nodiscard]] constexpr int compare(size_type __pos1, size_type __n1, const _CharT* __str, size_type __n2) const noexcept(false) @@ -352,19 +376,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus > 201703L #define __cpp_lib_starts_ends_with 201711L + [[nodiscard]] constexpr bool starts_with(basic_string_view __x) const noexcept { return this->substr(0, __x.size()) == __x; } + [[nodiscard]] constexpr bool starts_with(_CharT __x) const noexcept { return !this->empty() && traits_type::eq(this->front(), __x); } - [[__gnu__::__nonnull__]] + [[nodiscard, __gnu__::__nonnull__]] constexpr bool starts_with(const _CharT* __x) const noexcept { return this->starts_with(basic_string_view(__x)); } + [[nodiscard]] constexpr bool ends_with(basic_string_view __x) const noexcept { @@ -374,11 +401,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && traits_type::compare(end() - __xlen, __x.data(), __xlen) == 0; } + [[nodiscard]] constexpr bool ends_with(_CharT __x) const noexcept { return !this->empty() && traits_type::eq(this->back(), __x); } - [[__gnu__::__nonnull__]] + [[nodiscard, __gnu__::__nonnull__]] constexpr bool ends_with(const _CharT* __x) const noexcept { return this->ends_with(basic_string_view(__x)); } @@ -386,15 +414,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus > 202002L #define __cpp_lib_string_contains 202011L + [[nodiscard]] constexpr bool contains(basic_string_view __x) const noexcept { return this->find(__x) != npos; } + [[nodiscard]] constexpr bool contains(_CharT __x) const noexcept { return this->find(__x) != npos; } - [[__gnu__::__nonnull__]] + [[nodiscard, __gnu__::__nonnull__]] constexpr bool contains(const _CharT* __x) const noexcept { return this->find(__x) != npos; } @@ -402,99 +432,123 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [string.view.find], searching + [[nodiscard]] constexpr size_type find(basic_string_view __str, size_type __pos = 0) const noexcept { return this->find(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find(_CharT __c, size_type __pos = 0) const noexcept; + [[nodiscard]] constexpr size_type find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find(const _CharT* __str, size_type __pos = 0) const noexcept { return this->find(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type rfind(basic_string_view __str, size_type __pos = npos) const noexcept { return this->rfind(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type rfind(_CharT __c, size_type __pos = npos) const noexcept; + [[nodiscard]] constexpr size_type rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type rfind(const _CharT* __str, size_type __pos = npos) const noexcept { return this->rfind(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept { return this->find_first_of(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find_first_of(_CharT __c, size_type __pos = 0) const noexcept { return this->find(__c, __pos); } + [[nodiscard]] constexpr size_type find_first_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept { return this->find_first_of(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type find_last_of(basic_string_view __str, size_type __pos = npos) const noexcept { return this->find_last_of(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find_last_of(_CharT __c, size_type __pos=npos) const noexcept { return this->rfind(__c, __pos); } + [[nodiscard]] constexpr size_type find_last_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept { return this->find_last_of(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type find_first_not_of(basic_string_view __str, size_type __pos = 0) const noexcept { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; + [[nodiscard]] constexpr size_type find_first_not_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept { return this->find_first_not_of(__str, __pos, traits_type::length(__str)); } + [[nodiscard]] constexpr size_type find_last_not_of(basic_string_view __str, size_type __pos = npos) const noexcept { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } + [[nodiscard]] constexpr size_type find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; + [[nodiscard]] constexpr size_type find_last_not_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - __attribute__((__nonnull__)) constexpr size_type + [[nodiscard, __gnu__::__nonnull__]] + constexpr size_type find_last_not_of(const _CharT* __str, size_type __pos = npos) const noexcept { @@ -539,12 +593,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // type (see N3766). template + [[nodiscard]] constexpr bool operator==(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.size() == __y.size() && __x.compare(__y) == 0; } template + [[nodiscard]] constexpr bool operator==(basic_string_view<_CharT, _Traits> __x, __type_identity_t> __y) @@ -553,6 +609,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cpp_lib_three_way_comparison template + [[nodiscard]] constexpr auto operator<=>(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept @@ -560,6 +617,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } template + [[nodiscard]] constexpr auto operator<=>(basic_string_view<_CharT, _Traits> __x, __type_identity_t> __y) @@ -568,18 +626,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } #else template + [[nodiscard]] constexpr bool operator==(__type_identity_t> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.size() == __y.size() && __x.compare(__y) == 0; } template + [[nodiscard]] constexpr bool operator!=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return !(__x == __y); } template + [[nodiscard]] constexpr bool operator!=(basic_string_view<_CharT, _Traits> __x, __type_identity_t> __y) @@ -587,18 +648,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !(__x == __y); } template + [[nodiscard]] constexpr bool operator!=(__type_identity_t> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return !(__x == __y); } template + [[nodiscard]] constexpr bool operator< (basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) < 0; } template + [[nodiscard]] constexpr bool operator< (basic_string_view<_CharT, _Traits> __x, __type_identity_t> __y) @@ -606,18 +670,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.compare(__y) < 0; } template + [[nodiscard]] constexpr bool operator< (__type_identity_t> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) < 0; } template + [[nodiscard]] constexpr bool operator> (basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) > 0; } template + [[nodiscard]] constexpr bool operator> (basic_string_view<_CharT, _Traits> __x, __type_identity_t> __y) @@ -625,18 +692,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.compare(__y) > 0; } template + [[nodiscard]] constexpr bool operator> (__type_identity_t> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) > 0; } template + [[nodiscard]] constexpr bool operator<=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) <= 0; } template + [[nodiscard]] constexpr bool operator<=(basic_string_view<_CharT, _Traits> __x, __type_identity_t> __y) @@ -644,18 +714,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.compare(__y) <= 0; } template + [[nodiscard]] constexpr bool operator<=(__type_identity_t> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) <= 0; } template + [[nodiscard]] constexpr bool operator>=(basic_string_view<_CharT, _Traits> __x, basic_string_view<_CharT, _Traits> __y) noexcept { return __x.compare(__y) >= 0; } template + [[nodiscard]] constexpr bool operator>=(basic_string_view<_CharT, _Traits> __x, __type_identity_t> __y) @@ -663,6 +736,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x.compare(__y) >= 0; } template + [[nodiscard]] constexpr bool operator>=(__type_identity_t> __x, basic_string_view<_CharT, _Traits> __y) noexcept @@ -696,6 +770,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash : public __hash_base { + [[nodiscard]] size_t operator()(const string_view& __str) const noexcept { return std::_Hash_impl::hash(__str.data(), __str.length()); } @@ -709,6 +784,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash : public __hash_base { + [[nodiscard]] size_t operator()(const wstring_view& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), @@ -724,6 +800,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash : public __hash_base { + [[nodiscard]] size_t operator()(const u8string_view& __str) const noexcept { return std::_Hash_impl::hash(__str.data(), __str.length()); } @@ -738,6 +815,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash : public __hash_base { + [[nodiscard]] size_t operator()(const u16string_view& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), @@ -752,6 +830,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct hash : public __hash_base { + [[nodiscard]] size_t operator()(const u32string_view& __s) const noexcept { return std::_Hash_impl::hash(__s.data(), diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc index 45af457..1ae4d3d 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/1.cc @@ -175,7 +175,7 @@ void test01() sz03 = str02.size(); sz04 = str02.length(); VERIFY( sz03 == sz04 ); - str02.c_str(); + (void) str02.c_str(); sz03 = str02.size(); sz04 = str02.length(); VERIFY( sz03 == sz04 ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc index 244a795..1da273b 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/char/1.cc @@ -74,15 +74,15 @@ void test01() sz01 = str01.size(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); - str01.c_str(); + (void) str01.c_str(); sz01 = str01.size(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); sz01 = str01.length(); - str01.c_str(); + (void) str01.c_str(); str011 = str01 + "_addendum_"; - str01.c_str(); + (void) str01.c_str(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); sz02 = str011.length(); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc index 5cb682e..6f03e34 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/capacity/wchar_t/1.cc @@ -71,15 +71,15 @@ void test01() sz01 = str01.size(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); - str01.c_str(); + (void) str01.c_str(); sz01 = str01.size(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); sz01 = str01.length(); - str01.c_str(); + (void) str01.c_str(); str011 = str01 + L"_addendum_"; - str01.c_str(); + (void) str01.c_str(); sz02 = str01.length(); VERIFY( sz01 == sz02 ); sz02 = str011.length(); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc index d37fe39..ddd9aea 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/self_move.cc @@ -32,7 +32,7 @@ test(const char* s) String s3 __attribute__((unused)) = s1; s1 = std::move(s1); - s1.begin(); // causes COW string to "leak" + (void) s1.begin(); // causes COW string to "leak" s1 = std::move(s1); String s4 __attribute__((unused)) = s1; diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/1.cc index 7fb4323..5a176c0 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/1.cc @@ -53,7 +53,7 @@ void test01(void) cref cref3 = str01.at(csz01 - 1); VERIFY( cref3 == 'a' ); try { - str01.at(csz01); + (void) str01.at(csz01); VERIFY( false ); // Should not get here, as exception thrown. } catch(std::out_of_range& fail) { @@ -68,7 +68,7 @@ void test01(void) ref ref3 = str02.at(csz02 - 1); VERIFY( ref3 == 'a' ); try { - str02.at(csz02); + (void) str02.at(csz02); VERIFY( false ); // Should not get here, as exception thrown. } catch(std::out_of_range& fail) { diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/21674.cc b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/21674.cc index a5a129b..3ff8d51 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/21674.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/char/21674.cc @@ -27,5 +27,5 @@ int main() { typedef std::string string_type; string_type s; - s[1]; // abort + (void) s[1]; // abort } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/1.cc index 9bb5dcb..f9a07ab 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/1.cc @@ -53,7 +53,7 @@ void test01(void) cref cref3 = str01.at(csz01 - 1); VERIFY( cref3 == L'a' ); try { - str01.at(csz01); + (void) str01.at(csz01); VERIFY( false ); // Should not get here, as exception thrown. } catch(std::out_of_range& fail) { @@ -68,7 +68,7 @@ void test01(void) ref ref3 = str02.at(csz02 - 1); VERIFY( ref3 == L'a' ); try { - str02.at(csz02); + (void) str02.at(csz02); VERIFY( false ); // Should not get here, as exception thrown. } catch(std::out_of_range& fail) { diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc index 974e6b2..fc023a8 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc @@ -27,5 +27,5 @@ int main() { typedef std::wstring string_type; string_type s; - s[1]; // abort + (void) s[1]; // abort } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc index 45d514b..a9dcd9a 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2758.cc @@ -40,6 +40,6 @@ int main() x.replace(0, 3, "foo", 0, 3); x.replace(0, 3, cs, 0, 3); x = "bar"; - x.compare(0, 3, "foo", 0, 3); - x.compare(0, 3, cs, 0, 3); + (void) x.compare(0, 3, "foo", 0, 3); + (void) x.compare(0, 3, cs, 0, 3); } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc index 3cbaf17..6e308ba 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc @@ -29,12 +29,12 @@ int main() s.insert(0, {"abc", 1}); s.replace(0, 1, {"abc", 1}); s.replace(s.begin(), s.begin(), {"abc", 1}); - s.find({"abc", 1}); - s.rfind({"abc", 1}); - s.find_first_of({"abc", 1}); - s.find_last_of({"abc", 1}); - s.find_first_not_of({"abc", 1}); - s.find_last_not_of({"abc", 1}); - s.compare({"abc", 1}); - s.compare(0, 1, {"abc", 1}); + (void) s.find({"abc", 1}); + (void) s.rfind({"abc", 1}); + (void) s.find_first_of({"abc", 1}); + (void) s.find_last_of({"abc", 1}); + (void) s.find_first_not_of({"abc", 1}); + (void) s.find_last_not_of({"abc", 1}); + (void) s.compare({"abc", 1}); + (void) s.compare(0, 1, {"abc", 1}); } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc index e987cb7..41bb391 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/contains/nonnull.cc @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++23 -Wnonnull -O0" } +// { dg-options "-std=gnu++23 -Wnonnull -O0 -Wno-unused-result" } // { dg-do compile { target c++23 } } #include diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc index 1f2a156..32f3449 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++20 -Wnonnull -O0" } +// { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } // { dg-do compile { target c++20 } } #include diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc index 8514359..9e0d665 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++20 -Wnonnull -O0" } +// { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } // { dg-do compile { target c++20 } } #include diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/1.cc index 704d2f6..be3e41a 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/1.cc @@ -35,12 +35,12 @@ int test01(void) // 2:8-chars_8-chars_ // The following triggers -Wstringop-overread. See PR 103332. str1 = std::string("8-chars_") + "8-chars_"; - str1.c_str(); + (void) str1.c_str(); // printf("1:%s\n", str1.c_str()); VERIFY( str1 == "8-chars_8-chars_" ); str2 = str1 + "7-chars"; // printf("2:%s\n", str1.c_str()); //str1 is gone - str1.c_str(); + (void) str1.c_str(); VERIFY( str1 == "8-chars_8-chars_" ); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/1.cc index 4020950..df3ff7c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/wchar_t/1.cc @@ -32,11 +32,11 @@ int test01(void) // 1:8-chars_8-chars_ // 2:8-chars_8-chars_ str1 = std::wstring(L"8-chars_") + L"8-chars_"; - str1.c_str(); + (void) str1.c_str(); // wprintf("1:%s\n", str1.c_str()); str2 = str1 + L"7-chars"; // wprintf("2:%s\n", str1.c_str()); //str1 is gone - str1.c_str(); + (void) str1.c_str(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/capacity/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/capacity/1.cc index 0376d91..3d162c6 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/capacity/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/capacity/1.cc @@ -137,7 +137,7 @@ test01() sz03 = str02.size(); sz04 = str02.length(); VERIFY( sz03 == sz04 ); - str02.data(); + (void) str02.data(); sz03 = str02.size(); sz04 = str02.length(); VERIFY( sz03 == sz04 ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/1.cc index 5de62ec..b27e7d7 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/1.cc @@ -49,7 +49,7 @@ test01() VERIFY( cref3 == 'a' ); try { - str01.at(csz01); + (void) str01.at(csz01); VERIFY( false ); // Should not get here, as exception thrown. } catch (std::out_of_range& fail) diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/2.cc index e8f9db2..834d3f6 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/char/2.cc @@ -27,5 +27,5 @@ main() { typedef std::string_view string_view_type; string_view_type s; - s[0]; // abort + (void) s[0]; // abort } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc index 9877cd8..e9df872 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc @@ -49,7 +49,7 @@ test01() VERIFY( cref3 == L'a' ); try { - str01.at(csz01); + (void) str01.at(csz01); VERIFY( false ); // Should not get here, as exception thrown. } catch (std::out_of_range& fail) diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc index 23daa7a..840de84 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc @@ -29,5 +29,5 @@ main() { typedef std::wstring_view string_view_type; string_view_type s; - s[0]; // abort + (void) s[0]; // abort } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc index c0d274f..fafadcc 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++23 -Wnonnull -O0" } +// { dg-options "-std=gnu++23 -Wnonnull -O0 -Wno-unused-result" } // { dg-do compile { target c++23 } } #include diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc index 09a9997..50437bb 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++20 -Wnonnull -O0" } +// { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } // { dg-do compile { target c++20 } } #include diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc index c47f1da..fedba28a 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++20 -Wnonnull -O0" } +// { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } // { dg-do compile { target c++20 } } #include diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc index 1e8c5fd..2296fd1 100644 --- a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc @@ -41,18 +41,18 @@ void test04() // PUT strb_03.str(str_01); //reset - strb_03.str().length(); - strb_03.str().length(); + (void) strb_03.str().length(); + (void) strb_03.str().length(); // streamsize sputn(const char_typs* s, streamsize n) // write up to n chars to out_cur from s, returning number assigned // NB *sputn will happily put '\0' into your stream if you give it a chance* str_tmp = strb_03.str(); - str_tmp.length(); + (void) str_tmp.length(); strb_03.sputn("racadabras", 10);//"abracadabras or what?" - strb_03.str().length(); + (void) strb_03.str().length(); strb_03.sputn(", i wanna reach out and", 10); - strb_03.str().length(); + (void) strb_03.str().length(); str_tmp = strb_02.str(); strb_02.sputn("racadabra", 10); diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc index 6acc0f24..c44a535 100644 --- a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc @@ -41,18 +41,18 @@ void test04() // PUT strb_03.str(str_01); //reset - strb_03.str().length(); - strb_03.str().length(); + (void) strb_03.str().length(); + (void) strb_03.str().length(); // streamsize sputn(const char_typs* s, streamsize n) // write up to n chars to out_cur from s, returning number assigned // NB *sputn will happily put '\0' into your stream if you give it a chance* str_tmp = strb_03.str(); - str_tmp.length(); + (void) str_tmp.length(); strb_03.sputn(L"racadabras", 10);//"abracadabras or what?" - strb_03.str().length(); + (void) strb_03.str().length(); strb_03.sputn(L", i wanna reach out and", 10); - strb_03.str().length(); + (void) strb_03.str().length(); str_tmp = strb_02.str(); strb_02.sputn(L"racadabra", 10); diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/char/1.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/char/1.cc index 2a3a28b..b4cdb17 100644 --- a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/char/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/char/1.cc @@ -41,18 +41,18 @@ void test04() // PUT strb_03.str(str_01); //reset - strb_03.str().length(); - strb_03.str().length(); + (void) strb_03.str().length(); + (void) strb_03.str().length(); // streamsize sputn(const char_typs* s, streamsize n) // write up to n chars to out_cur from s, returning number assigned // NB *sputn will happily put '\0' into your stream if you give it a chance* str_tmp = strb_03.str(); - str_tmp.length(); + (void) str_tmp.length(); strb_03.sputn("racadabras", 10);//"abracadabras or what?" - strb_03.str().length(); + (void) strb_03.str().length(); strb_03.sputn(", i wanna reach out and", 10); - strb_03.str().length(); + (void) strb_03.str().length(); str_tmp = strb_02.str(); strb_02.sputn("racadabra", 10); diff --git a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc index 5f20e2c..eb0ae5e 100644 --- a/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc +++ b/libstdc++-v3/testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc @@ -41,18 +41,18 @@ void test04() // PUT strb_03.str(str_01); //reset - strb_03.str().length(); - strb_03.str().length(); + (void) strb_03.str().length(); + (void) strb_03.str().length(); // streamsize sputn(const char_typs* s, streamsize n) // write up to n chars to out_cur from s, returning number assigned // NB *sputn will happily put '\0' into your stream if you give it a chance* str_tmp = strb_03.str(); - str_tmp.length(); + (void) str_tmp.length(); strb_03.sputn(L"racadabras", 10);//"abracadabras or what?" - strb_03.str().length(); + (void) strb_03.str().length(); strb_03.sputn(L", i wanna reach out and", 10); - strb_03.str().length(); + (void) strb_03.str().length(); str_tmp = strb_02.str(); strb_02.sputn(L"racadabra", 10); -- cgit v1.1 From 5d27fcd993e4519fc05224f48bd2492b6cf52be1 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 31 Aug 2022 13:44:45 +0100 Subject: libstdc++: Improve comments in std::reference_wrapper tests libstdc++-v3/ChangeLog: * testsuite/20_util/reference_wrapper/invoke-2.cc: Improve comments. * testsuite/20_util/reference_wrapper/invoke-3.cc: Likewise. * testsuite/20_util/reference_wrapper/invoke.cc: Likewise. --- libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc | 3 ++- libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc | 3 ++- libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc index 2741510..fd3430c 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc @@ -16,7 +16,7 @@ // with this library; see the file COPYING3. If not see // . -// 20.6.4 function object return types [func.ret] +// C++11 20.8.3.4 reference_wrapper invocation [refwrap.invoke] #include struct X @@ -27,6 +27,7 @@ struct X void test01() { + // PR libstdc++/48521 std::result_of doesn't work with pointer to member typedef int (X::*mfp)(int); typedef int X::*mp; mfp m = &X::f; diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc index e4124c9..c25315b 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-3.cc @@ -17,7 +17,7 @@ // with this library; see the file COPYING3. If not see // . -// 20.8.3.4 reference_wrapper invocation [refwrap.invoke] +// C++11 20.8.3.4 reference_wrapper invocation [refwrap.invoke] #include struct ABC @@ -33,4 +33,5 @@ struct Concrete : ABC Concrete c; ABC& abc = c; +// PR libstdc++/57336 Cannot INVOKE a reference_wrapper around an abstract type auto b = std::cref(abc)(); diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc index cd884fe..b2abc81 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc @@ -17,6 +17,8 @@ // with this library; see the file COPYING3. If not see // . +// C++11 20.8.3.4 reference_wrapper invocation [refwrap.invoke] + #include #include #include -- cgit v1.1 From e47df5eb56c4e7aca0d3e50826e5aaa1887fa446 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 31 Aug 2022 13:57:34 +0100 Subject: libstdc++: Add noexcept-specifier to std::reference_wrapper::operator() This isn't required by the standard, but there's an LWG issue suggesting to add it. Also use __invoke_result instead of result_of, to match the spec in recent standards. libstdc++-v3/ChangeLog: * include/bits/refwrap.h (reference_wrapper::operator()): Add noexcept-specifier and use __invoke_result instead of result_of. * testsuite/20_util/reference_wrapper/invoke-noexcept.cc: New test. --- libstdc++-v3/include/bits/refwrap.h | 3 ++- .../20_util/reference_wrapper/invoke-noexcept.cc | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-noexcept.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h index 8016f87..976902b 100644 --- a/libstdc++-v3/include/bits/refwrap.h +++ b/libstdc++-v3/include/bits/refwrap.h @@ -348,8 +348,9 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) template _GLIBCXX20_CONSTEXPR - typename result_of<_Tp&(_Args&&...)>::type + typename __invoke_result<_Tp&, _Args...>::type operator()(_Args&&... __args) const + noexcept(__is_nothrow_invocable<_Tp&, _Args...>::value) { #if __cplusplus > 201703L if constexpr (is_object_v) diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-noexcept.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-noexcept.cc new file mode 100644 index 0000000..91b5d09 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-noexcept.cc @@ -0,0 +1,15 @@ +// { dg-do compile { target c++11 } } + +// C++11 20.8.3.4 reference_wrapper invocation [refwrap.invoke] + +#include + +struct F +{ + int operator()() noexcept(true) { return 1; } + int operator()() const noexcept(false) { return 2; } +}; + +F f; +static_assert( noexcept(std::ref(f)()) ); +static_assert( ! noexcept(std::cref(f)()) ); -- cgit v1.1 From caaf9e66c498d9d6dc8be665d820ab45afa406ae Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 31 Aug 2022 10:04:54 -0400 Subject: libstdc++: Add test for std::con/disjunction's short circuiting libstdc++-v3/ChangeLog: * testsuite/20_util/logical_traits/requirements/short_circuit.cc: New test. --- .../logical_traits/requirements/short_circuit.cc | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc new file mode 100644 index 0000000..86996b2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc @@ -0,0 +1,26 @@ +// { dg-do compile { target c++17 } } + +#include + +template struct A { using type = typename T::type; }; +using invalid = A; + +// [meta.logical]/3: For a specialization conjunction, if +// there is a template type argument B_i for which bool(B_i::value) is false, +// then instantiating conjunction::value does not require the +// instantiation of B_j::value for j > i. + +static_assert(!std::conjunction_v); +static_assert(!std::conjunction_v); +static_assert(!std::conjunction_v); +static_assert(!std::conjunction_v); + +// [meta.logical]/8: For a specialization disjunction, if +// there is a template type argument B_i for which bool(B_i::value) is true, +// then instantiating disjunction::value does not require the +// instantiation of B_j::value for j > i. + +static_assert(std::disjunction_v); +static_assert(std::disjunction_v); +static_assert(std::disjunction_v); +static_assert(std::disjunction_v); -- cgit v1.1 From 4d5660907c2b4c301fcbdc3dc713879fa31afec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Dumont?= Date: Tue, 21 Jan 2020 19:33:15 +0100 Subject: libstdc++: [_GLIBCXX_DEBUG] Add backtrace generation on demand Add _GLIBCXX_DEBUG_BACKTRACE macro to activate backtrace generation on _GLIBCXX_DEBUG assertions. Prerequisite is to have configure the lib with: --enable-libstdcxx-backtrace=yes libstdc++-v3/ChangeLog: * include/debug/formatter.h [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_state): Declare. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_create_state): Declare. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full_callback): Define. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_error_callback): Define. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full_func): Define. [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full): Declare. [_GLIBCXX_HAVE_STACKTRACE](_Error_formatter::_M_backtrace_state): New. [_GLIBCXX_HAVE_STACKTRACE](_Error_formatter::_M_backtrace_full): New. * src/c++11/debug.cc [_GLIBCXX_HAVE_STACKTRACE](print_backtrace): New. (_Error_formatter::_M_error()): Adapt. * src/libbacktrace/Makefile.am: Add backtrace.c. * src/libbacktrace/Makefile.in: Regenerate. * src/libbacktrace/backtrace-rename.h (backtrace_full): New. * testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc: New test. * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE. * doc/xml/manual/using.xml: Likewise. --- libstdc++-v3/doc/xml/manual/debug_mode.xml | 6 ++ libstdc++-v3/doc/xml/manual/using.xml | 10 +++ libstdc++-v3/include/debug/formatter.h | 44 +++++++++++++ libstdc++-v3/src/c++11/debug.cc | 75 ++++++++++++++++++++-- libstdc++-v3/src/libbacktrace/Makefile.am | 1 + libstdc++-v3/src/libbacktrace/Makefile.in | 12 ++-- libstdc++-v3/src/libbacktrace/backtrace-rename.h | 1 + .../vector/debug/assign4_backtrace_neg.cc | 17 +++++ 8 files changed, 157 insertions(+), 9 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/doc/xml/manual/debug_mode.xml b/libstdc++-v3/doc/xml/manual/debug_mode.xml index 988c4a9..dadc0cd 100644 --- a/libstdc++-v3/doc/xml/manual/debug_mode.xml +++ b/libstdc++-v3/doc/xml/manual/debug_mode.xml @@ -161,6 +161,12 @@ which always works correctly. GLIBCXX_DEBUG_MESSAGE_LENGTH can be used to request a different length. +Note that libstdc++ is able to produce backtraces on error. + It requires that you configure libstdc++ build with + . + Use -D_GLIBCXX_DEBUG_BACKTRACE to activate it. + You'll then have to link with libstdc++_libbacktrace static library + () to build your application.
Using a Specific Debug Container diff --git a/libstdc++-v3/doc/xml/manual/using.xml b/libstdc++-v3/doc/xml/manual/using.xml index 0b9a0c9..0acdba6 100644 --- a/libstdc++-v3/doc/xml/manual/using.xml +++ b/libstdc++-v3/doc/xml/manual/using.xml @@ -1144,6 +1144,15 @@ g++ -Winvalid-pch -I. -include stdc++.h -H -g -O2 hello.cc -o test.exe extensions and libstdc++-specific behavior into errors. + _GLIBCXX_DEBUG_BACKTRACE + + + Undefined by default. Considered only if libstdc++ has been configured with + and if _GLIBCXX_DEBUG + is defined. When defined display backtraces on + debug mode assertions. + + _GLIBCXX_PARALLEL Undefined by default. When defined, compiles user code @@ -1650,6 +1659,7 @@ A quick read of the relevant part of the GCC header will remain compatible between different GCC releases.
+
Concurrency diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h index 748d4fb..b4b7238 100644 --- a/libstdc++-v3/include/debug/formatter.h +++ b/libstdc++-v3/include/debug/formatter.h @@ -31,6 +31,37 @@ #include +#if _GLIBCXX_HAVE_STACKTRACE +struct __glibcxx_backtrace_state; + +extern "C" +{ + __glibcxx_backtrace_state* + __glibcxx_backtrace_create_state(const char*, int, + void(*)(void*, const char*, int), + void*); + + typedef int (*__glibcxx_backtrace_full_callback) ( + void*, __UINTPTR_TYPE__, const char *, int, const char*); + + typedef void (*__glibcxx_backtrace_error_callback) ( + void*, const char*, int); + + typedef int (*__glibcxx_backtrace_full_func) ( + __glibcxx_backtrace_state*, int, + __glibcxx_backtrace_full_callback, + __glibcxx_backtrace_error_callback, + void*); + + int + __glibcxx_backtrace_full( + __glibcxx_backtrace_state*, int, + __glibcxx_backtrace_full_callback, + __glibcxx_backtrace_error_callback, + void*); +} +#endif + #if __cpp_rtti # include # define _GLIBCXX_TYPEID(_Type) &typeid(_Type) @@ -576,6 +607,15 @@ namespace __gnu_debug const char* __function) : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) , _M_function(__function) +#if _GLIBCXX_HAVE_STACKTRACE +# ifdef _GLIBCXX_DEBUG_BACKTRACE + , _M_backtrace_state( + __glibcxx_backtrace_create_state(nullptr, 0, nullptr, nullptr)) + , _M_backtrace_full(&__glibcxx_backtrace_full) +# else + , _M_backtrace_state() +# endif +#endif { } #if !_GLIBCXX_INLINE_VERSION @@ -591,6 +631,10 @@ namespace __gnu_debug unsigned int _M_num_parameters; const char* _M_text; const char* _M_function; +#if _GLIBCXX_HAVE_STACKTRACE + __glibcxx_backtrace_state* _M_backtrace_state; + __glibcxx_backtrace_full_func _M_backtrace_full; +#endif public: static _Error_formatter& diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index 8ed61a6..abc4124 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -611,10 +611,12 @@ namespace void print_raw(PrintContext& ctx, const char* str, ptrdiff_t nbc = -1) { - if (nbc >= 0) - ctx._M_column += fprintf(stderr, "%.*s", (int)nbc, str); - else - ctx._M_column += fprintf(stderr, "%s", str); + if (nbc != 0) + { + ctx._M_column += (nbc > 0) + ? fprintf(stderr, "%.*s", (int)nbc, str) + : fprintf(stderr, "%s", str); + } } void @@ -680,7 +682,7 @@ namespace pos += 2; // advance past "__" if (memcmp(pos, cxx1998, 9) == 0) - pos += 9; // advance part "cxx1998::" + pos += 9; // advance past "cxx1998::" str = pos; } @@ -1093,6 +1095,58 @@ namespace void print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc) { print_string(ctx, str, nbc, nullptr, 0); } + +#if _GLIBCXX_HAVE_STACKTRACE + int + print_backtrace(void* data, __UINTPTR_TYPE__ pc, const char* filename, + int lineno, const char* function) + { + const int bufsize = 64; + char buf[bufsize]; + + PrintContext& ctx = *static_cast(data); + + int written = __builtin_sprintf(buf, "%p ", (void*)pc); + print_word(ctx, buf, written); + + int ret = 0; + if (function) + { + int status; + char* demangled_name = + __cxxabiv1::__cxa_demangle(function, NULL, NULL, &status); + if (status == 0) + pretty_print(ctx, demangled_name, &print_raw); + else + print_word(ctx, function); + + free(demangled_name); + ret = strstr(function, "main") ? 1 : 0; + } + + print_literal(ctx, "\n"); + + if (filename) + { + bool wordwrap = false; + swap(wordwrap, ctx._M_wordwrap); + print_word(ctx, filename); + + if (lineno) + { + written = __builtin_sprintf(buf, ":%u\n", lineno); + print_word(ctx, buf, written); + } + else + print_literal(ctx, "\n"); + swap(wordwrap, ctx._M_wordwrap); + } + else + print_literal(ctx, "???:0\n"); + + return ret; + } +#endif } namespace __gnu_debug @@ -1139,6 +1193,17 @@ namespace __gnu_debug print_literal(ctx, "\n"); } +#if _GLIBCXX_HAVE_STACKTRACE + if (_M_backtrace_state) + { + print_literal(ctx, "Backtrace:\n"); + _M_backtrace_full( + _M_backtrace_state, 1, print_backtrace, nullptr, &ctx); + ctx._M_first_line = true; + print_literal(ctx, "\n"); + } +#endif + print_literal(ctx, "Error: "); // Print the error message diff --git a/libstdc++-v3/src/libbacktrace/Makefile.am b/libstdc++-v3/src/libbacktrace/Makefile.am index 0f11435..52d8f81 100644 --- a/libstdc++-v3/src/libbacktrace/Makefile.am +++ b/libstdc++-v3/src/libbacktrace/Makefile.am @@ -60,6 +60,7 @@ libstdc___libbacktrace_la_SHORTNAME = $(obj_prefix) libstdc___libbacktrace_la_SOURCES = \ atomic.c \ + backtrace.c \ dwarf.c \ fileline.c \ posix.c \ diff --git a/libstdc++-v3/src/libbacktrace/Makefile.in b/libstdc++-v3/src/libbacktrace/Makefile.in index 7545894..5c6b4dd 100644 --- a/libstdc++-v3/src/libbacktrace/Makefile.in +++ b/libstdc++-v3/src/libbacktrace/Makefile.in @@ -181,10 +181,10 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(toolexeclibdir)" LTLIBRARIES = $(toolexeclib_LTLIBRARIES) am_libstdc___libbacktrace_la_OBJECTS = $(obj_prefix)-atomic.lo \ - $(obj_prefix)-dwarf.lo $(obj_prefix)-fileline.lo \ - $(obj_prefix)-posix.lo $(obj_prefix)-sort.lo \ - $(obj_prefix)-simple.lo $(obj_prefix)-state.lo \ - $(obj_prefix)-cp-demangle.lo + $(obj_prefix)-backtrace.lo $(obj_prefix)-dwarf.lo \ + $(obj_prefix)-fileline.lo $(obj_prefix)-posix.lo \ + $(obj_prefix)-sort.lo $(obj_prefix)-simple.lo \ + $(obj_prefix)-state.lo $(obj_prefix)-cp-demangle.lo libstdc___libbacktrace_la_OBJECTS = \ $(am_libstdc___libbacktrace_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -507,6 +507,7 @@ obj_prefix = std_stacktrace libstdc___libbacktrace_la_SHORTNAME = $(obj_prefix) libstdc___libbacktrace_la_SOURCES = \ atomic.c \ + backtrace.c \ dwarf.c \ fileline.c \ posix.c \ @@ -647,6 +648,9 @@ distclean-compile: $(obj_prefix)-atomic.lo: atomic.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-atomic.lo `test -f 'atomic.c' || echo '$(srcdir)/'`atomic.c +$(obj_prefix)-backtrace.lo: backtrace.c + $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-backtrace.lo `test -f 'backtrace.c' || echo '$(srcdir)/'`backtrace.c + $(obj_prefix)-dwarf.lo: dwarf.c $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libstdc___libbacktrace_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o $(obj_prefix)-dwarf.lo `test -f 'dwarf.c' || echo '$(srcdir)/'`dwarf.c diff --git a/libstdc++-v3/src/libbacktrace/backtrace-rename.h b/libstdc++-v3/src/libbacktrace/backtrace-rename.h index 7a59f16..79bdef6 100644 --- a/libstdc++-v3/src/libbacktrace/backtrace-rename.h +++ b/libstdc++-v3/src/libbacktrace/backtrace-rename.h @@ -4,6 +4,7 @@ #define backtrace_create_state __glibcxx_backtrace_create_state #define backtrace_dwarf_add __glibcxx_backtrace_dwarf_add #define backtrace_free __glibcxx_backtrace_free +#define backtrace_full __glibcxx_backtrace_full #define backtrace_get_view __glibcxx_backtrace_get_view #define backtrace_initialize __glibcxx_backtrace_initialize #define backtrace_open __glibcxx_backtrace_open diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc new file mode 100644 index 0000000..520788d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc @@ -0,0 +1,17 @@ +// { dg-do run { xfail *-*-* } } +// { dg-options "-D_GLIBCXX_DEBUG_BACKTRACE -lstdc++_libbacktrace" } +// { dg-require-effective-target stacktrace } + +#include +#include + +void test01() +{ + __gnu_test::check_assign1<__gnu_debug::vector >(); +} + +int main() +{ + test01(); + return 0; +} -- cgit v1.1 From f956cadc292aec42ceeba1e4835ad795c9aab5c2 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 31 Aug 2022 15:09:10 -0400 Subject: libstdc++: Implement ranges::adjacent_view from P2321R2 libstdc++-v3/ChangeLog: * include/std/ranges (adjacent_view): Define. (enable_borrowed_range): Define. (__detail::__repeated_tuple): Define. (adjacent_view::_Iterator): Define. (adjacent_view::_Sentinel): Define. (views::__detail::__can_adjacent_view): Define. (views::_Adjacent): Define. (views::adjacent): Define. (views::pairwise): Define. * testsuite/std/ranges/adaptors/adjacent/1.cc: New test. --- libstdc++-v3/include/std/ranges | 358 +++++++++++++++++++++ .../testsuite/std/ranges/adaptors/adjacent/1.cc | 110 +++++++ 2 files changed, 468 insertions(+) create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 6e2e561..2352aad 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -5081,6 +5081,364 @@ namespace views::__adaptor inline constexpr _ZipTransform zip_transform; } + + template + requires view<_Vp> && (_Nm > 0) + class adjacent_view : public view_interface> + { + _Vp _M_base = _Vp(); + + template class _Iterator; + template class _Sentinel; + + struct __as_sentinel + { }; + + public: + adjacent_view() requires default_initializable<_Vp> = default; + + constexpr explicit + adjacent_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(ranges::begin(_M_base), ranges::end(_M_base)); } + + constexpr auto + begin() const requires range + { return _Iterator(ranges::begin(_M_base), ranges::end(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (common_range<_Vp>) + return _Iterator(__as_sentinel{}, ranges::begin(_M_base), ranges::end(_M_base)); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + end() const requires range + { + if constexpr (common_range) + return _Iterator(__as_sentinel{}, ranges::begin(_M_base), ranges::end(_M_base)); + else + return _Sentinel(ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { + using _ST = decltype(ranges::size(_M_base)); + using _CT = common_type_t<_ST, size_t>; + auto __sz = static_cast<_CT>(ranges::size(_M_base)); + __sz -= std::min<_CT>(__sz, _Nm - 1); + return static_cast<_ST>(__sz); + } + + constexpr auto + size() const requires sized_range + { + using _ST = decltype(ranges::size(_M_base)); + using _CT = common_type_t<_ST, size_t>; + auto __sz = static_cast<_CT>(ranges::size(_M_base)); + __sz -= std::min<_CT>(__sz, _Nm - 1); + return static_cast<_ST>(__sz); + } + }; + + template + inline constexpr bool enable_borrowed_range> + = enable_borrowed_range<_Vp>; + + namespace __detail + { + // Yields tuple<_Tp, ..., _Tp> with _Nm elements. + template + using __repeated_tuple = decltype(std::tuple_cat(std::declval>())); + } + + template + requires view<_Vp> && (_Nm > 0) + template + class adjacent_view<_Vp, _Nm>::_Iterator + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + array, _Nm> _M_current = array, _Nm>(); + + constexpr + _Iterator(iterator_t<_Base> __first, sentinel_t<_Base> __last) + { + for (auto& __i : _M_current) + { + __i = __first; + ranges::advance(__first, 1, __last); + } + } + + constexpr + _Iterator(__as_sentinel, iterator_t<_Base> __first, iterator_t<_Base> __last) + { + if constexpr (!bidirectional_range<_Base>) + for (auto& __it : _M_current) + __it = __last; + else + for (size_t __i = 0; __i < _Nm; ++__i) + { + _M_current[_Nm - 1 - __i] = __last; + ranges::advance(__last, -1, __first); + } + } + + static auto + _S_iter_concept() + { + if constexpr (random_access_range<_Base>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Base>) + return bidirectional_iterator_tag{}; + else + return forward_iterator_tag{}; + } + + friend class adjacent_view; + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = decltype(_S_iter_concept()); + using value_type = conditional_t<_Nm == 2, + pair, range_value_t<_Base>>, + __detail::__repeated_tuple, _Nm>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to, iterator_t<_Base>> + { + for (size_t __j = 0; __j < _Nm; ++__j) + _M_current[__j] = std::move(__i[__j]); + } + + constexpr auto + operator*() const + { + auto __f = [](auto& __i) -> decltype(auto) { return *__i; }; + return __detail::__tuple_transform(__f, _M_current); + } + + constexpr _Iterator& + operator++() + { + for (auto& __i : _M_current) + ++__i; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + for (auto& __i : _M_current) + --__i; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) + requires random_access_range<_Base> + { + for (auto& __i : _M_current) + __i += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) + requires random_access_range<_Base> + { + for (auto& __i : _M_current) + __i -= __x; + return *this; + } + + constexpr auto + operator[](difference_type __n) const + requires random_access_range<_Base> + { + auto __f = [&](auto& __i) -> decltype(auto) { return __i[__n]; }; + return __detail::__tuple_transform(__f, _M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_current.back() == __y._M_current.back(); } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current.back() < __y._M_current.back(); } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current.back() <=> __y._M_current.back(); } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { + auto __r = __i; + __r += __n; + return __r; + } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { + auto __r = __i; + __r -= __n; + return __r; + } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for, iterator_t<_Base>> + { return __x._M_current.back() - __y._M_current.back(); } + + friend constexpr auto + iter_move(const _Iterator& __i) + { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __l, const _Iterator& __r) + requires indirectly_swappable> + { + for (size_t __i = 0; __i < _Nm; __i++) + ranges::iter_swap(__l._M_current[__i], __r._M_current[__i]); + } + }; + + template + requires view<_Vp> && (_Nm > 0) + template + class adjacent_view<_Vp, _Nm>::_Sentinel + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + friend class adjacent_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __i) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__i._M_end)) + { } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current.back() == __y._M_end; } + + template + requires sized_sentinel_for, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_current.back() - __y._M_end; } + + template + requires sized_sentinel_for, + iterator_t<__detail::__maybe_const_t<_OtherConst, _Vp>>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _Vp>> + operator-(const _Sentinel& __y, const _Iterator<_OtherConst>& __x) + { return __y._M_end - __x._M_current.back(); } + }; + + namespace views + { + namespace __detail + { + template + concept __can_adjacent_view + = requires { adjacent_view, _Nm>(std::declval<_Range>()); }; + } + + template + struct _Adjacent : __adaptor::_RangeAdaptorClosure + { + template + requires (_Nm == 0) || __detail::__can_adjacent_view<_Nm, _Range> + constexpr auto + operator() [[nodiscard]] (_Range&& __r) const + { + if constexpr (_Nm == 0) + return views::empty>; + else + return adjacent_view, _Nm>(std::forward<_Range>(__r)); + } + }; + + template + inline constexpr _Adjacent<_Nm> adjacent; + + inline constexpr auto pairwise = adjacent<2>; + } #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc new file mode 100644 index 0000000..9829f79 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent/1.cc @@ -0,0 +1,110 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include +#include +#include +#include +#include + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + static_assert(ranges::empty(std::array{1, 2, 3} | views::adjacent<0>)); + + auto v1 = std::array{1, 2} | views::adjacent<1>; + const auto i0 = v1.begin(), i1 = v1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < v1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( v1.end() - i1 == 1 ); + VERIFY( i1 - v1.end() == -1 ); + ranges::iter_swap(i0, i1); + VERIFY( ranges::equal(std::move(v1) | views::keys, (int[]){2, 1}) ); + + int x[] = {1, 2, 3, 4}; + auto v2 = x | views::pairwise; + auto i2 = v2.begin(); + i2 += 2; + i2 -= -1; + VERIFY( i2 == v2.end() ); + VERIFY( ranges::size(v2) == 3 ); + VERIFY( ranges::size(std::as_const(v2)) == 3 ); + VERIFY( ranges::equal(v2 | views::keys, (int[]){1, 2, 3}) ); + VERIFY( ranges::equal(v2 | views::values, (int[]){2, 3, 4}) ); + + int y[] = {1, 2, 3, 4, 5}; + const auto v3 = y | views::adjacent<3>; + VERIFY( ranges::size(v3) == 3 ); + for (unsigned i = 0; i < ranges::size(x); i++) + { + VERIFY( &std::get<0>(v3[i]) == &y[i] + 0 ); + VERIFY( &std::get<1>(v3[i]) == &y[i] + 1 ); + VERIFY( &std::get<2>(v3[i]) == &y[i] + 2 ); + } + + const auto v5 = y | views::adjacent<5>; + VERIFY( ranges::equal(v5, views::single(std::make_tuple(1, 2, 3, 4, 5))) ); + + const auto v6 = y | views::adjacent<6>; + VERIFY( ranges::empty(v6) ); + + const auto v0 = y | views::adjacent<0>; + VERIFY( ranges::empty(v0) ); + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::adjacent_view>, 2>; + static_assert(ranges::forward_range); + static_assert(!ranges::bidirectional_range); + static_assert(!ranges::sized_range); + + using ty2 = ranges::adjacent_view>, 3>; + static_assert(ranges::random_access_range); + static_assert(ranges::sized_range); + + return true; +} + +constexpr bool +test03() +{ + auto v = views::iota(0, 4) | views::filter([](auto) { return true; }) | views::pairwise; + using ty = decltype(v); + static_assert(ranges::forward_range); + static_assert(ranges::common_range); + static_assert(!ranges::sized_range); + VERIFY( v.begin() == v.begin() ); + VERIFY( v.begin() != v.end() ); + VERIFY( ranges::next(v.begin(), 3) == v.end() ); + auto it = v.begin(); + ++it; + it++; + VERIFY( ranges::next(it) == v.end() ); + it--; + --it; + VERIFY( it == v.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +} -- cgit v1.1 From 5f932c9f93c45440a7baf7d9059d3b33a0f2d2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Dumont?= Date: Sun, 14 Aug 2022 17:11:02 +0200 Subject: libstdc++: [_GLIBCXX_DEBUG] Review nullptr assertion diagnostics Review null string checks to show: _String != nullptr rather than: _String != 0 libstdc++-v3/ChangeLog: * include/debug/debug.h: Use nullptr rather than '0' in checks in post-C++11. * include/debug/string: Likewise. * testsuite/21_strings/basic_string/operations/ends_with/char.cc: Use __gnu_test::string. * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc: Likewise. * testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc: Likewise. * testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc: Likewise. * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc: Likewise. * testsuite/21_strings/basic_string/operations/starts_with/char.cc: Likewise.. --- libstdc++-v3/include/debug/debug.h | 11 ++++++++-- libstdc++-v3/include/debug/string | 25 ++++++++++++++++++++-- .../basic_string/operations/ends_with/char.cc | 4 ++-- .../basic_string/operations/ends_with/nonnull.cc | 4 ++-- .../basic_string/operations/ends_with/wchar_t.cc | 4 ++-- .../basic_string/operations/starts_with/char.cc | 4 ++-- .../basic_string/operations/starts_with/nonnull.cc | 4 ++-- .../basic_string/operations/starts_with/wchar_t.cc | 4 ++-- 8 files changed, 44 insertions(+), 16 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/debug/debug.h b/libstdc++-v3/include/debug/debug.h index 28e250f..f423376 100644 --- a/libstdc++-v3/include/debug/debug.h +++ b/libstdc++-v3/include/debug/debug.h @@ -118,10 +118,17 @@ namespace __gnu_debug __glibcxx_check_heap(_First,_Last) # define __glibcxx_requires_heap_pred(_First,_Last,_Pred) \ __glibcxx_check_heap_pred(_First,_Last,_Pred) -# define __glibcxx_requires_string(_String) \ +# if __cplusplus < 201103L +# define __glibcxx_requires_string(_String) \ _GLIBCXX_DEBUG_PEDASSERT(_String != 0) -# define __glibcxx_requires_string_len(_String,_Len) \ +# define __glibcxx_requires_string_len(_String,_Len) \ _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0) +# else +# define __glibcxx_requires_string(_String) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != nullptr) +# define __glibcxx_requires_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != nullptr || _Len == 0) +# endif # define __glibcxx_requires_irreflexive(_First,_Last) \ __glibcxx_check_irreflexive(_First,_Last) # define __glibcxx_requires_irreflexive2(_First,_Last) \ diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string index a4482db..c16751c 100644 --- a/libstdc++-v3/include/debug/string +++ b/libstdc++-v3/include/debug/string @@ -50,14 +50,25 @@ #endif #ifdef _GLIBCXX_DEBUG_PEDANTIC -# define __glibcxx_check_string(_String) \ +# if __cplusplus < 201103L +# define __glibcxx_check_string(_String) \ _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_String != 0, \ __FILE__, __LINE__, \ __PRETTY_FUNCTION__); -# define __glibcxx_check_string_len(_String,_Len) \ +# define __glibcxx_check_string_len(_String,_Len) \ _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_String != 0 || _Len == 0, \ __FILE__, __LINE__, \ __PRETTY_FUNCTION__); +# else +# define __glibcxx_check_string(_String) \ + _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_String != nullptr, \ + __FILE__, __LINE__, \ + __PRETTY_FUNCTION__); +# define __glibcxx_check_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(_String != nullptr || _Len == 0, \ + __FILE__, __LINE__, \ + __PRETTY_FUNCTION__); +# endif #else # define __glibcxx_check_string(_String) # define __glibcxx_check_string_len(_String,_Len) @@ -75,8 +86,13 @@ namespace __gnu_debug const char* __function __attribute__((__unused__))) { #ifdef _GLIBCXX_DEBUG_PEDANTIC +# if __cplusplus < 201103L _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != 0 || __n == 0, __file, __line, __function); +# else + _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != nullptr || __n == 0, + __file, __line, __function); +# endif #endif return __s; } @@ -90,8 +106,13 @@ namespace __gnu_debug const char* __function __attribute__((__unused__))) { #ifdef _GLIBCXX_DEBUG_PEDANTIC +# if __cplusplus < 201103L _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != 0, __file, __line, __function); +# else + _GLIBCXX_DEBUG_VERIFY_STR_COND_AT(__s != nullptr, + __file, __line, __function); +# endif #endif return __s; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char.cc index cfe18e0..3cf8512 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/char.cc @@ -20,7 +20,7 @@ // basic_string ends_with -#include +#include #include void @@ -31,7 +31,7 @@ test01() const char cstr_suf2[] = ".rgb"; const std::string_view sv_suf2(".rgb"); - const std::string s_test("slugs/slimy.jpg"); + const __gnu_test::string s_test("slugs/slimy.jpg"); const auto cstr_in_slugs = s_test.ends_with(cstr_suf); VERIFY( cstr_in_slugs ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc index 32f3449..ba77f01 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc @@ -1,10 +1,10 @@ // { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } // { dg-do compile { target c++20 } } -#include +#include void -test01(const std::string& s) +test01(const __gnu_test::string& s) { s.ends_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } s.ends_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc index d27e824..70b522f 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc @@ -20,7 +20,7 @@ // basic_string ends_with -#include +#include #include void @@ -31,7 +31,7 @@ test01() const wchar_t cstr_suf2[] = L".rgb"; const std::wstring_view sv_suf2(L".rgb"); - const std::wstring s_test(L"slugs/slimy.jpg"); + const __gnu_test::wstring s_test(L"slugs/slimy.jpg"); const auto cstr_in_slugs = s_test.ends_with(cstr_suf); VERIFY( cstr_in_slugs ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char.cc index 5c0b3af..dddf51c 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/char.cc @@ -20,7 +20,7 @@ // basic_string begins_with -#include +#include #include void @@ -31,7 +31,7 @@ test01() const char cstr_dir2[] = "worms/"; const std::string_view sv_dir2("worms/"); - const std::string s_test("slugs/slimy.jpg"); + const __gnu_test::string s_test("slugs/slimy.jpg"); const auto cstr_in_slugs = s_test.starts_with(cstr_dir); VERIFY( cstr_in_slugs ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc index 9e0d665..a023d9e 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc @@ -1,10 +1,10 @@ // { dg-options "-std=gnu++20 -Wnonnull -O0 -Wno-unused-result" } // { dg-do compile { target c++20 } } -#include +#include void -test01(const std::string& s) +test01(const __gnu_test::string& s) { s.starts_with((const char*)nullptr); // { dg-warning "\\\[-Wnonnull" } s.starts_with((char*)nullptr); // { dg-warning "\\\[-Wnonnull" } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc index eda7321..747b23a 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc @@ -20,7 +20,7 @@ // basic_string begins_with -#include +#include #include void @@ -31,7 +31,7 @@ test01() const wchar_t cstr_dir2[] = L"worms/"; const std::wstring_view sv_dir2(L"worms/"); - const std::wstring s_test(L"slugs/slimy.jpg"); + const __gnu_test::wstring s_test(L"slugs/slimy.jpg"); const auto cstr_in_slugs = s_test.starts_with(cstr_dir); VERIFY( cstr_in_slugs ); -- cgit v1.1 From dc832fb39fc0f9e5f3a86e3b8399259b1adccc8d Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Thu, 25 Aug 2022 14:30:51 +0200 Subject: 32-bit PA-RISC with HP-UX: remove deprecated ports ChangeLog: * configure: Regenerate. * configure.ac: Delete hpux9 and hpux10. config/ChangeLog: * mh-pa-hpux10: Removed. contrib/ChangeLog: * config-list.mk: Remove deprecated ports. contrib/header-tools/ChangeLog: * README: Remove deprecated ports. * reduce-headers: Likewise. gcc/ChangeLog: * config.build: Remove deprecated ports. * config.gcc: Likewise. * config.host: Likewise. * configure.ac: Likewise. * configure: Regenerate. * config/pa/pa-hpux10.h: Removed. * config/pa/pa-hpux10.opt: Removed. * config/pa/t-dce-thr: Removed. gnattools/ChangeLog: * configure.ac: Remove deprecated ports. * configure: Regenerate. libstdc++-v3/ChangeLog: * configure: Regenerate. * crossconfig.m4: Remove deprecated ports. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/lambda/lambda-conv.C: Remove useless test. * gcc.c-torture/execute/ieee/hugeval.x: Likewise. * gcc.dg/torture/pr47917.c: Likewise. * lib/target-supports.exp: Likewise. libgcc/ChangeLog: * config.host: Remove hppa. libitm/ChangeLog: * configure: Regenerate. fixincludes/ChangeLog: * configure: Regenerate. --- libstdc++-v3/configure | 14 -------------- libstdc++-v3/crossconfig.m4 | 9 --------- 2 files changed, 23 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 9e2ee86..1772eef 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -47955,20 +47955,6 @@ $as_echo "$gcc_cv_have_tls" >&6; } $as_echo "#define HAVE_TLS 1" >>confdefs.h fi - case "$target" in - *-hpux10*) - $as_echo "#define HAVE_ISINF 1" >>confdefs.h - - $as_echo "#define HAVE_ISINFF 1" >>confdefs.h - - $as_echo "#define HAVE_ISNANF 1" >>confdefs.h - - $as_echo "#define HAVE_FINITE 1" >>confdefs.h - - $as_echo "#define HAVE_FINITEF 1" >>confdefs.h - - ;; - esac ;; *-linux* | *-uclinux* | *-gnu* | *-kfreebsd*-gnu | *-cygwin* | *-solaris*) diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4 index e8ff89f..130f47f 100644 --- a/libstdc++-v3/crossconfig.m4 +++ b/libstdc++-v3/crossconfig.m4 @@ -173,15 +173,6 @@ case "${host}" in AC_DEFINE(HAVE_STRTOLD) GCC_CHECK_TLS - case "$target" in - *-hpux10*) - AC_DEFINE(HAVE_ISINF) - AC_DEFINE(HAVE_ISINFF) - AC_DEFINE(HAVE_ISNANF) - AC_DEFINE(HAVE_FINITE) - AC_DEFINE(HAVE_FINITEF) - ;; - esac ;; *-linux* | *-uclinux* | *-gnu* | *-kfreebsd*-gnu | *-cygwin* | *-solaris*) GLIBCXX_CHECK_COMPILER_FEATURES -- cgit v1.1 From 26aafae4e50d1b90fe3a265027003487c1d25b45 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 31 Aug 2022 16:45:30 -0400 Subject: libstdc++: A few more minor cleanups libstdc++-v3/ChangeLog: * include/bits/ranges_base.h (__advance_fn::operator()): Add parentheses in assert condition to avoid -Wparentheses warning. * include/std/ranges: (take_view::take_view): Uglify 'base'. (take_while_view::take_while_view): Likewise. (elements_view::elements_view): Likewise. (views::_Zip::operator()): Adjust position of [[nodiscard]] for compatibility with -fconcepts-ts. (zip_transform_view::_Sentinel): Uglify 'OtherConst'. (views::_ZipTransform::operator()): Adjust position of [[nodiscard]] for compatibilty with -fconcepts-ts. --- libstdc++-v3/include/bits/ranges_base.h | 2 +- libstdc++-v3/include/std/ranges | 40 ++++++++++++++++----------------- 2 files changed, 20 insertions(+), 22 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index 38db33f..866d7c5 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -778,7 +778,7 @@ namespace ranges else if (__n != 0) [[likely]] { // n and bound must not lead in opposite directions: - __glibcxx_assert(__n < 0 == __diff < 0); + __glibcxx_assert((__n < 0) == (__diff < 0)); (*this)(__it, __n); return 0; diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 2352aad..39822b7 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -2121,8 +2121,8 @@ namespace views::__adaptor take_view() requires default_initializable<_Vp> = default; constexpr - take_view(_Vp base, range_difference_t<_Vp> __count) - : _M_base(std::move(base)), _M_count(std::move(__count)) + take_view(_Vp __base, range_difference_t<_Vp> __count) + : _M_base(std::move(__base)), _M_count(std::move(__count)) { } constexpr _Vp @@ -2355,8 +2355,8 @@ namespace views::__adaptor = default; constexpr - take_while_view(_Vp base, _Pred __pred) - : _M_base(std::move(base)), _M_pred(std::move(__pred)) + take_while_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } constexpr _Vp @@ -3982,8 +3982,8 @@ namespace views::__adaptor elements_view() requires default_initializable<_Vp> = default; constexpr explicit - elements_view(_Vp base) - : _M_base(std::move(base)) + elements_view(_Vp __base) + : _M_base(std::move(__base)) { } constexpr _Vp @@ -4753,9 +4753,8 @@ namespace views::__adaptor { template requires (sizeof...(_Ts) == 0 || __detail::__can_zip_view<_Ts...>) - [[nodiscard]] constexpr auto - operator()(_Ts&&... __ts) const + operator() [[nodiscard]] (_Ts&&... __ts) const { if constexpr (sizeof...(_Ts) == 0) return views::empty>; @@ -5036,22 +5035,22 @@ namespace views::__adaptor : _M_inner(std::move(__i._M_inner)) { } - template - requires sentinel_for<__zentinel<_Const>, __ziperator> + template + requires sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> friend constexpr bool - operator==(const _Iterator& __x, const _Sentinel& __y) + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) { return __x._M_inner == __y._M_inner; } - template - requires sized_sentinel_for<__zentinel<_Const>, __ziperator> - friend constexpr range_difference_t<__detail::__maybe_const_t> - operator-(const _Iterator& __x, const _Sentinel& __y) + template + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) { return __x._M_inner - __y._M_inner; } - template - requires sized_sentinel_for<__zentinel<_Const>, __ziperator> - friend constexpr range_difference_t<__detail::__maybe_const_t> - operator-(const _Sentinel& __x, const _Iterator& __y) + template + requires sized_sentinel_for<__zentinel<_Const>, __ziperator<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Sentinel& __x, const _Iterator<_OtherConst>& __y) { return __x._M_inner - __y._M_inner; } }; @@ -5068,9 +5067,8 @@ namespace views::__adaptor { template requires (sizeof...(_Ts) == 0) || __detail::__can_zip_transform_view<_Fp, _Ts...> - [[nodiscard]] constexpr auto - operator()(_Fp&& __f, _Ts&&... __ts) const + operator() [[nodiscard]] (_Fp&& __f, _Ts&&... __ts) const { if constexpr (sizeof...(_Ts) == 0) return views::empty>>; -- cgit v1.1 From 542c60c4fb557ec437e3d20634fd59a61d619ac3 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 1 Sep 2022 00:17:39 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 137 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ba5939d..712ce17 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,140 @@ +2022-08-31 Patrick Palka + + * include/bits/ranges_base.h (__advance_fn::operator()): Add + parentheses in assert condition to avoid -Wparentheses warning. + * include/std/ranges: (take_view::take_view): Uglify 'base'. + (take_while_view::take_while_view): Likewise. + (elements_view::elements_view): Likewise. + (views::_Zip::operator()): Adjust position of [[nodiscard]] for + compatibility with -fconcepts-ts. + (zip_transform_view::_Sentinel): Uglify 'OtherConst'. + (views::_ZipTransform::operator()): Adjust position of + [[nodiscard]] for compatibilty with -fconcepts-ts. + +2022-08-31 Martin Liska + + * configure: Regenerate. + * crossconfig.m4: Remove deprecated ports. + +2022-08-31 François Dumont + + * include/debug/debug.h: Use nullptr rather than '0' in checks in post-C++11. + * include/debug/string: Likewise. + * testsuite/21_strings/basic_string/operations/ends_with/char.cc: Use __gnu_test::string. + * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc: Likewise. + * testsuite/21_strings/basic_string/operations/ends_with/wchar_t.cc: Likewise. + * testsuite/21_strings/basic_string/operations/starts_with/wchar_t.cc: Likewise. + * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc: Likewise. + * testsuite/21_strings/basic_string/operations/starts_with/char.cc: Likewise.. + +2022-08-31 Patrick Palka + + * include/std/ranges (adjacent_view): Define. + (enable_borrowed_range): Define. + (__detail::__repeated_tuple): Define. + (adjacent_view::_Iterator): Define. + (adjacent_view::_Sentinel): Define. + (views::__detail::__can_adjacent_view): Define. + (views::_Adjacent): Define. + (views::adjacent): Define. + (views::pairwise): Define. + * testsuite/std/ranges/adaptors/adjacent/1.cc: New test. + +2022-08-31 François Dumont + + * include/debug/formatter.h + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_state): Declare. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_create_state): Declare. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full_callback): Define. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_error_callback): Define. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full_func): Define. + [_GLIBCXX_HAVE_STACKTRACE](__glibcxx_backtrace_full): Declare. + [_GLIBCXX_HAVE_STACKTRACE](_Error_formatter::_M_backtrace_state): New. + [_GLIBCXX_HAVE_STACKTRACE](_Error_formatter::_M_backtrace_full): New. + * src/c++11/debug.cc [_GLIBCXX_HAVE_STACKTRACE](print_backtrace): New. + (_Error_formatter::_M_error()): Adapt. + * src/libbacktrace/Makefile.am: Add backtrace.c. + * src/libbacktrace/Makefile.in: Regenerate. + * src/libbacktrace/backtrace-rename.h (backtrace_full): New. + * testsuite/23_containers/vector/debug/assign4_backtrace_neg.cc: New test. + * doc/xml/manual/debug_mode.xml: Document _GLIBCXX_DEBUG_BACKTRACE. + * doc/xml/manual/using.xml: Likewise. + +2022-08-31 Patrick Palka + + * testsuite/20_util/logical_traits/requirements/short_circuit.cc: New test. + +2022-08-31 Jonathan Wakely + + * include/bits/refwrap.h (reference_wrapper::operator()): Add + noexcept-specifier and use __invoke_result instead of result_of. + * testsuite/20_util/reference_wrapper/invoke-noexcept.cc: New test. + +2022-08-31 Jonathan Wakely + + * testsuite/20_util/reference_wrapper/invoke-2.cc: Improve + comments. + * testsuite/20_util/reference_wrapper/invoke-3.cc: Likewise. + * testsuite/20_util/reference_wrapper/invoke.cc: Likewise. + +2022-08-31 Jonathan Wakely + + * include/bits/basic_string.h (basic_string): Add nodiscard + attribute to all relevant functions. + * include/std/string_view (basic_string_view): Likewise. + * testsuite/21_strings/basic_string/capacity/1.cc: Cast unused + results to void. + * testsuite/21_strings/basic_string/capacity/char/1.cc: + Likewise. + * testsuite/21_strings/basic_string/capacity/wchar_t/1.cc: + Likewise. + * testsuite/21_strings/basic_string/cons/char/self_move.cc: + Likewise. + * testsuite/21_strings/basic_string/element_access/char/1.cc: + Likewise. + * testsuite/21_strings/basic_string/element_access/char/21674.cc: + Likewise. + * testsuite/21_strings/basic_string/element_access/wchar_t/1.cc: + Likewise. + * testsuite/21_strings/basic_string/element_access/wchar_t/21674.cc: + Likewise. + * testsuite/21_strings/basic_string/lwg2758.cc: Likewise. + * testsuite/21_strings/basic_string/lwg2946.cc: Likewise. + * testsuite/21_strings/basic_string/operations/contains/nonnull.cc: + Add -Wno-unused-result to options. + * testsuite/21_strings/basic_string/operations/ends_with/nonnull.cc: + Likewise. + * testsuite/21_strings/basic_string/operations/starts_with/nonnull.cc: + Likewise. + * testsuite/21_strings/basic_string/operators/char/1.cc: Cast + unused results to void. + * testsuite/21_strings/basic_string/operators/wchar_t/1.cc: + Likewise. + * testsuite/21_strings/basic_string_view/capacity/1.cc: + Likewise. + * testsuite/21_strings/basic_string_view/element_access/char/1.cc: + Likewise. + * testsuite/21_strings/basic_string_view/element_access/char/2.cc: + Likewise. + * testsuite/21_strings/basic_string_view/element_access/wchar_t/1.cc: + Likewise. + * testsuite/21_strings/basic_string_view/element_access/wchar_t/2.cc: + Likewise. + * testsuite/21_strings/basic_string_view/operations/contains/nonnull.cc: + Likewise. + Add -Wno-unused-result to options. + * testsuite/21_strings/basic_string_view/operations/ends_with/nonnull.cc: + Likewise. + * testsuite/21_strings/basic_string_view/operations/starts_with/nonnull.cc: + Likewise. + * testsuite/27_io/basic_stringbuf/sputbackc/char/1.cc: Cast + unused results to void. + * testsuite/27_io/basic_stringbuf/sputbackc/wchar_t/1.cc: + Likewise. + * testsuite/27_io/basic_stringbuf/sungetc/char/1.cc: Likewise. + * testsuite/27_io/basic_stringbuf/sungetc/wchar_t/1.cc: + Likewise. + 2022-08-27 Patrick Palka * testsuite/20_util/logical_traits/requirements/base_classes.cc: New test. -- cgit v1.1 From 0e1b1222af5e5346df9431df817f2e7dca01bee6 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 31 Aug 2022 15:00:07 +0100 Subject: libstdc++: Optimize array traits Improve compile times by avoiding unnecessary class template instantiations. __is_array_known_bounds and __is_array_unknown_bounds can be defined without instantiating extent, by providing partial specializations for the true cases. std::extent can avoid recursing down through a multidimensional array, so it stops after providing the result. Previously extent would instantiate extent and extent as well. std::is_array_v can use partial specializations to avoid instantiating std::is_array, and similarly for std::rank_v and std::extent_v. std::is_bounded_array_v and std::is_unbounded_array_v can also use partial specializations, and then the class templates can be defined in terms of the variable templates. This makes sense for these traits, because they are new in C++20 and so the variable templates are always available, which isn't true in general for C++11 and C++14 traits. libstdc++-v3/ChangeLog: * include/std/type_traits (__is_array_known_bounds): Add partial specialization instead of using std::extent. (__is_array_unknown_bounds): Likewise. (extent): Add partial specializations to stop recursion after the result is found. (is_array_v): Add partial specializations instead of instantiating the class template. (rank_v, extent_v): Likewise. (is_bounded_array_v, is_unbounded_array_v): Likewise. (is_bounded_array, is_unbounded_array): Define in terms of the variable templates. --- libstdc++-v3/include/std/type_traits | 98 ++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 31 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index c2f5cb9..5984442 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -867,21 +867,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template auto declval() noexcept -> decltype(__declval<_Tp>(0)); - template - struct extent; - template struct remove_all_extents; /// @cond undocumented template struct __is_array_known_bounds - : public integral_constant::value > 0)> + : public false_type + { }; + + template + struct __is_array_known_bounds<_Tp[_Size]> + : public true_type { }; template struct __is_array_unknown_bounds - : public __and_, __not_>> + : public false_type + { }; + + template + struct __is_array_unknown_bounds<_Tp[]> + : public true_type { }; // Destructible and constructible type properties. @@ -1430,23 +1437,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public integral_constant::value> { }; /// extent - template + template struct extent - : public integral_constant { }; + : public integral_constant { }; - template + template + struct extent<_Tp[_Size], 0> + : public integral_constant { }; + + template struct extent<_Tp[_Size], _Uint> - : public integral_constant::value> - { }; + : public extent<_Tp, _Uint - 1>::type { }; + + template + struct extent<_Tp[], 0> + : public integral_constant { }; template struct extent<_Tp[], _Uint> - : public integral_constant::value> - { }; + : public extent<_Tp, _Uint - 1>::type { }; // Type relations. @@ -3133,8 +3142,14 @@ template inline constexpr bool is_integral_v = is_integral<_Tp>::value; template inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; + +template + inline constexpr bool is_array_v = false; template - inline constexpr bool is_array_v = is_array<_Tp>::value; + inline constexpr bool is_array_v<_Tp[]> = true; +template + inline constexpr bool is_array_v<_Tp[_Num]> = true; + template inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; template @@ -3276,10 +3291,25 @@ template has_virtual_destructor<_Tp>::value; template inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; + +template + inline constexpr size_t rank_v = 0; +template + inline constexpr size_t rank_v<_Tp[_Size]> = 1 + rank_v<_Tp>; template - inline constexpr size_t rank_v = rank<_Tp>::value; + inline constexpr size_t rank_v<_Tp[]> = 1 + rank_v<_Tp>; + template - inline constexpr size_t extent_v = extent<_Tp, _Idx>::value; + inline constexpr size_t extent_v = 0; +template + inline constexpr size_t extent_v<_Tp[_Size], 0> = _Size; +template + inline constexpr size_t extent_v<_Tp[_Size], _Idx> = extent_v<_Tp, _Idx - 1>; +template + inline constexpr size_t extent_v<_Tp[], 0> = 0; +template + inline constexpr size_t extent_v<_Tp[], _Idx> = extent_v<_Tp, _Idx - 1>; + #ifdef _GLIBCXX_HAVE_BUILTIN_IS_SAME template inline constexpr bool is_same_v = __is_same(_Tp, _Up); @@ -3408,30 +3438,36 @@ template #define __cpp_lib_bounded_array_traits 201902L /// True for a type that is an array of known bound. + /// @ingroup variable_templates /// @since C++20 template - struct is_bounded_array - : public __is_array_known_bounds<_Tp> - { }; + inline constexpr bool is_bounded_array_v = false; + + template + inline constexpr bool is_bounded_array_v<_Tp[_Size]> = true; /// True for a type that is an array of unknown bound. + /// @ingroup variable_templates /// @since C++20 template - struct is_unbounded_array - : public __is_array_unknown_bounds<_Tp> - { }; + inline constexpr bool is_unbounded_array_v = false; - /// @ingroup variable_templates + template + inline constexpr bool is_unbounded_array_v<_Tp[]> = true; + + /// True for a type that is an array of known bound. /// @since C++20 template - inline constexpr bool is_bounded_array_v - = is_bounded_array<_Tp>::value; + struct is_bounded_array + : public bool_constant> + { }; - /// @ingroup variable_templates + /// True for a type that is an array of unknown bound. /// @since C++20 template - inline constexpr bool is_unbounded_array_v - = is_unbounded_array<_Tp>::value; + struct is_unbounded_array + : public bool_constant> + { }; #if __has_builtin(__is_layout_compatible) -- cgit v1.1 From 0cb8d96157a95b7619ef1ccf28051181415fe989 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Thu, 1 Sep 2022 09:54:57 -0400 Subject: libstdc++: Implement ranges::adjacent_transform_view from P2321R2 libstdc++-v3/ChangeLog: * include/std/ranges (__detail::__unarize): Define. (adjacent_view::_Iterator): Befriend adjacent_transform_view. (adjacent_transform_view): Define. (adjacent_transform_view::_Iterator): Define. (adjacent_transform_view::_Sentinel): Define. (views::__detail::__can_adjacent_transform_view): Define. (views::_AdjacentTransform): Define. (views::adjacent_transform): Define. (views::pairwise_transform): Define. * testsuite/std/ranges/adaptors/adjacent_transform/1.cc: New test. --- libstdc++-v3/include/std/ranges | 341 +++++++++++++++++++++ .../std/ranges/adaptors/adjacent_transform/1.cc | 106 +++++++ 2 files changed, 447 insertions(+) create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 39822b7..dad1e4c 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -5156,6 +5156,20 @@ namespace views::__adaptor // Yields tuple<_Tp, ..., _Tp> with _Nm elements. template using __repeated_tuple = decltype(std::tuple_cat(std::declval>())); + + // For a functor F that is callable with N arguments, the expression + // declval<__unarize>(x) is equivalent to declval(x, ..., x). + template + struct __unarize + { + template + static invoke_result_t<_Fp, _Ts...> + __tuple_apply(const tuple<_Ts...>&); // not defined + + template + decltype(__tuple_apply(std::declval<__repeated_tuple<_Tp, _Nm>>())) + operator()(_Tp&&); // not defined + }; } template @@ -5203,6 +5217,13 @@ namespace views::__adaptor friend class adjacent_view; + template + requires view<_Wp> && (_Mm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Mm>, range_reference_t<_Wp>> + && std::__detail::__can_reference, + range_reference_t<_Wp>>> + friend class adjacent_transform_view; + public: using iterator_category = input_iterator_tag; using iterator_concept = decltype(_S_iter_concept()); @@ -5437,6 +5458,326 @@ namespace views::__adaptor inline constexpr auto pairwise = adjacent<2>; } + + template + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference, + range_reference_t<_Vp>>> + class adjacent_transform_view : public view_interface> + { + [[no_unique_address]] __detail::__box<_Fp> _M_fun; + adjacent_view<_Vp, _Nm> _M_inner; + + using _InnerView = adjacent_view<_Vp, _Nm>; + + template + using _InnerIter = iterator_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template + using _InnerSent = sentinel_t<__detail::__maybe_const_t<_Const, _InnerView>>; + + template class _Iterator; + template class _Sentinel; + + public: + adjacent_transform_view() = default; + + constexpr explicit + adjacent_transform_view(_Vp __base, _Fp __fun) + : _M_fun(std::move(__fun)), _M_inner(std::move(__base)) + { } + + constexpr auto + begin() + { return _Iterator(*this, _M_inner.begin()); } + + constexpr auto + begin() const + requires range + && regular_invocable<__detail::__unarize, + range_reference_t> + { return _Iterator(*this, _M_inner.begin()); } + + constexpr auto + end() + { + if constexpr (common_range<_InnerView>) + return _Iterator(*this, _M_inner.end()); + else + return _Sentinel(_M_inner.end()); + } + + constexpr auto + end() const + requires range + && regular_invocable<__detail::__unarize, + range_reference_t> + { + if constexpr (common_range) + return _Iterator(*this, _M_inner.end()); + else + return _Sentinel(_M_inner.end()); + } + + constexpr auto + size() requires sized_range<_InnerView> + { return _M_inner.size(); } + + constexpr auto + size() const requires sized_range + { return _M_inner.size(); } + }; + + template + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference, + range_reference_t<_Vp>>> + template + class adjacent_transform_view<_Vp, _Fp, _Nm>::_Iterator + { + using _Parent = __detail::__maybe_const_t<_Const, adjacent_transform_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + _Parent* _M_parent = nullptr; + _InnerIter<_Const> _M_inner; + + constexpr + _Iterator(_Parent& __parent, _InnerIter<_Const> __inner) + : _M_parent(std::__addressof(__parent)), _M_inner(std::move(__inner)) + { } + + static auto + _S_iter_cat() + { + using __detail::__maybe_const_t; + using __detail::__unarize; + using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, _Fp>&, _Nm>, + range_reference_t<_Base>>; + using _Cat = iterator_traits>::iterator_category; + if constexpr (!is_lvalue_reference_v<_Res>) + return input_iterator_tag{}; + else if constexpr (derived_from<_Cat, random_access_iterator_tag>) + return random_access_iterator_tag{}; + else if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + friend class adjacent_transform_view; + + public: + using iterator_category = decltype(_S_iter_cat()); + using iterator_concept = typename _InnerIter<_Const>::iterator_concept; + using value_type + = remove_cvref_t&, _Nm>, + range_reference_t<_Base>>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Iterator __i) + requires _Const && convertible_to<_InnerIter, _InnerIter<_Const>> + : _M_parent(__i._M_parent), _M_inner(std::move(__i._M_inner)) + { } + + constexpr decltype(auto) + operator*() const + { + return std::apply([&](const auto&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, *__iters...); + }, _M_inner._M_current); + } + + constexpr _Iterator& + operator++() + { + ++_M_inner; + return *this; + } + + constexpr _Iterator + operator++(int) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __x) requires random_access_range<_Base> + { + _M_inner += __x; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __x) requires random_access_range<_Base> + { + _M_inner -= __x; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const requires random_access_range<_Base> + { + return std::apply([&](const auto&... __iters) -> decltype(auto) { + return std::__invoke(*_M_parent->_M_fun, __iters[__n]...); + }, _M_inner._M_current); + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + { return __x._M_inner == __y._M_inner; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner < __y._M_inner; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner > __y._M_inner; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner <= __y._M_inner; } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_inner >= __y._M_inner; } + + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> && + three_way_comparable<_InnerIter<_Const>> + { return __x._M_inner <=> __y._M_inner; } + + friend constexpr _Iterator + operator+(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { return _Iterator(*__i._M_parent, __i._M_inner + __n); } + + friend constexpr _Iterator + operator+(difference_type __n, const _Iterator& __i) + requires random_access_range<_Base> + { return _Iterator(*__i._M_parent, __i._M_inner + __n); } + + friend constexpr _Iterator + operator-(const _Iterator& __i, difference_type __n) + requires random_access_range<_Base> + { return _Iterator(*__i._M_parent, __i._M_inner - __n); } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires sized_sentinel_for<_InnerIter<_Const>, _InnerIter<_Const>> + { return __x._M_inner - __y._M_inner; } + }; + + template + requires view<_Vp> && (_Nm > 0) && is_object_v<_Fp> + && regular_invocable<__detail::__unarize<_Fp&, _Nm>, range_reference_t<_Vp>> + && std::__detail::__can_reference, + range_reference_t<_Vp>>> + template + class adjacent_transform_view<_Vp, _Fp, _Nm>::_Sentinel + { + _InnerSent<_Const> _M_inner; + + constexpr explicit + _Sentinel(_InnerSent<_Const> __inner) + : _M_inner(__inner) + { } + + friend class adjacent_transform_view; + + public: + _Sentinel() = default; + + constexpr + _Sentinel(_Sentinel __i) + requires _Const && convertible_to<_InnerSent, _InnerSent<_Const>> + : _M_inner(std::move(__i._M_inner)) + { } + + template + requires sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr bool + operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner == __y._M_inner; } + + template + requires sized_sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y) + { return __x._M_inner - __y._M_inner; } + + template + requires sized_sentinel_for<_InnerSent<_Const>, _InnerIter<_OtherConst>> + friend constexpr range_difference_t<__detail::__maybe_const_t<_OtherConst, _InnerView>> + operator-(const _Sentinel& __x, const _Iterator<_OtherConst>& __y) + { return __x._M_inner - __y._M_inner; } + }; + + namespace views + { + namespace __detail + { + template + concept __can_adjacent_transform_view + = requires { adjacent_transform_view, decay_t<_Fp>, _Nm> + (std::declval<_Range>(), std::declval<_Fp>()); }; + } + + template + struct _AdjacentTransform : __adaptor::_RangeAdaptor<_AdjacentTransform<_Nm>> + { + template + requires (_Nm == 0) || __detail::__can_adjacent_transform_view<_Nm, _Range, _Fp> + constexpr auto + operator() [[nodiscard]] (_Range&& __r, _Fp&& __f) const + { + if constexpr (_Nm == 0) + return views::empty>; + else + return adjacent_transform_view, decay_t<_Fp>, _Nm> + (std::forward<_Range>(__r), std::forward<_Fp>(__f)); + } + + using __adaptor::_RangeAdaptor<_AdjacentTransform>::operator(); + static constexpr int _S_arity = 2; + static constexpr bool _S_has_simple_extra_args = true; + }; + + template + inline constexpr _AdjacentTransform<_Nm> adjacent_transform; + + inline constexpr auto pairwise_transform = adjacent_transform<2>; + } #endif // C++23 } // namespace ranges diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc new file mode 100644 index 0000000..07f20b7 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/adjacent_transform/1.cc @@ -0,0 +1,106 @@ +// { dg-options "-std=gnu++23" } +// { dg-do run { target c++23 } } + +#include +#include +#include +#include +#include + +namespace ranges = std::ranges; +namespace views = std::views; + +constexpr bool +test01() +{ + auto v1 = std::array{1, 2, 3} | views::adjacent_transform<1>(std::identity{}); + VERIFY( ranges::equal(v1, (int[]){1, 2, 3}) ); + const auto i0 = v1.begin(), i1 = v1.begin() + 1; + VERIFY( i0 + 1 - 1 == i0 ); + VERIFY( i0 < i1 ); + VERIFY( i1 < v1.end() ); + VERIFY( i1 - i0 == 1 ); + VERIFY( i0 - i1 == -1 ); + VERIFY( v1.end() - i1 == 2 ); + VERIFY( i1 - v1.end() == -2 ); + ranges::iter_swap(i0, i1); + VERIFY( ranges::equal(std::move(v1), (int[]){2, 1, 3}) ); + + auto v2 = std::array{1, -1, 2, -2} | views::pairwise_transform(std::multiplies{}); + auto i2 = v2.begin(); + i2 += 1; + i2 -= -2; + VERIFY( i2 == v2.end() ); + VERIFY( ranges::size(v2) == 3 ); + VERIFY( ranges::size(std::as_const(v2)) == 3 ); + VERIFY( ranges::equal(v2, (int[]){-1, -2, -4}) ); + + int y[] = {1, 2, 3, 4, 5, 6}; + auto v3 = y | views::adjacent_transform<3>([](auto... xs) { return ranges::max({xs...}); }); + VERIFY( ranges::size(v3) == 4 ); + VERIFY( ranges::equal(v3, (int[]){3, 4, 5, 6}) ); + + const auto v6 = y | views::adjacent_transform<6>([](auto...) { return 0; }); + VERIFY( ranges::equal(v6, (int[]){0}) ); + + const auto v7 = y | views::adjacent_transform<7>([](auto...) { return 0; }); + VERIFY( ranges::empty(v7) ); + + const auto v0 = y | views::adjacent_transform<0>([] { return 0; }); + VERIFY( ranges::empty(v0) ); + + return true; +} + +constexpr bool +test02() +{ + using __gnu_test::test_input_range; + using __gnu_test::test_forward_range; + using __gnu_test::test_random_access_range; + + using ty1 = ranges::adjacent_transform_view>, + std::plus<>, 2>; + static_assert(ranges::forward_range); + static_assert(!ranges::bidirectional_range); + static_assert(!ranges::sized_range); + + using ty2 = ranges::adjacent_transform_view>, + decltype([](int, int, int) { return 0;}), 3>; + static_assert(ranges::random_access_range); + static_assert(ranges::sized_range); + + return true; +} + +constexpr bool +test03() +{ + auto v = views::iota(0, 4) + | views::filter([](auto) { return true; }) + | views::pairwise_transform(std::plus{}); + using ty = decltype(v); + static_assert(ranges::forward_range); + static_assert(ranges::common_range); + static_assert(!ranges::sized_range); + VERIFY( v.begin() == v.begin() ); + VERIFY( v.begin() != v.end() ); + VERIFY( ranges::next(v.begin(), 3) == v.end() ); + auto it = v.begin(); + ++it; + it++; + VERIFY( ranges::next(it) == v.end() ); + it--; + --it; + VERIFY( it == v.begin() ); + + return true; +} + +int +main() +{ + static_assert(test01()); + static_assert(test02()); + static_assert(test03()); +} -- cgit v1.1 From 37ff51a98583e63fb9afe83cf9f4351760149028 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 1 Sep 2022 11:52:52 +0100 Subject: libstdc++: Remove FIXME for ICE with remove_cvref_t in requires-expression PR c++/99968 is fixed since GCC 12.1 so we can remove the workaround. libstdc++-v3/ChangeLog: * include/std/type_traits (is_scoped_enum): Remove workaround. --- libstdc++-v3/include/std/type_traits | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 5984442..5b8314f 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -3534,20 +3534,11 @@ template template requires __is_enum(_Tp) - && requires(_Tp __t) { __t = __t; } // fails if incomplete + && requires(remove_cv_t<_Tp> __t) { __t = __t; } // fails if incomplete struct is_scoped_enum<_Tp> : bool_constant { }; - // FIXME remove this partial specialization and use remove_cv_t<_Tp> above - // when PR c++/99968 is fixed. - template - requires __is_enum(_Tp) - && requires(_Tp __t) { __t = __t; } // fails if incomplete - struct is_scoped_enum - : bool_constant - { }; - /// @ingroup variable_templates /// @since C++23 template -- cgit v1.1 From cd20d9482a1f10ddf1c398c1a1d8421f97dfdefa Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 31 Aug 2022 15:00:24 +0100 Subject: libstdc++: Use built-ins for some variable templates This avoids having to instantiate a class template that just uses the same built-in anyway. None of the corresponding class templates have any type-completeness static assertions, so we're not losing any diagnostics by using the built-ins directly. libstdc++-v3/ChangeLog: * include/std/type_traits (is_enum_v, is_class_v, is_union_v) (is_empty_v, is_polymoprhic_v, is_abstract_v, is_final_v) (is_base_of_v, is_aggregate_v): Use built-in directly instead of instantiating class template. --- libstdc++-v3/include/std/type_traits | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 5b8314f..52cca8b 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -3165,11 +3165,11 @@ template inline constexpr bool is_member_function_pointer_v = is_member_function_pointer<_Tp>::value; template - inline constexpr bool is_enum_v = is_enum<_Tp>::value; + inline constexpr bool is_enum_v = __is_enum(_Tp); template - inline constexpr bool is_union_v = is_union<_Tp>::value; + inline constexpr bool is_union_v = __is_union(_Tp); template - inline constexpr bool is_class_v = is_class<_Tp>::value; + inline constexpr bool is_class_v = __is_class(_Tp); template inline constexpr bool is_function_v = is_function<_Tp>::value; template @@ -3206,14 +3206,14 @@ template _GLIBCXX17_DEPRECATED inline constexpr bool is_literal_type_v = is_literal_type<_Tp>::value; #pragma GCC diagnostic pop - template - inline constexpr bool is_empty_v = is_empty<_Tp>::value; template - inline constexpr bool is_polymorphic_v = is_polymorphic<_Tp>::value; + inline constexpr bool is_empty_v = __is_empty(_Tp); template - inline constexpr bool is_abstract_v = is_abstract<_Tp>::value; + inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp); template - inline constexpr bool is_final_v = is_final<_Tp>::value; + inline constexpr bool is_abstract_v = __is_abstract(_Tp); +template + inline constexpr bool is_final_v = __is_final(_Tp); template inline constexpr bool is_signed_v = is_signed<_Tp>::value; template @@ -3318,7 +3318,7 @@ template inline constexpr bool is_same_v = std::is_same<_Tp, _Up>::value; #endif template - inline constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value; + inline constexpr bool is_base_of_v = __is_base_of(_Base, _Derived); template inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; template @@ -3356,16 +3356,19 @@ template #ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE # define __cpp_lib_is_aggregate 201703L - /// is_aggregate + /// is_aggregate - true if the type is an aggregate. /// @since C++17 template struct is_aggregate : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> { }; - /// @ingroup variable_templates + /** is_aggregate_v - true if the type is an aggregate. + * @ingroup variable_templates + * @since C++17 + */ template - inline constexpr bool is_aggregate_v = is_aggregate<_Tp>::value; + inline constexpr bool is_aggregate_v = __is_aggregate(remove_cv_t<_Tp>); #endif #endif // C++17 -- cgit v1.1 From 33005a4be49466880fe3f5a9317bccc8c1ed423b Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 1 Sep 2022 12:32:09 +0100 Subject: libstdc++: Add specializations for some variable templates This avoids having to instantiate a class template when we can detect the true cases easily with a partial specialization. libstdc++-v3/ChangeLog: * include/std/type_traits (is_lvalue_reference_v) (is_rvalue_reference_v, is_reference_v, is_const_v) (is_volatile_v): Define using partial specializations instead of instantiating class templates. --- libstdc++-v3/include/std/type_traits | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 52cca8b..e4b9b59 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -3153,11 +3153,13 @@ template template inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; template - inline constexpr bool is_lvalue_reference_v = - is_lvalue_reference<_Tp>::value; + inline constexpr bool is_lvalue_reference_v = false; template - inline constexpr bool is_rvalue_reference_v = - is_rvalue_reference<_Tp>::value; + inline constexpr bool is_lvalue_reference_v<_Tp&> = true; +template + inline constexpr bool is_rvalue_reference_v = false; +template + inline constexpr bool is_rvalue_reference_v<_Tp&&> = true; template inline constexpr bool is_member_object_pointer_v = is_member_object_pointer<_Tp>::value; @@ -3173,7 +3175,11 @@ template template inline constexpr bool is_function_v = is_function<_Tp>::value; template - inline constexpr bool is_reference_v = is_reference<_Tp>::value; + inline constexpr bool is_reference_v = false; +template + inline constexpr bool is_reference_v<_Tp&> = true; +template + inline constexpr bool is_reference_v<_Tp&&> = true; template inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; template @@ -3187,9 +3193,13 @@ template template inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; template - inline constexpr bool is_const_v = is_const<_Tp>::value; + inline constexpr bool is_const_v = false; +template + inline constexpr bool is_const_v = true; +template + inline constexpr bool is_volatile_v = false; template - inline constexpr bool is_volatile_v = is_volatile<_Tp>::value; + inline constexpr bool is_volatile_v = true; template inline constexpr bool is_trivial_v = is_trivial<_Tp>::value; template -- cgit v1.1 From 775fe01b38933850dcb884733c4d0edc7cde45c3 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 1 Sep 2022 13:06:13 +0100 Subject: libstdc++: Optimize std::decay Define partial specializations of std::decay and its __decay_selector helper so that remove_reference, is_array and is_function are not instantiated for every type, and remove_extent is not instantiated for arrays. libstdc++-v3/ChangeLog: * include/std/type_traits (__decay_selector): Add partial specializations for array types. Only check for function types when not dealing with an array. (decay): Add partial specializations for reference types. --- libstdc++-v3/include/std/type_traits | 39 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index e4b9b59..639c351 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2203,34 +2203,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Decay trait for arrays and functions, used for perfect forwarding // in make_pair, make_tuple, etc. - template::value, - bool _IsFunction = is_function<_Up>::value> - struct __decay_selector; - - // NB: DR 705. template - struct __decay_selector<_Up, false, false> - { typedef __remove_cv_t<_Up> __type; }; + struct __decay_selector + : __conditional_t::value, // false for functions + remove_cv<_Up>, // N.B. DR 705. + add_pointer<_Up>> // function decays to pointer + { }; - template - struct __decay_selector<_Up, true, false> - { typedef typename remove_extent<_Up>::type* __type; }; + template + struct __decay_selector<_Up[_Nm]> + { using type = _Up*; }; template - struct __decay_selector<_Up, false, true> - { typedef typename add_pointer<_Up>::type __type; }; + struct __decay_selector<_Up[]> + { using type = _Up*; }; + /// @endcond /// decay template - class decay - { - typedef typename remove_reference<_Tp>::type __remove_type; + struct decay + { using type = typename __decay_selector<_Tp>::type; }; - public: - typedef typename __decay_selector<__remove_type>::__type type; - }; + template + struct decay<_Tp&> + { using type = typename __decay_selector<_Tp>::type; }; + + template + struct decay<_Tp&&> + { using type = typename __decay_selector<_Tp>::type; }; /// @cond undocumented -- cgit v1.1 From 9bcedbbfc510e79cd299001dd79756ee4173b411 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 1 Sep 2022 15:19:28 +0100 Subject: libstdc++: Optimize is_constructible traits We can replace some class template helpers with alias templates, which are cheaper to instantiate. For example, replace the __is_copy_constructible_impl class template with an alias template that uses just evaluates the __is_constructible built-in, using add_lvalue_reference to get the argument type in a way that works for non-referenceable types. For a given specialization of is_copy_constructible this results in the same number of class templates being instantiated (for the common case of non-void, non-function types), but the add_lvalue_reference instantiations are not specific to the is_copy_constructible specialization and so can be reused by other traits. Previously __is_copy_constructible_impl was a distinct class template and its specializations were never used for anything except is_copy_constructible. With the new definitions of these traits that don't depend on helper classes, it becomes more practical to optimize the is_xxx_constructible_v variable templates to avoid instantiations. Previously doing so would have meant two entirely separate implementation strategies for these traits. libstdc++-v3/ChangeLog: * include/std/type_traits (__is_constructible_impl): Replace class template with alias template. (is_default_constructible, is_nothrow_constructible) (is_nothrow_constructible): Simplify base-specifier. (__is_copy_constructible_impl, __is_move_constructible_impl) (__is_nothrow_copy_constructible_impl) (__is_nothrow_move_constructible_impl): Remove class templates. (is_copy_constructible, is_move_constructible) (is_nothrow_constructible, is_nothrow_default_constructible) (is_nothrow_copy_constructible, is_nothrow_move_constructible): Adjust base-specifiers to use __is_constructible_impl. (__is_copy_assignable_impl, __is_move_assignable_impl) (__is_nt_copy_assignable_impl, __is_nt_move_assignable_impl): Remove class templates. (__is_assignable_impl): New alias template. (is_assignable, is_copy_assignable, is_move_assignable): Adjust base-specifiers to use new alias template. (is_nothrow_copy_assignable, is_nothrow_move_assignable): Adjust base-specifiers to use existing alias template. (__is_trivially_constructible_impl): New alias template. (is_trivially_constructible, is_trivially_default_constructible) (is_trivially_copy_constructible) (is_trivially_move_constructible): Adjust base-specifiers to use new alias template. (__is_trivially_assignable_impl): New alias template. (is_trivially_assignable, is_trivially_copy_assignable) (is_trivially_move_assignable): Adjust base-specifier to use new alias template. (__add_lval_ref_t, __add_rval_ref_t): New alias templates. (add_lvalue_reference, add_rvalue_reference): Use new alias templates. --- libstdc++-v3/include/std/type_traits | 239 +++++++++-------------------------- 1 file changed, 57 insertions(+), 182 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 639c351..3041ac3 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -1001,9 +1001,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented template - struct __is_constructible_impl - : public __bool_constant<__is_constructible(_Tp, _Args...)> - { }; + using __is_constructible_impl + = __bool_constant<__is_constructible(_Tp, _Args...)>; /// @endcond /// is_constructible @@ -1018,7 +1017,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_default_constructible template struct is_default_constructible - : public __is_constructible_impl<_Tp>::type + : public __is_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1026,22 +1025,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented template::value> - struct __is_copy_constructible_impl; + struct __add_lvalue_reference_helper + { using type = _Tp; }; template - struct __is_copy_constructible_impl<_Tp, false> - : public false_type { }; + struct __add_lvalue_reference_helper<_Tp, true> + { using type = _Tp&; }; template - struct __is_copy_constructible_impl<_Tp, true> - : public __is_constructible_impl<_Tp, const _Tp&> - { }; + using __add_lval_ref_t = typename __add_lvalue_reference_helper<_Tp>::type; /// @endcond /// is_copy_constructible template struct is_copy_constructible - : public __is_copy_constructible_impl<_Tp> + : public __is_constructible_impl<_Tp, __add_lval_ref_t> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1049,22 +1047,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented template::value> - struct __is_move_constructible_impl; + struct __add_rvalue_reference_helper + { using type = _Tp; }; template - struct __is_move_constructible_impl<_Tp, false> - : public false_type { }; + struct __add_rvalue_reference_helper<_Tp, true> + { using type = _Tp&&; }; template - struct __is_move_constructible_impl<_Tp, true> - : public __is_constructible_impl<_Tp, _Tp&&> - { }; + using __add_rval_ref_t = typename __add_rvalue_reference_helper<_Tp>::type; /// @endcond /// is_move_constructible template struct is_move_constructible - : public __is_move_constructible_impl<_Tp> + : public __is_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1079,7 +1076,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_nothrow_constructible template struct is_nothrow_constructible - : public __is_nothrow_constructible_impl<_Tp, _Args...>::type + : public __is_nothrow_constructible_impl<_Tp, _Args...> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1088,112 +1085,68 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_nothrow_default_constructible template struct is_nothrow_default_constructible - : public __bool_constant<__is_nothrow_constructible(_Tp)> + : public __is_nothrow_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - /// @cond undocumented - template::value> - struct __is_nothrow_copy_constructible_impl; - - template - struct __is_nothrow_copy_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_nothrow_copy_constructible_impl<_Tp, true> - : public __is_nothrow_constructible_impl<_Tp, const _Tp&> - { }; - /// @endcond - /// is_nothrow_copy_constructible template struct is_nothrow_copy_constructible - : public __is_nothrow_copy_constructible_impl<_Tp>::type + : public __is_nothrow_constructible_impl<_Tp, __add_lval_ref_t> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - /// @cond undocumented - template::value> - struct __is_nothrow_move_constructible_impl; - - template - struct __is_nothrow_move_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_nothrow_move_constructible_impl<_Tp, true> - : public __is_nothrow_constructible_impl<_Tp, _Tp&&> - { }; - /// @endcond - /// is_nothrow_move_constructible template struct is_nothrow_move_constructible - : public __is_nothrow_move_constructible_impl<_Tp>::type + : public __is_nothrow_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; + /// @cond undocumented + template + using __is_assignable_impl = __bool_constant<__is_assignable(_Tp, _Up)>; + /// @endcond + /// is_assignable template struct is_assignable - : public __bool_constant<__is_assignable(_Tp, _Up)> + : public __is_assignable_impl<_Tp, _Up> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template::value> - struct __is_copy_assignable_impl; - - template - struct __is_copy_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_copy_assignable_impl<_Tp, true> - : public __bool_constant<__is_assignable(_Tp&, const _Tp&)> - { }; - /// is_copy_assignable template struct is_copy_assignable - : public __is_copy_assignable_impl<_Tp>::type + : public __is_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template::value> - struct __is_move_assignable_impl; - - template - struct __is_move_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_move_assignable_impl<_Tp, true> - : public __bool_constant<__is_assignable(_Tp&, _Tp&&)> - { }; - /// is_move_assignable template struct is_move_assignable - : public __is_move_assignable_impl<_Tp>::type + : public __is_assignable_impl<__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; + /// @cond undocumented template using __is_nothrow_assignable_impl = __bool_constant<__is_nothrow_assignable(_Tp, _Up)>; + /// @endcond /// is_nothrow_assignable template @@ -1204,52 +1157,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "template argument must be a complete class or an unbounded array"); }; - template::value> - struct __is_nt_copy_assignable_impl; - - template - struct __is_nt_copy_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_nt_copy_assignable_impl<_Tp, true> - : public __is_nothrow_assignable_impl<_Tp&, const _Tp&> - { }; - /// is_nothrow_copy_assignable template struct is_nothrow_copy_assignable - : public __is_nt_copy_assignable_impl<_Tp> + : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template::value> - struct __is_nt_move_assignable_impl; - - template - struct __is_nt_move_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_nt_move_assignable_impl<_Tp, true> - : public __is_nothrow_assignable_impl<_Tp&, _Tp&&> - { }; - /// is_nothrow_move_assignable template struct is_nothrow_move_assignable - : public __is_nt_move_assignable_impl<_Tp> + : public __is_nothrow_assignable_impl<__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; + /// @cond undocumented + template + using __is_trivially_constructible_impl + = __bool_constant<__is_trivially_constructible(_Tp, _Args...)>; + /// @endcond + /// is_trivially_constructible template struct is_trivially_constructible - : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)> + : public __is_trivially_constructible_impl<_Tp, _Args...> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1258,7 +1195,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_trivially_default_constructible template struct is_trivially_default_constructible - : public __bool_constant<__is_trivially_constructible(_Tp)> + : public __is_trivially_constructible_impl<_Tp> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1294,98 +1231,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __is_implicitly_default_constructible_safe<_Tp>> { }; - template::value> - struct __is_trivially_copy_constructible_impl; - - template - struct __is_trivially_copy_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_trivially_copy_constructible_impl<_Tp, true> - : public __and_<__is_copy_constructible_impl<_Tp>, - integral_constant> - { }; - /// is_trivially_copy_constructible template struct is_trivially_copy_constructible - : public __is_trivially_copy_constructible_impl<_Tp> + : public __is_trivially_constructible_impl<_Tp, __add_lval_ref_t> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template::value> - struct __is_trivially_move_constructible_impl; - - template - struct __is_trivially_move_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_trivially_move_constructible_impl<_Tp, true> - : public __and_<__is_move_constructible_impl<_Tp>, - integral_constant> - { }; - /// is_trivially_move_constructible template struct is_trivially_move_constructible - : public __is_trivially_move_constructible_impl<_Tp> + : public __is_trivially_constructible_impl<_Tp, __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; + /// @cond undocumented + template + using __is_trivially_assignable_impl + = __bool_constant<__is_trivially_assignable(_Tp, _Up)>; + /// @endcond + /// is_trivially_assignable template struct is_trivially_assignable - : public __bool_constant<__is_trivially_assignable(_Tp, _Up)> + : public __is_trivially_assignable_impl<_Tp, _Up> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template::value> - struct __is_trivially_copy_assignable_impl; - - template - struct __is_trivially_copy_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_trivially_copy_assignable_impl<_Tp, true> - : public __bool_constant<__is_trivially_assignable(_Tp&, const _Tp&)> - { }; - /// is_trivially_copy_assignable template struct is_trivially_copy_assignable - : public __is_trivially_copy_assignable_impl<_Tp> + : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>, + __add_lval_ref_t> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - template::value> - struct __is_trivially_move_assignable_impl; - - template - struct __is_trivially_move_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_trivially_move_assignable_impl<_Tp, true> - : public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)> - { }; - /// is_trivially_move_assignable template struct is_trivially_move_assignable - : public __is_trivially_move_assignable_impl<_Tp> + : public __is_trivially_assignable_impl<__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>> { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -1669,33 +1562,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct remove_reference<_Tp&&> { typedef _Tp type; }; - template::value> - struct __add_lvalue_reference_helper - { typedef _Tp type; }; - - template - struct __add_lvalue_reference_helper<_Tp, true> - { typedef _Tp& type; }; - /// add_lvalue_reference template struct add_lvalue_reference - : public __add_lvalue_reference_helper<_Tp> - { }; - - template::value> - struct __add_rvalue_reference_helper - { typedef _Tp type; }; - - template - struct __add_rvalue_reference_helper<_Tp, true> - { typedef _Tp&& type; }; + { using type = __add_lval_ref_t<_Tp>; }; /// add_rvalue_reference template struct add_rvalue_reference - : public __add_rvalue_reference_helper<_Tp> - { }; + { using type = __add_rval_ref_t<_Tp>; }; #if __cplusplus > 201103L /// Alias template for remove_reference -- cgit v1.1 From 56bb34e3d2c800a7f13e65755bccfb6b2dc5e898 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 1 Sep 2022 15:58:34 +0100 Subject: libstdc++: Remove __is_referenceable helper We only use the __is_referenceable helper in three places now: add_pointer, add_lvalue_reference, and add_rvalue_reference. But lots of other traits depend on add_[lr]value_reference, and decay depends on add_pointer, so removing the instantiation of __is_referenceable helps compile all those other traits slightly faster. We can just use void_t to check for a referenceable type in the add_[lr]value_reference traits. Then we can specialize add_pointer for reference types, so that we don't need to use remove_reference, and then use void_t for all non-reference types to detect when we can form a pointer to the type. libstdc++-v3/ChangeLog: * include/std/type_traits (__is_referenceable): Remove. (__add_lvalue_reference_helper, __add_rvalue_reference_helper): Use __void_t instead of __is_referenceable. (__add_pointer_helper): Likewise. (add_pointer): Add partial specializations for reference types. --- libstdc++-v3/include/std/type_traits | 37 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 21 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 3041ac3..8b11f31 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -712,18 +712,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __void_t (std::void_t for C++11) template using __void_t = void; - - // Utility to detect referenceable types ([defns.referenceable]). - - template - struct __is_referenceable - : public false_type - { }; - - template - struct __is_referenceable<_Tp, __void_t<_Tp&>> - : public true_type - { }; /// @endcond // Type properties. @@ -1024,12 +1012,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; /// @cond undocumented - template::value> + template struct __add_lvalue_reference_helper { using type = _Tp; }; template - struct __add_lvalue_reference_helper<_Tp, true> + struct __add_lvalue_reference_helper<_Tp, __void_t<_Tp&>> { using type = _Tp&; }; template @@ -1046,12 +1034,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; /// @cond undocumented - template::value> + template struct __add_rvalue_reference_helper { using type = _Tp; }; template - struct __add_rvalue_reference_helper<_Tp, true> + struct __add_rvalue_reference_helper<_Tp, __void_t<_Tp&&>> { using type = _Tp&&; }; template @@ -1971,14 +1959,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>> { }; - template, - is_void<_Tp>>::value> + template struct __add_pointer_helper - { typedef _Tp type; }; + { using type = _Tp; }; template - struct __add_pointer_helper<_Tp, true> - { typedef typename remove_reference<_Tp>::type* type; }; + struct __add_pointer_helper<_Tp, __void_t<_Tp*>> + { using type = _Tp*; }; /// add_pointer template @@ -1986,6 +1973,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __add_pointer_helper<_Tp> { }; + template + struct add_pointer<_Tp&> + { using type = _Tp*; }; + + template + struct add_pointer<_Tp&&> + { using type = _Tp*; }; + #if __cplusplus > 201103L /// Alias template for remove_pointer template -- cgit v1.1 From 42e489088bf53845c648e512449b72dbd3c7169b Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 1 Sep 2022 20:36:06 +0100 Subject: libstdc++: Add 'typename' for Clang compatibility Clang doesn't yet implement the C++20 change that makes 'typename' optional here. libstdc++-v3/ChangeLog: * include/std/ranges (adjacent_transform_view::_Iterator): Add typename keyword before dependent qualified-id. --- libstdc++-v3/include/std/ranges | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index dad1e4c..2b5cb05 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -5555,7 +5555,7 @@ namespace views::__adaptor using __detail::__unarize; using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, _Fp>&, _Nm>, range_reference_t<_Base>>; - using _Cat = iterator_traits>::iterator_category; + using _Cat = typename iterator_traits>::iterator_category; if constexpr (!is_lvalue_reference_v<_Res>) return input_iterator_tag{}; else if constexpr (derived_from<_Cat, random_access_iterator_tag>) -- cgit v1.1 From bb0a1556df79d02cf570f5eb17a1b02a509f0be4 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 2 Sep 2022 00:16:33 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 712ce17..2547cd6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,102 @@ +2022-09-01 Jonathan Wakely + + * include/std/ranges (adjacent_transform_view::_Iterator): Add + typename keyword before dependent qualified-id. + +2022-09-01 Jonathan Wakely + + * include/std/type_traits (__is_referenceable): Remove. + (__add_lvalue_reference_helper, __add_rvalue_reference_helper): + Use __void_t instead of __is_referenceable. + (__add_pointer_helper): Likewise. + (add_pointer): Add partial specializations for reference types. + +2022-09-01 Jonathan Wakely + + * include/std/type_traits (__is_constructible_impl): Replace + class template with alias template. + (is_default_constructible, is_nothrow_constructible) + (is_nothrow_constructible): Simplify base-specifier. + (__is_copy_constructible_impl, __is_move_constructible_impl) + (__is_nothrow_copy_constructible_impl) + (__is_nothrow_move_constructible_impl): Remove class templates. + (is_copy_constructible, is_move_constructible) + (is_nothrow_constructible, is_nothrow_default_constructible) + (is_nothrow_copy_constructible, is_nothrow_move_constructible): + Adjust base-specifiers to use __is_constructible_impl. + (__is_copy_assignable_impl, __is_move_assignable_impl) + (__is_nt_copy_assignable_impl, __is_nt_move_assignable_impl): + Remove class templates. + (__is_assignable_impl): New alias template. + (is_assignable, is_copy_assignable, is_move_assignable): + Adjust base-specifiers to use new alias template. + (is_nothrow_copy_assignable, is_nothrow_move_assignable): + Adjust base-specifiers to use existing alias template. + (__is_trivially_constructible_impl): New alias template. + (is_trivially_constructible, is_trivially_default_constructible) + (is_trivially_copy_constructible) + (is_trivially_move_constructible): Adjust base-specifiers to use + new alias template. + (__is_trivially_assignable_impl): New alias template. + (is_trivially_assignable, is_trivially_copy_assignable) + (is_trivially_move_assignable): Adjust base-specifier to use + new alias template. + (__add_lval_ref_t, __add_rval_ref_t): New alias templates. + (add_lvalue_reference, add_rvalue_reference): Use new alias + templates. + +2022-09-01 Jonathan Wakely + + * include/std/type_traits (__decay_selector): Add partial + specializations for array types. Only check for function types + when not dealing with an array. + (decay): Add partial specializations for reference types. + +2022-09-01 Jonathan Wakely + + * include/std/type_traits (is_lvalue_reference_v) + (is_rvalue_reference_v, is_reference_v, is_const_v) + (is_volatile_v): Define using partial specializations instead + of instantiating class templates. + +2022-09-01 Jonathan Wakely + + * include/std/type_traits (is_enum_v, is_class_v, is_union_v) + (is_empty_v, is_polymoprhic_v, is_abstract_v, is_final_v) + (is_base_of_v, is_aggregate_v): Use built-in directly instead of + instantiating class template. + +2022-09-01 Jonathan Wakely + + * include/std/type_traits (is_scoped_enum): Remove workaround. + +2022-09-01 Patrick Palka + + * include/std/ranges (__detail::__unarize): Define. + (adjacent_view::_Iterator): Befriend adjacent_transform_view. + (adjacent_transform_view): Define. + (adjacent_transform_view::_Iterator): Define. + (adjacent_transform_view::_Sentinel): Define. + (views::__detail::__can_adjacent_transform_view): Define. + (views::_AdjacentTransform): Define. + (views::adjacent_transform): Define. + (views::pairwise_transform): Define. + * testsuite/std/ranges/adaptors/adjacent_transform/1.cc: New test. + +2022-09-01 Jonathan Wakely + + * include/std/type_traits (__is_array_known_bounds): Add partial + specialization instead of using std::extent. + (__is_array_unknown_bounds): Likewise. + (extent): Add partial specializations to stop recursion after + the result is found. + (is_array_v): Add partial specializations instead of + instantiating the class template. + (rank_v, extent_v): Likewise. + (is_bounded_array_v, is_unbounded_array_v): Likewise. + (is_bounded_array, is_unbounded_array): Define in terms of the + variable templates. + 2022-08-31 Patrick Palka * include/bits/ranges_base.h (__advance_fn::operator()): Add -- cgit v1.1 From 51c42b38e43b5283b116882529d232719b099bfc Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 2 Sep 2022 11:19:51 -0400 Subject: libstdc++: Fix laziness of __and/or/not_ r13-2230-g390f94eee1ae69 redefined the internal logical operator traits __and_, __or_ and __not_ as alias templates that directly resolve to true_type or false_type. But it turns out using an alias template here causes the traits to be less lazy than before because we now compute the logical result immediately upon _specialization_ of the trait, and not later upon _completion_ of the specialization. So for example, in using type = __and_>; we now compute the conjunction and thus instantiate A even though we're in a context that doesn't require completion of the __and_. What's worse is that we also compute the inner negation and thus instantiate B (for the same reason), independent of the __and_ and the value of A! Thus the traits are now less lazy and composable than before. Fortunately, the fix is cheap and straightforward: redefine these traits as class templates instead of as alias templates so that computation of the logical result is triggered by completion, not by specialization. libstdc++-v3/ChangeLog: * include/std/type_traits (__or_, __and_, __not_): Redefine as a class template instead of as an alias template. * testsuite/20_util/logical_traits/requirements/short_circuit.cc: Add more tests for conjunction and disjunction. Add corresponding tests for __and_ and __or_. --- libstdc++-v3/include/std/type_traits | 12 ++++++--- .../logical_traits/requirements/short_circuit.cc | 29 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 8b11f31..be9f295 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -168,13 +168,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // to either true_type or false_type which allows for a more efficient // implementation that avoids recursive class template instantiation. template - using __or_ = decltype(__detail::__or_fn<_Bn...>(0)); + struct __or_ + : decltype(__detail::__or_fn<_Bn...>(0)) + { }; template - using __and_ = decltype(__detail::__and_fn<_Bn...>(0)); + struct __and_ + : decltype(__detail::__and_fn<_Bn...>(0)) + { }; template - using __not_ = __bool_constant; + struct __not_ + : __bool_constant + { }; /// @endcond #if __cplusplus >= 201703L diff --git a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc index 86996b2..ff90f8a 100644 --- a/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc +++ b/libstdc++-v3/testsuite/20_util/logical_traits/requirements/short_circuit.cc @@ -14,6 +14,10 @@ static_assert(!std::conjunction_v); static_assert(!std::conjunction_v); static_assert(!std::conjunction_v); static_assert(!std::conjunction_v); +static_assert(!std::conjunction_v, + std::disjunction, + std::negation>); // [meta.logical]/8: For a specialization disjunction, if // there is a template type argument B_i for which bool(B_i::value) is true, @@ -24,3 +28,28 @@ static_assert(std::disjunction_v); static_assert(std::disjunction_v); static_assert(std::disjunction_v); static_assert(std::disjunction_v); +static_assert(std::disjunction_v, + std::disjunction, + std::negation>); + +#if __GLIBCXX__ +// Also test the corresponding internal traits __and_, __or_ and __not_. +static_assert(!std::__and_v); +static_assert(!std::__and_v); +static_assert(!std::__and_v); +static_assert(!std::__and_v); +static_assert(!std::__and_v, + std::__or_, + std::__not_>); + +static_assert(std::__or_v); +static_assert(std::__or_v); +static_assert(std::__or_v); +static_assert(std::__or_v); +static_assert(std::__or_v, + std::__or_, + std::__not_>); +#endif -- cgit v1.1 From 45433832a1ec392814e7f1cb7559bca48c2cb4e0 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 1 Sep 2022 20:40:42 +0100 Subject: libstdc++: Optimize constructible/assignable variable templates This defines the is_xxx_constructible_v and is_xxx_assignable_v variable templates by using the built-ins directly. The actual logic for each one is the same as the corresponding class template, but way using the variable template doesn't need to instantiate the class template. This means that the variable templates won't use the static assertions checking for complete types, cv void or unbounded arrays, but that's OK because the built-ins check those anyway. We could probably remove the static assertions from the class templates, and maybe from all type traits that use a built-in. libstdc++-v3/ChangeLog: * include/std/type_traits (is_constructible_v) (is_default_constructible_v, is_copy_constructible_v) (is_move_constructible_v): Define using __is_constructible. (is_assignable_v, is_copy_assignable_v, is_move_assignable_v): Define using __is_assignable. (is_trivially_constructible_v) (is_trivially_default_constructible_v) (is_trivially_copy_constructible_v) (is_trivially_move_constructible_v): Define using __is_trivially_constructible. (is_trivially_assignable_v, is_trivially_copy_assignable_v) (is_trivially_move_assignable_v): Define using __is_trivially_assignable. (is_nothrow_constructible_v) (is_nothrow_default_constructible_v) (is_nothrow_copy_constructible_v) (is_nothrow_move_constructible_v): Define using __is_nothrow_constructible. (is_nothrow_assignable_v, is_nothrow_copy_assignable_v) (is_nothrow_move_assignable_v): Define using __is_nothrow_assignable. --- libstdc++-v3/include/std/type_traits | 88 ++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 39 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index be9f295..2f5fe80 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -3105,71 +3105,81 @@ template inline constexpr bool is_signed_v = is_signed<_Tp>::value; template inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; + template - inline constexpr bool is_constructible_v = - is_constructible<_Tp, _Args...>::value; + inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...); template - inline constexpr bool is_default_constructible_v = - is_default_constructible<_Tp>::value; + inline constexpr bool is_default_constructible_v = __is_constructible(_Tp); template - inline constexpr bool is_copy_constructible_v = - is_copy_constructible<_Tp>::value; + inline constexpr bool is_copy_constructible_v + = __is_constructible(_Tp, __add_lval_ref_t); template - inline constexpr bool is_move_constructible_v = - is_move_constructible<_Tp>::value; + inline constexpr bool is_move_constructible_v + = __is_constructible(_Tp, __add_rval_ref_t<_Tp>); + template - inline constexpr bool is_assignable_v = is_assignable<_Tp, _Up>::value; + inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Up); template - inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; + inline constexpr bool is_copy_assignable_v + = __is_assignable(__add_lval_ref_t<_Tp>, __add_lval_ref_t); template - inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value; + inline constexpr bool is_move_assignable_v + = __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); + template inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; + template - inline constexpr bool is_trivially_constructible_v = - is_trivially_constructible<_Tp, _Args...>::value; + inline constexpr bool is_trivially_constructible_v + = __is_trivially_constructible(_Tp, _Args...); template - inline constexpr bool is_trivially_default_constructible_v = - is_trivially_default_constructible<_Tp>::value; + inline constexpr bool is_trivially_default_constructible_v + = __is_trivially_constructible(_Tp); template - inline constexpr bool is_trivially_copy_constructible_v = - is_trivially_copy_constructible<_Tp>::value; + inline constexpr bool is_trivially_copy_constructible_v + = __is_trivially_constructible(_Tp, __add_lval_ref_t); template - inline constexpr bool is_trivially_move_constructible_v = - is_trivially_move_constructible<_Tp>::value; + inline constexpr bool is_trivially_move_constructible_v + = __is_trivially_constructible(_Tp, __add_rval_ref_t<_Tp>); + template - inline constexpr bool is_trivially_assignable_v = - is_trivially_assignable<_Tp, _Up>::value; + inline constexpr bool is_trivially_assignable_v + = __is_trivially_assignable(_Tp, _Up); template - inline constexpr bool is_trivially_copy_assignable_v = - is_trivially_copy_assignable<_Tp>::value; + inline constexpr bool is_trivially_copy_assignable_v + = __is_trivially_assignable(__add_lval_ref_t<_Tp>, + __add_lval_ref_t); template - inline constexpr bool is_trivially_move_assignable_v = - is_trivially_move_assignable<_Tp>::value; + inline constexpr bool is_trivially_move_assignable_v + = __is_trivially_assignable(__add_lval_ref_t<_Tp>, + __add_rval_ref_t<_Tp>); template inline constexpr bool is_trivially_destructible_v = is_trivially_destructible<_Tp>::value; template - inline constexpr bool is_nothrow_constructible_v = - is_nothrow_constructible<_Tp, _Args...>::value; + inline constexpr bool is_nothrow_constructible_v + = __is_nothrow_constructible(_Tp, _Args...); template - inline constexpr bool is_nothrow_default_constructible_v = - is_nothrow_default_constructible<_Tp>::value; + inline constexpr bool is_nothrow_default_constructible_v + = __is_nothrow_constructible(_Tp); template - inline constexpr bool is_nothrow_copy_constructible_v = - is_nothrow_copy_constructible<_Tp>::value; + inline constexpr bool is_nothrow_copy_constructible_v + = __is_nothrow_constructible(_Tp, __add_lval_ref_t); template - inline constexpr bool is_nothrow_move_constructible_v = - is_nothrow_move_constructible<_Tp>::value; + inline constexpr bool is_nothrow_move_constructible_v + = __is_nothrow_constructible(_Tp, __add_rval_ref_t<_Tp>); + template - inline constexpr bool is_nothrow_assignable_v = - is_nothrow_assignable<_Tp, _Up>::value; + inline constexpr bool is_nothrow_assignable_v + = __is_nothrow_assignable(_Tp, _Up); template - inline constexpr bool is_nothrow_copy_assignable_v = - is_nothrow_copy_assignable<_Tp>::value; + inline constexpr bool is_nothrow_copy_assignable_v + = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, + __add_lval_ref_t); template - inline constexpr bool is_nothrow_move_assignable_v = - is_nothrow_move_assignable<_Tp>::value; + inline constexpr bool is_nothrow_move_assignable_v + = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); + template inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<_Tp>::value; -- cgit v1.1 From 68c23af0dd7403c95c43310edc15669d4dacb005 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 2 Sep 2022 15:16:37 -0400 Subject: libstdc++: Consistently use ::type when deriving from __and/or/not_ Now that these internal type traits are (again) class templates, it's better to derive from the trait's ::type instead of from the trait itself, for sake of a shallower inheritance chain. libstdc++-v3/ChangeLog: * include/std/tuple (tuple::_UseOtherCtor): Use ::type when deriving from __and_, __or_ or __not_. * include/std/type_traits (negation): Likewise. (is_unsigned): Likewise. (__is_implicitly_default_constructible): Likewise. (is_trivially_destructible): Likewise. (__is_nt_invocable_impl): Likewise. --- libstdc++-v3/include/std/tuple | 2 +- libstdc++-v3/include/std/type_traits | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index ddd7c22..26e2484 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -826,7 +826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // then TUPLE should match tuple(UTypes&&...) instead. template struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>> - : __or_, is_constructible<_Tp, _Tuple>> + : __or_, is_constructible<_Tp, _Tuple>>::type { }; // If TUPLE and *this each have a single element of the same type, // then TUPLE should match a copy/move constructor instead. diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 2f5fe80..c7a9607 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -235,7 +235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct negation - : __not_<_Pp> + : __not_<_Pp>::type { }; /** @ingroup variable_templates @@ -845,7 +845,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// is_unsigned template struct is_unsigned - : public __and_, __not_>> + : public __and_, __not_>>::type { }; /// @cond undocumented @@ -1222,7 +1222,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __is_implicitly_default_constructible : public __and_<__is_constructible_impl<_Tp>, - __is_implicitly_default_constructible_safe<_Tp>> + __is_implicitly_default_constructible_safe<_Tp>>::type { }; /// is_trivially_copy_constructible @@ -1282,7 +1282,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct is_trivially_destructible : public __and_<__is_destructible_safe<_Tp>, - __bool_constant<__has_trivial_destructor(_Tp)>> + __bool_constant<__has_trivial_destructor(_Tp)>>::type { static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); @@ -2975,7 +2975,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __is_nt_invocable_impl<_Result, _Ret, __void_t> : __or_, - __is_nothrow_convertible> + __is_nothrow_convertible>::type { }; /// @endcond -- cgit v1.1 From c64b09471a8a06e929c70bf6017d7163776145e0 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 3 Sep 2022 00:17:21 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 2547cd6..d905767 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,45 @@ +2022-09-02 Patrick Palka + + * include/std/tuple (tuple::_UseOtherCtor): Use ::type when + deriving from __and_, __or_ or __not_. + * include/std/type_traits (negation): Likewise. + (is_unsigned): Likewise. + (__is_implicitly_default_constructible): Likewise. + (is_trivially_destructible): Likewise. + (__is_nt_invocable_impl): Likewise. + +2022-09-02 Jonathan Wakely + + * include/std/type_traits (is_constructible_v) + (is_default_constructible_v, is_copy_constructible_v) + (is_move_constructible_v): Define using __is_constructible. + (is_assignable_v, is_copy_assignable_v, is_move_assignable_v): + Define using __is_assignable. + (is_trivially_constructible_v) + (is_trivially_default_constructible_v) + (is_trivially_copy_constructible_v) + (is_trivially_move_constructible_v): Define using + __is_trivially_constructible. + (is_trivially_assignable_v, is_trivially_copy_assignable_v) + (is_trivially_move_assignable_v): Define using + __is_trivially_assignable. + (is_nothrow_constructible_v) + (is_nothrow_default_constructible_v) + (is_nothrow_copy_constructible_v) + (is_nothrow_move_constructible_v): Define using + __is_nothrow_constructible. + (is_nothrow_assignable_v, is_nothrow_copy_assignable_v) + (is_nothrow_move_assignable_v): Define using + __is_nothrow_assignable. + +2022-09-02 Patrick Palka + + * include/std/type_traits (__or_, __and_, __not_): Redefine as a + class template instead of as an alias template. + * testsuite/20_util/logical_traits/requirements/short_circuit.cc: + Add more tests for conjunction and disjunction. Add corresponding + tests for __and_ and __or_. + 2022-09-01 Jonathan Wakely * include/std/ranges (adjacent_transform_view::_Iterator): Add -- cgit v1.1