aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog172
-rw-r--r--libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt11
-rw-r--r--libstdc++-v3/include/bits/max_size_type.h83
-rw-r--r--libstdc++-v3/include/bits/shared_ptr.h58
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h40
-rw-r--r--libstdc++-v3/include/bits/version.def9
-rw-r--r--libstdc++-v3/include/bits/version.h10
-rw-r--r--libstdc++-v3/include/debug/forward_list8
-rw-r--r--libstdc++-v3/include/std/format4
-rw-r--r--libstdc++-v3/include/std/mdspan8
-rw-r--r--libstdc++-v3/include/std/memory1
-rw-r--r--libstdc++-v3/include/std/span20
-rw-r--r--libstdc++-v3/src/c++17/memory_resource.cc56
-rw-r--r--libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc105
-rw-r--r--libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc30
-rw-r--r--libstdc++-v3/testsuite/20_util/owner_equal/version.cc13
-rw-r--r--libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc87
-rw-r--r--libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc16
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc74
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc71
-rw-r--r--libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc6
-rw-r--r--libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc58
-rw-r--r--libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc52
-rw-r--r--libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc50
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc20
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc25
-rw-r--r--libstdc++-v3/testsuite/23_containers/span/deduction.cc3
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc52
-rw-r--r--libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc31
29 files changed, 1147 insertions, 26 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 4298304..090c5ce 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,175 @@
+2025-07-08 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/118681
+ * testsuite/20_util/unsynchronized_pool_resource/118681.cc: Fix
+ deallocate argument.
+
+2025-07-08 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/118681
+ * src/c++17/memory_resource.cc (choose_block_size): New
+ function.
+ (synchronized_pool_resource::do_allocate): Use choose_block_size
+ to determine appropriate block size.
+ (synchronized_pool_resource::do_deallocate): Likewise
+ (unsynchronized_pool_resource::do_allocate): Likewise.
+ (unsynchronized_pool_resource::do_deallocate): Likewise
+ * testsuite/20_util/synchronized_pool_resource/118681.cc: New
+ test.
+ * testsuite/20_util/unsynchronized_pool_resource/118681.cc: New
+ test.
+
+2025-07-08 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/debug/forward_list (_Safe_forward_list<>::_M_swap):
+ Adapt to _M_this() signature change.
+
+2025-07-08 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ PR libstdc++/119861
+ * include/std/format (formatter<_Rg, _CharT>::set_separator)
+ (formatter<_Rg, _CharT>::set_brackets): Constrain with
+ (format_kind<_Rg> == range_format::sequence).
+ * testsuite/std/format/ranges/pr119861_neg.cc: New test.
+
+2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ PR libstdc++/120914
+ * include/std/span (span): Update CTAD to enable
+ integral constants [P3029R1].
+ * include/std/mdspan (extents): ditto.
+ (mdspan): ditto.
+ * testsuite/23_containers/span/deduction.cc: Test deduction
+ guide.
+ * testsuite/23_containers/mdspan/extents/misc.cc: ditto.
+ * testsuite/23_containers/mdspan/mdspan.cc: ditto.
+
+2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * testsuite/23_containers/span/contiguous_range_neg.cc: Silence
+ warning about unused variable myspan.
+
+2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ PR libstdc++/107761
+ * include/bits/version.def (mdspan): Set to 202207 and remove
+ no_stdname.
+ * include/bits/version.h: Regenerate.
+ * testsuite/23_containers/mdspan/version.cc: Test presence
+ of feature test macro.
+
+2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ PR libstdc++/107761
+ * include/std/mdspan (mdspan): New class.
+ * src/c++23/std.cc.in (mdspan): Add.
+ * testsuite/23_containers/mdspan/class_mandate_neg.cc: New test.
+ * testsuite/23_containers/mdspan/mdspan.cc: New test.
+ * testsuite/23_containers/mdspan/layout_like.h: Add class
+ LayoutLike which models a user-defined layout.
+ * testsuite/23_containers/mdspan/out_of_bounds_neg.cc: New file.
+
+2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan (__mdspan::__size): New function.
+
+2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * testsuite/23_containers/mdspan/extents/custom_integer.cc:
+ Delete IntLike and include "int_like.h".
+ * testsuite/23_containers/mdspan/extents/int_like.h: Add
+ IntLike.
+
+2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan (extents): Check prerequisite of the ctor that
+ static_extent(i) == dynamic_extent || extent(i) == other.extent(i).
+ * testsuite/23_containers/mdspan/extents/class_mandates_neg.cc:
+ Test the implemented prerequisite.
+ * testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc: New file.
+
+2025-07-08 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan: Check prerequisites of
+ layout_*::operator() with _GLIBCXX_DEBUG_ASSERTs.
+ * testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc:
+ Add tests for prerequisites.
+
+2025-07-08 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * include/std/queue (formatter<queue<_Tp, _Container>, _CharT>)
+ (formatter<priority_queue<_Tp, _Container, _Compare>, _CharT>):
+ Add _GLIBCXX_RESOLVE_LIB_DEFECTS comments.
+
+2025-07-08 François Dumont <frs.dumont@gmail.com>
+
+ PR c++/116369
+ * config/abi/pre/gnu-versioned-namespace.ver: Use new const qualified symbols.
+ * config/abi/pre/gnu.ver: Add new const qualified symbols.
+ * include/debug/safe_base.h
+ (_Safe_iterator_base::_M_sequence): Declare as pointer-to-const.
+ (_Safe_iterator_base::_M_attach, _M_attach_single): New, take pointer-to-const
+ _Safe_sequence_base.
+ (_Safe_sequence_base::_M_detach_all, _M_detach_singular, _M_revalidate_singular)
+ (_M_swap, _M_get_mutex): New, const qualified.
+ (_Safe_sequence_base::_M_attach, _M_attach_single, _M_detach, _M_detach_single):
+ const qualify.
+ * include/debug/safe_container.h (_Safe_container<>::_M_cont): Add const qualifier.
+ (_Safe_container<>::_M_swap_base): New.
+ (_Safe_container(_Safe_container&&, const _Alloc&, std::false_type)):
+ Adapt to use latter.
+ (_Safe_container<>::operator=(_Safe_container&&)): Likewise.
+ (_Safe_container<>::_M_swap): Likewise and take parameter as const reference.
+ * include/debug/safe_unordered_base.h
+ (_Safe_local_iterator_base::_M_safe_container): New.
+ (_Safe_local_iterator_base::_Safe_local_iterator_base): Take
+ _Safe_unordered_container_base as pointer-to-const.
+ (_Safe_unordered_container_base::_M_attach, _M_attach_single): New, take
+ container as _Safe_unordered_container_base pointer-to-const.
+ (_Safe_unordered_container_base::_M_local_iterators, _M_const_local_iterators):
+ Add mutable.
+ (_Safe_unordered_container_base::_M_detach_all, _M_swap): New, const qualify.
+ (_Safe_unordered_container_base::_M_attach_local, _M_attach_local_single)
+ (_M_detach_local, _M_detach_local_single): Add const qualifier.
+ * include/debug/safe_unordered_container.h (_Safe_unordered_container::_M_self()): New.
+ * include/debug/safe_unordered_container.tcc
+ (_Safe_unordered_container::_M_invalidate_if, _M_invalidated_local_if): Use latter.
+ * include/debug/safe_iterator.h (_Safe_iterator<>::_M_attach, _M_attach_single):
+ Take _Safe_sequence_base as pointer-to-const.
+ (_Safe_iterator<>::_M_get_sequence): Add const_cast and comment about it.
+ * include/debug/safe_local_iterator.h (_Safe_local_iterator<>): Replace usages
+ of _M_sequence member by _M_safe_container().
+ (_Safe_local_iterator<>::_M_attach, _M_attach_single): Take
+ _Safe_unordered_container_base as pointer-to-const.
+ (_Safe_local_iterator<>::_M_get_sequence): Rename into...
+ (_Safe_local_iterator<>::_M_get_ucontainer): ...this. Add necessary const_cast and
+ comment to explain it.
+ (_Safe_local_iterator<>::_M_is_begin, _M_is_end): Adapt.
+ * include/debug/safe_local_iterator.tcc: Adapt.
+ * include/debug/safe_sequence.h
+ (_Safe_sequence<>::_M_invalidate_if, _M_transfer_from_if): Add const qualifier.
+ * include/debug/safe_sequence.tcc: Adapt.
+ * include/debug/deque (std::__debug::deque::erase): Adapt to use new const
+ qualified methods.
+ * include/debug/formatter.h: Adapt.
+ * include/debug/forward_list (_Safe_forward_list::_M_this): Add const
+ qualification and return pointer for consistency with 'this' keyword.
+ (_Safe_forward_list::_M_swap_aux): Rename into...
+ (_Safe_forward_list::_S_swap_aux): ...this and take sequence as const reference.
+ (forward_list<>::resize): Adapt to use const methods.
+ * include/debug/list (list<>::resize): Likewise.
+ * src/c++11/debug.cc: Adapt to const qualification.
+ * testsuite/util/testsuite_containers.h
+ (forward_members_unordered::forward_members_unordered): Add check on local_iterator
+ conversion to const_local_iterator.
+ (forward_members::forward_members): Add check on iterator conversion to
+ const_iterator.
+ * testsuite/23_containers/unordered_map/const_container.cc: New test case.
+ * testsuite/23_containers/unordered_multimap/const_container.cc: New test case.
+ * testsuite/23_containers/unordered_multiset/const_container.cc: New test case.
+ * testsuite/23_containers/unordered_set/const_container.cc: New test case.
+ * testsuite/23_containers/vector/debug/mutex_association.cc: Adapt.
+
2025-07-07 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/120949
diff --git a/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt b/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt
index ac11d5d..5d55287 100644
--- a/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt
+++ b/libstdc++-v3/config/abi/post/x86_64-linux-gnu/x32/baseline_symbols.txt
@@ -2124,6 +2124,10 @@ FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policy
FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEC2EOS5_@@GLIBCXX_3.4.28
FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEC2Ev@@GLIBCXX_3.4.27
FUNC:_ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEaSEOS5_@@GLIBCXX_3.4.26
+FUNC:_ZNSt12__sso_stringC1Ev@@GLIBCXX_3.4.34
+FUNC:_ZNSt12__sso_stringC2Ev@@GLIBCXX_3.4.34
+FUNC:_ZNSt12__sso_stringD1Ev@@GLIBCXX_3.4.34
+FUNC:_ZNSt12__sso_stringD2Ev@@GLIBCXX_3.4.34
FUNC:_ZNSt12bad_weak_ptrD0Ev@@GLIBCXX_3.4.15
FUNC:_ZNSt12bad_weak_ptrD1Ev@@GLIBCXX_3.4.15
FUNC:_ZNSt12bad_weak_ptrD2Ev@@GLIBCXX_3.4.15
@@ -3221,6 +3225,8 @@ FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC1EPcRKS
FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC2EPcOS3_@@GLIBCXX_3.4.23
FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_Alloc_hiderC2EPcRKS3_@@GLIBCXX_3.4.21
FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructEjc@@GLIBCXX_3.4.21
+FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructILb0EEEvPKcj@@GLIBCXX_3.4.34
+FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructILb1EEEvPKcj@@GLIBCXX_3.4.34
FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPKcS4_EEEEvT_SB_St20forward_iterator_tag@@GLIBCXX_3.4.21
FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPcS4_EEEEvT_SA_St20forward_iterator_tag@@GLIBCXX_3.4.21
FUNC:_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag@@GLIBCXX_3.4.21
@@ -3374,6 +3380,8 @@ FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC1EPwRKS
FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC2EPwOS3_@@GLIBCXX_3.4.23
FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_Alloc_hiderC2EPwRKS3_@@GLIBCXX_3.4.21
FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructEjw@@GLIBCXX_3.4.21
+FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructILb0EEEvPKwj@@GLIBCXX_3.4.34
+FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructILb1EEEvPKwj@@GLIBCXX_3.4.34
FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPKwS4_EEEEvT_SB_St20forward_iterator_tag@@GLIBCXX_3.4.21
FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIN9__gnu_cxx17__normal_iteratorIPwS4_EEEEvT_SA_St20forward_iterator_tag@@GLIBCXX_3.4.21
FUNC:_ZNSt7__cxx1112basic_stringIwSt11char_traitsIwESaIwEE12_M_constructIPKwEEvT_S8_St20forward_iterator_tag@@GLIBCXX_3.4.21
@@ -3941,6 +3949,8 @@ FUNC:_ZNSt8__detail15_List_node_base11_M_transferEPS0_S1_@@GLIBCXX_3.4.15
FUNC:_ZNSt8__detail15_List_node_base4swapERS0_S1_@@GLIBCXX_3.4.15
FUNC:_ZNSt8__detail15_List_node_base7_M_hookEPS0_@@GLIBCXX_3.4.15
FUNC:_ZNSt8__detail15_List_node_base9_M_unhookEv@@GLIBCXX_3.4.15
+FUNC:_ZNSt8__format25__locale_encoding_to_utf8ERKSt6localeSt17basic_string_viewIcSt11char_traitsIcEEPv@@GLIBCXX_3.4.34
+FUNC:_ZNSt8__format26__with_encoding_conversionERKSt6locale@@GLIBCXX_3.4.34
FUNC:_ZNSt8bad_castD0Ev@@GLIBCXX_3.4
FUNC:_ZNSt8bad_castD1Ev@@GLIBCXX_3.4
FUNC:_ZNSt8bad_castD2Ev@@GLIBCXX_3.4
@@ -4617,6 +4627,7 @@ OBJECT:0:GLIBCXX_3.4.30
OBJECT:0:GLIBCXX_3.4.31
OBJECT:0:GLIBCXX_3.4.32
OBJECT:0:GLIBCXX_3.4.33
+OBJECT:0:GLIBCXX_3.4.34
OBJECT:0:GLIBCXX_3.4.4
OBJECT:0:GLIBCXX_3.4.5
OBJECT:0:GLIBCXX_3.4.6
diff --git a/libstdc++-v3/include/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h
index 73a6d14..30c5b12 100644
--- a/libstdc++-v3/include/bits/max_size_type.h
+++ b/libstdc++-v3/include/bits/max_size_type.h
@@ -38,6 +38,7 @@
#include <ext/numeric_traits.h>
#include <bit> // __bit_width
#include <numbers>
+#include <limits> // __glibcxx_integral_traps
// This header implements unsigned and signed integer-class types (as per
// [iterator.concept.winc]) that are one bit wider than the widest supported
@@ -775,10 +776,27 @@ namespace ranges
static constexpr bool is_signed = false;
static constexpr bool is_integer = true;
static constexpr bool is_exact = true;
+ static constexpr bool is_bounded = true;
+ static constexpr bool is_modulo = true;
+ static constexpr bool traps = __glibcxx_integral_traps;
+ static constexpr int radix = 2;
static constexpr int digits
= __gnu_cxx::__int_traits<_Sp::__rep>::__digits + 1;
static constexpr int digits10
= static_cast<int>(digits * numbers::ln2 / numbers::ln10);
+ static constexpr int max_digits10 = 0;
+ static constexpr int min_exponent = 0;
+ static constexpr int min_exponent10 = 0;
+ static constexpr int max_exponent = 0;
+ static constexpr int max_exponent10 = 0;
+ static constexpr bool is_iec559 = false;
+ static constexpr bool has_infinity = false;
+ static constexpr bool has_quiet_NaN = false;
+ static constexpr bool has_signaling_NaN = false;
+ static constexpr bool has_denorm_loss = false;
+ static constexpr bool tinyness_before = false;
+ static constexpr float_denorm_style has_denorm = denorm_absent;
+ static constexpr float_round_style round_style = round_toward_zero;
static constexpr _Sp
min() noexcept
@@ -791,6 +809,30 @@ namespace ranges
static constexpr _Sp
lowest() noexcept
{ return min(); }
+
+ static constexpr _Sp
+ denorm_min() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ epsilon() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ round_error() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ infinity() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ quiet_NaN() noexcept
+ { return 0; }
+
+ static constexpr _Sp
+ signaling_NaN() noexcept
+ { return 0; }
};
template<>
@@ -802,9 +844,26 @@ namespace ranges
static constexpr bool is_signed = true;
static constexpr bool is_integer = true;
static constexpr bool is_exact = true;
+ static constexpr bool is_bounded = true;
+ static constexpr bool is_modulo = false;
+ static constexpr bool traps = __glibcxx_integral_traps;
+ static constexpr int radix = 2;
static constexpr int digits = numeric_limits<_Sp>::digits - 1;
static constexpr int digits10
= static_cast<int>(digits * numbers::ln2 / numbers::ln10);
+ static constexpr int max_digits10 = 0;
+ static constexpr int min_exponent = 0;
+ static constexpr int min_exponent10 = 0;
+ static constexpr int max_exponent = 0;
+ static constexpr int max_exponent10 = 0;
+ static constexpr bool is_iec559 = false;
+ static constexpr bool has_infinity = false;
+ static constexpr bool has_quiet_NaN = false;
+ static constexpr bool has_signaling_NaN = false;
+ static constexpr bool has_denorm_loss = false;
+ static constexpr bool tinyness_before = false;
+ static constexpr float_denorm_style has_denorm = denorm_absent;
+ static constexpr float_round_style round_style = round_toward_zero;
static constexpr _Dp
min() noexcept
@@ -817,6 +876,30 @@ namespace ranges
static constexpr _Dp
lowest() noexcept
{ return min(); }
+
+ static constexpr _Dp
+ denorm_min() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ epsilon() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ round_error() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ infinity() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ quiet_NaN() noexcept
+ { return 0; }
+
+ static constexpr _Dp
+ signaling_NaN() noexcept
+ { return 0; }
};
template<>
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index a196a0f..f2b4601 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -909,6 +909,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
{ };
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+
+ /**
+ * @brief Provides ownership-based hashing.
+ * @headerfile memory
+ * @since C++26
+ */
+ struct owner_hash
+ {
+ template<typename _Tp>
+ size_t
+ operator()(const shared_ptr<_Tp>& __s) const noexcept
+ { return __s.owner_hash(); }
+
+ template<typename _Tp>
+ size_t
+ operator()(const weak_ptr<_Tp>& __s) const noexcept
+ { return __s.owner_hash(); }
+
+ using is_transparent = void;
+ };
+
+ /**
+ * @brief Provides ownership-based mixed equality comparisons of
+ * shared and weak pointers.
+ * @headerfile memory
+ * @since C++26
+ */
+ struct owner_equal
+ {
+ template<typename _Tp1, typename _Tp2>
+ bool
+ operator()(const shared_ptr<_Tp1>& __lhs,
+ const shared_ptr<_Tp2>& __rhs) const noexcept
+ { return __lhs.owner_equal(__rhs); }
+
+ template<typename _Tp1, typename _Tp2>
+ bool
+ operator()(const shared_ptr<_Tp1>& __lhs,
+ const weak_ptr<_Tp2>& __rhs) const noexcept
+ { return __lhs.owner_equal(__rhs); }
+
+ template<typename _Tp1, typename _Tp2>
+ bool
+ operator()(const weak_ptr<_Tp1>& __lhs,
+ const shared_ptr<_Tp2>& __rhs) const noexcept
+ { return __lhs.owner_equal(__rhs); }
+
+ template<typename _Tp1, typename _Tp2>
+ bool
+ operator()(const weak_ptr<_Tp1>& __lhs,
+ const weak_ptr<_Tp2>& __rhs) const noexcept
+ { return __lhs.owner_equal(__rhs); }
+
+ using is_transparent = void;
+ };
+#endif
+
/**
* @brief Base class allowing use of the member function `shared_from_this`.
* @headerfile memory
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index b4be1b4..fb868e7 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -1122,6 +1122,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_less(const __weak_count<_Lp>& __rhs) const noexcept
{ return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+ size_t
+ _M_owner_hash() const noexcept
+ { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); }
+#endif
+
// Friend function injected into enclosing namespace and found by ADL
friend inline bool
operator==(const __shared_count& __a, const __shared_count& __b) noexcept
@@ -1225,6 +1231,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_less(const __shared_count<_Lp>& __rhs) const noexcept
{ return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); }
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+ size_t
+ _M_owner_hash() const noexcept
+ { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); }
+#endif
+
// Friend function injected into enclosing namespace and found by ADL
friend inline bool
operator==(const __weak_count& __a, const __weak_count& __b) noexcept
@@ -1715,6 +1727,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return _M_refcount._M_less(__rhs._M_refcount); }
/// @}
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+ size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); }
+
+ template<typename _Tp1>
+ bool
+ owner_equal(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept
+ { return _M_refcount == __rhs._M_refcount; }
+
+ template<typename _Tp1>
+ bool
+ owner_equal(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept
+ { return _M_refcount == __rhs._M_refcount; }
+#endif
+
protected:
// This constructor is non-standard, it is used by allocate_shared.
template<typename _Alloc, typename... _Args>
@@ -2098,6 +2124,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept
{ return _M_refcount._M_less(__rhs._M_refcount); }
+#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26
+ size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); }
+
+ template<typename _Tp1>
+ bool
+ owner_equal(const __shared_ptr<_Tp1, _Lp> & __rhs) const noexcept
+ { return _M_refcount == __rhs._M_refcount; }
+
+ template<typename _Tp1>
+ bool
+ owner_equal(const __weak_ptr<_Tp1, _Lp> & __rhs) const noexcept
+ { return _M_refcount == __rhs._M_refcount; }
+#endif
+
void
reset() noexcept
{ __weak_ptr().swap(*this); }
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index f1015ab..31385b5 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2007,6 +2007,15 @@ ftms = {
};
ftms = {
+ name = smart_ptr_owner_equality;
+ values = {
+ v = 202306;
+ cxxmin = 26;
+ hosted = yes;
+ };
+};
+
+ftms = {
name = sstream_from_string_view;
values = {
v = 202306;
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 80f6586..aa53f29 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2249,6 +2249,16 @@
#endif /* !defined(__cpp_lib_polymorphic) && defined(__glibcxx_want_polymorphic) */
#undef __glibcxx_want_polymorphic
+#if !defined(__cpp_lib_smart_ptr_owner_equality)
+# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
+# define __glibcxx_smart_ptr_owner_equality 202306L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_smart_ptr_owner_equality)
+# define __cpp_lib_smart_ptr_owner_equality 202306L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_smart_ptr_owner_equality) && defined(__glibcxx_want_smart_ptr_owner_equality) */
+#undef __glibcxx_want_smart_ptr_owner_equality
+
#if !defined(__cpp_lib_sstream_from_string_view)
# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
# define __glibcxx_sstream_from_string_view 202306L
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index 4e1511d..9da7dda 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -144,13 +144,13 @@ namespace __gnu_debug
//std::swap(_M_this()->_M_version, __other._M_version);
_Safe_iterator_base* __this_its = _M_this()->_M_iterators;
_S_swap_aux(__other, __other._M_iterators,
- _M_this(), _M_this()->_M_iterators);
+ *_M_this(), _M_this()->_M_iterators);
_Safe_iterator_base* __this_const_its = _M_this()->_M_const_iterators;
_S_swap_aux(__other, __other._M_const_iterators,
- _M_this(), _M_this()->_M_const_iterators);
- _S_swap_aux(_M_this(), __this_its,
+ *_M_this(), _M_this()->_M_const_iterators);
+ _S_swap_aux(*_M_this(), __this_its,
__other, __other._M_iterators);
- _S_swap_aux(_M_this(), __this_const_its,
+ _S_swap_aux(*_M_this(), __this_const_its,
__other, __other._M_const_iterators);
}
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 5749aa1..d584b81 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -6030,13 +6030,13 @@ namespace __format
constexpr void
set_separator(basic_string_view<_CharT> __sep) noexcept
- requires (!_S_range_format_is_string)
+ requires (format_kind<_Rg> == range_format::sequence)
{ _M_under.set_separator(__sep); }
constexpr void
set_brackets(basic_string_view<_CharT> __open,
basic_string_view<_CharT> __close) noexcept
- requires (!_S_range_format_is_string)
+ requires (format_kind<_Rg> == range_format::sequence)
{ _M_under.set_brackets(__open, __close); }
// We deviate from standard, that declares this as template accepting
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 5a42aea..5d16de5 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -406,10 +406,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _IndexType, size_t... _Counts>
auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
-> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
-
- template<typename _Tp>
- consteval size_t
- __dynamic_extent() { return dynamic_extent; }
}
template<typename _IndexType, size_t _Rank>
@@ -419,7 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename... _Integrals>
requires (is_convertible_v<_Integrals, size_t> && ...)
explicit extents(_Integrals...) ->
- extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>;
+ extents<size_t, __detail::__maybe_static_ext<_Integrals>...>;
struct layout_left
{
@@ -1316,7 +1312,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& (sizeof...(_Integrals) > 0)
explicit mdspan(_ElementType*, _Integrals...)
-> mdspan<_ElementType,
- extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>>;
+ extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>;
template<typename _ElementType, typename _OIndexType, size_t _Nm>
mdspan(_ElementType*, span<_OIndexType, _Nm>)
diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory
index 1da03b3..763a57e 100644
--- a/libstdc++-v3/include/std/memory
+++ b/libstdc++-v3/include/std/memory
@@ -121,6 +121,7 @@
#define __glibcxx_want_smart_ptr_for_overwrite
#define __glibcxx_want_to_address
#define __glibcxx_want_transparent_operators
+#define __glibcxx_want_smart_ptr_owner_equality
#include <bits/version.h>
#if __cplusplus >= 201103L && __cplusplus <= 202002L && _GLIBCXX_HOSTED
diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index 49ab910..5629a71 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -476,6 +476,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
};
// deduction guides
+ namespace __detail
+ {
+ template<typename _Tp>
+ concept __integral_constant_like = is_integral_v<decltype(_Tp::value)>
+ && !is_same_v<bool, remove_const_t<decltype(_Tp::value)>>
+ && convertible_to<_Tp, decltype(_Tp::value)>
+ && equality_comparable_with<_Tp, decltype(_Tp::value)>
+ && bool_constant<_Tp() == _Tp::value>::value
+ && bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value>
+ ::value;
+
+ template<typename _Tp>
+ constexpr size_t __maybe_static_ext = dynamic_extent;
+
+ template<__integral_constant_like _Tp>
+ constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value};
+ }
template<typename _Type, size_t _ArrayExtent>
span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
@@ -489,7 +506,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<contiguous_iterator _Iter, typename _End>
span(_Iter, _End)
- -> span<remove_reference_t<iter_reference_t<_Iter>>>;
+ -> span<remove_reference_t<iter_reference_t<_Iter>>,
+ __detail::__maybe_static_ext<_End>>;
template<ranges::contiguous_range _Range>
span(_Range &&)
diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc
index fac4c78..c61569f 100644
--- a/libstdc++-v3/src/c++17/memory_resource.cc
+++ b/libstdc++-v3/src/c++17/memory_resource.cc
@@ -182,8 +182,8 @@ namespace pmr
// versions will not use this symbol.
monotonic_buffer_resource::~monotonic_buffer_resource() { release(); }
- namespace {
-
+namespace
+{
// aligned_size<N> stores the size and alignment of a memory allocation.
// The size must be a multiple of N, leaving the low log2(N) bits free
// to store the base-2 logarithm of the alignment.
@@ -221,7 +221,7 @@ namespace pmr
return (n + alignment - 1) & ~(alignment - 1);
}
- } // namespace
+} // namespace
// Memory allocated by the upstream resource is managed in a linked list
// of _Chunk objects. A _Chunk object recording the size and alignment of
@@ -307,8 +307,8 @@ namespace pmr
// Helper types for synchronized_pool_resource & unsynchronized_pool_resource
- namespace {
-
+namespace
+{
// Simple bitset with runtime size.
// Tracks which blocks in a pool chunk are used/unused.
struct bitset
@@ -636,7 +636,7 @@ namespace pmr
static_assert(sizeof(big_block) == (2 * sizeof(void*)));
- } // namespace
+} // namespace
// A pool that serves blocks of a particular size.
// Each pool manages a number of chunks.
@@ -868,7 +868,16 @@ namespace pmr
using big_block::big_block;
};
- namespace {
+namespace
+{
+ // N.B. it is important that we don't skip any power of two sizes if there
+ // is a non-power of two size between them, e.g. must not have pool sizes
+ // of 24 and 40 without having a pool size of 32. Otherwise an allocation
+ // of 32 bytes with alignment 16 would choose the 40-byte pool which is not
+ // correctly aligned for 16-byte alignment. It would be OK (but suboptimal)
+ // to have no pool of size 32 if we have pool sizes of 16 and 64 and no
+ // non-power of two sizes between those, because the example of (32, 16)
+ // would choose the 64-byte pool, which would be correctly aligned.
constexpr size_t pool_sizes[] = {
8, 16, 24,
@@ -983,7 +992,7 @@ namespace pmr
using exclusive_lock = lock_guard<shared_mutex>;
#endif
- } // namespace
+} // namespace
__pool_resource::
__pool_resource(const pool_options& opts, memory_resource* upstream)
@@ -1075,12 +1084,33 @@ namespace pmr
return p;
}
+ // Determine the appropriate allocation size, rounding up to a multiple
+ // of the alignment if needed.
+ static inline size_t
+ choose_block_size(size_t bytes, size_t alignment)
+ {
+ if (bytes == 0) [[unlikely]]
+ return alignment;
+
+ // Use bit_ceil in case alignment is invalid (i.e. not a power of two).
+ size_t mask = std::__bit_ceil(alignment) - 1;
+ // Round up to a multiple of alignment.
+ size_t block_size = (bytes + mask) & ~mask;
+
+ if (block_size >= bytes) [[likely]]
+ return block_size;
+
+ // Wrapped around to zero, bytes must have been impossibly large.
+ return numeric_limits<size_t>::max();
+ }
+
+
#ifdef _GLIBCXX_HAS_GTHREADS
// synchronized_pool_resource members.
/* Notes on implementation and thread safety:
*
- * Each synchronized_pool_resource manages an linked list of N+1 _TPools
+ * Each synchronized_pool_resource manages a linked list of N+1 _TPools
* objects, where N is the number of threads using the pool resource.
* Each _TPools object has its own set of pools, with their own chunks.
* The first element of the list, _M_tpools[0], can be used by any thread.
@@ -1247,7 +1277,7 @@ namespace pmr
synchronized_pool_resource::
do_allocate(size_t bytes, size_t alignment)
{
- const auto block_size = std::max(bytes, alignment);
+ const auto block_size = choose_block_size(bytes, alignment);
const pool_options opts = _M_impl._M_opts;
if (block_size <= opts.largest_required_pool_block)
{
@@ -1294,7 +1324,7 @@ namespace pmr
synchronized_pool_resource::
do_deallocate(void* p, size_t bytes, size_t alignment)
{
- size_t block_size = std::max(bytes, alignment);
+ size_t block_size = choose_block_size(bytes, alignment);
if (block_size <= _M_impl._M_opts.largest_required_pool_block)
{
const ptrdiff_t index = pool_index(block_size, _M_impl._M_npools);
@@ -1453,7 +1483,7 @@ namespace pmr
void*
unsynchronized_pool_resource::do_allocate(size_t bytes, size_t alignment)
{
- const auto block_size = std::max(bytes, alignment);
+ const auto block_size = choose_block_size(bytes, alignment);
if (block_size <= _M_impl._M_opts.largest_required_pool_block)
{
// Recreate pools if release() has been called:
@@ -1470,7 +1500,7 @@ namespace pmr
unsynchronized_pool_resource::
do_deallocate(void* p, size_t bytes, size_t alignment)
{
- size_t block_size = std::max(bytes, alignment);
+ size_t block_size = choose_block_size(bytes, alignment);
if (block_size <= _M_impl._M_opts.largest_required_pool_block)
{
if (auto pool = _M_find_pool(block_size))
diff --git a/libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc b/libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc
new file mode 100644
index 0000000..311ddf2
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/owner_equal/cmp.cc
@@ -0,0 +1,105 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 20.3.2.6 Struct owner_equal [util.smartptr.owner.equal]
+
+#include <memory>
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+struct A { };
+
+struct B { A a[2]; };
+
+int
+test01()
+{
+ // test empty shared_ptr owners compare equivalent
+ std::owner_equal eq;
+ std::shared_ptr<A> p1;
+ std::shared_ptr<A> p2;
+ VERIFY( eq(p1, p2) && eq(p2, p1) );
+ std::weak_ptr<A> p3;
+ VERIFY( eq(p1, p3) && eq(p3, p1) );
+ VERIFY( eq(p1, p3) && eq(p3, p1) );
+ return 0;
+}
+
+
+// Construction from pointer
+int
+test02()
+{
+ std::owner_equal eq;
+
+ std::shared_ptr<A> empty;
+
+ std::shared_ptr<A> a1(new A);
+ VERIFY( !eq(empty, a1) && !eq(a1, empty) );
+
+ std::shared_ptr<A> a2(new A);
+ VERIFY( !eq(a1, a2) && !eq(a2, a1) );
+
+ std::weak_ptr<A> w1(a1);
+ VERIFY( eq(a1, w1) && eq(w1, a1) );
+
+ std::weak_ptr<A> w2(a2);
+ VERIFY( !eq(w1, w2) && !eq(w2, w1) );
+
+ a1.reset();
+ VERIFY( eq(empty, a1) && eq(a1, empty) );
+ VERIFY( !eq(a1, w1) && !eq(w1, a1) );
+
+ a2.reset();
+ VERIFY( eq(a2, a1) && eq(a1, a2) );
+
+ return 0;
+}
+
+// aliasing
+int
+test03()
+{
+ std::owner_equal eq;
+
+ std::shared_ptr<B> b(new B);
+ std::shared_ptr<A> a0(b, &b->a[0]);
+ std::shared_ptr<A> a1(b, &b->a[1]);
+ // values are different but owners are equivalent:
+ VERIFY( a0 < a1 && eq(a0, a1) && eq(b, a0) && eq(b, a1) );
+
+ std::weak_ptr<A> w0(a0);
+ std::weak_ptr<A> w1(a1);
+ VERIFY( eq(w0, w1) && eq(w1, w0) );
+ VERIFY( eq(a0, w1) && eq(w1, a0) );
+ VERIFY( eq(w0, a1) && eq(a1, w0) );
+
+ return 0;
+}
+
+// as binary predicate
+int
+test04()
+{
+ std::owner_equal eq;
+
+ std::shared_ptr<B> b(new B);
+ std::shared_ptr<A> a0(b, &b->a[0]);
+ std::shared_ptr<A> a1(b, &b->a[1]);
+ std::shared_ptr<A> c(new A);
+ std::weak_ptr<A> a[3]{a0, a1, c};
+ std::weak_ptr<A>* p = std::unique(a, a+3, eq);
+ VERIFY( p == &a[2] );
+
+ return 0;
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc b/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc
new file mode 100644
index 0000000..fb479f6
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/owner_equal/noexcept.cc
@@ -0,0 +1,30 @@
+// { dg-do compile { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 20.3.2.6 Struct owner_equal [util.smartptr.owner.equal]
+
+#include <memory>
+
+#ifndef __cpp_lib_smart_ptr_owner_equality
+# error "Feature-test macro for smart ptr owner equality missing in <memory>"
+#elif __cpp_lib_smart_ptr_owner_equality != 202306L
+# error "Feature-test macro for smart ptr owner equality has wrong value in <memory>"
+#endif
+
+const std::owner_equal eq;
+const std::shared_ptr<int> si;
+const std::weak_ptr<int> wi;
+static_assert( noexcept(!eq(si, si)) );
+static_assert( noexcept(!eq(si, wi)) );
+static_assert( noexcept(!eq(wi, si)) );
+static_assert( noexcept(!eq(wi, wi)) );
+static_assert( noexcept(!eq(si, wi)) );
+static_assert( noexcept(!eq(wi, si)) );
+const std::shared_ptr<long> sl;
+const std::weak_ptr<char> wc;
+static_assert( noexcept(!eq(si, si)) );
+static_assert( noexcept(!eq(si, sl)) );
+static_assert( noexcept(!eq(sl, si)) );
+static_assert( noexcept(!eq(si, wc)) );
+static_assert( noexcept(!eq(wc, si)) );
+static_assert( noexcept(!eq(wc, wi)) );
diff --git a/libstdc++-v3/testsuite/20_util/owner_equal/version.cc b/libstdc++-v3/testsuite/20_util/owner_equal/version.cc
new file mode 100644
index 0000000..db29154
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/owner_equal/version.cc
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 17.3.2 Header <version> synopsis [version.syn]
+
+#include <version>
+
+#ifndef __cpp_lib_smart_ptr_owner_equality
+# error "Feature-test macro for smart ptr owner equality missing in <version>"
+#elif __cpp_lib_smart_ptr_owner_equality != 202306L
+# error "Feature-test macro for smart ptr owner equality has wrong value in <version>"
+#endif
+
diff --git a/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc b/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc
new file mode 100644
index 0000000..c03a926
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/owner_hash/cmp.cc
@@ -0,0 +1,87 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 20.3.2.5 Struct owner_hash [util.smartptr.owner.hash]
+
+#include <memory>
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+struct A { };
+
+struct B { A a[2]; };
+
+int
+test01()
+{
+ // test empty shared_ptr hashes compare equivalent
+ std::owner_hash oh;
+ std::shared_ptr<A> p1;
+ std::shared_ptr<A> p2;
+ VERIFY( oh(p1) == oh(p2) );
+ std::weak_ptr<A> p3;
+ VERIFY( oh(p1) == oh(p3) );
+ VERIFY( oh(p1) == oh(p3) );
+ return 0;
+}
+
+
+// Construction from pointer
+int
+test02()
+{
+ std::owner_hash oh;
+
+ std::shared_ptr<A> empty;
+
+ std::shared_ptr<A> a1(new A);
+ VERIFY( oh(empty) != oh(a1) );
+
+ std::shared_ptr<A> a2(new A);
+ VERIFY( oh(a1) != oh(a2) );
+
+ std::weak_ptr<A> w1(a1);
+ VERIFY( oh(a1) == oh(w1) );
+
+ std::weak_ptr<A> w2(a2);
+ VERIFY( oh(w1) != oh(w2) );
+
+ a1.reset();
+ VERIFY( oh(empty) == oh(a1) );
+ VERIFY( oh(a1) != oh(w1) );
+
+ a2.reset();
+ VERIFY( oh(a2) == oh(a1) );
+
+ return 0;
+}
+
+// aliasing
+int
+test03()
+{
+ std::owner_hash oh;
+
+ std::shared_ptr<B> b(new B);
+ std::shared_ptr<A> a0(b, &b->a[0]);
+ std::shared_ptr<A> a1(b, &b->a[1]);
+ // values are different but owners are ohuivalent:
+ VERIFY( a0 < a1 && oh(a0) == oh(a1) && oh(b) == oh(a0) && oh(b) == oh(a1) );
+
+ std::weak_ptr<A> w0(a0);
+ std::weak_ptr<A> w1(a1);
+ VERIFY( oh(w0) == oh(w1) );
+ VERIFY( oh(a0) == oh(w1) );
+ VERIFY( oh(w0) == oh(a1) );
+
+ return 0;
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc b/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc
new file mode 100644
index 0000000..12b2f2f
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/owner_hash/noexcept.cc
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 20.3.2.5 Struct owner_hash [util.smartptr.owner.hash]
+
+#include <memory>
+
+const std::owner_hash oh;
+const std::shared_ptr<int> si;
+const std::weak_ptr<int> wi;
+static_assert( noexcept(!oh(si)) );
+static_assert( noexcept(!oh(wi)) );
+const std::shared_ptr<long> sl;
+const std::weak_ptr<char> wc;
+static_assert( noexcept(!oh(sl)) );
+static_assert( noexcept(!oh(wc)) );
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc
new file mode 100644
index 0000000..7ec8691
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_equal.cc
@@ -0,0 +1,74 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 20.3.2.2.6 shared_ptr observers [util.smartptr.shared.obs]
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+ int i;
+ virtual ~A() { }
+};
+
+struct B : A
+{
+};
+
+void
+test01()
+{
+ // test empty shared_ptr owners compare equivalent
+ std::shared_ptr<A> p1;
+ std::shared_ptr<B> p2;
+ VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) );
+}
+
+
+// Construction from pointer
+void
+test02()
+{
+ std::shared_ptr<A> a0;
+
+ std::shared_ptr<A> a1(new A);
+ VERIFY( !a1.owner_equal(a0) && !a0.owner_equal(a1) );
+
+ std::shared_ptr<B> b1(new B);
+ VERIFY( !a1.owner_equal(b1) && !b1.owner_equal(a1) );
+
+ std::shared_ptr<A> a2(a1);
+ VERIFY( a1.owner_equal(a2) && a2.owner_equal(a1) );
+ a2 = b1;
+ VERIFY( b1.owner_equal(a2) && a2.owner_equal(b1) );
+
+ std::weak_ptr<A> w1(a1);
+ VERIFY( a1.owner_equal(w1) && w1.owner_equal(a1) );
+ std::weak_ptr<A> w2(a2);
+ VERIFY( b1.owner_equal(w2) && w2.owner_equal(b1) );
+
+ static_assert( noexcept(a1.owner_equal(a0)) );
+ static_assert( noexcept(a1.owner_equal(b1)) );
+ static_assert( noexcept(b1.owner_equal(a1)) );
+ static_assert( noexcept(a1.owner_equal(w1)) );
+ static_assert( noexcept(b1.owner_equal(w1)) );
+}
+
+// Aliasing
+void
+test03()
+{
+ std::shared_ptr<A> p1(new A());
+ std::shared_ptr<int> p2(p1, &p1->i);
+ VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc
new file mode 100644
index 0000000..8e6c02c
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/observers/owner_hash.cc
@@ -0,0 +1,71 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 20.3.2.2.6 shared_ptr observers [util.smartptr.shared.obs]
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+ int i;
+ virtual ~A() { }
+};
+
+struct B : A
+{
+};
+
+void
+test01()
+{
+ // test empty shared_ptr hashes compare equivalent
+ std::shared_ptr<A> p1;
+ std::shared_ptr<B> p2;
+ VERIFY( p1.owner_hash() == p2.owner_hash() );
+}
+
+
+// Construction from pointer
+void
+test02()
+{
+ std::shared_ptr<A> a0;
+
+ std::shared_ptr<A> a1(new A);
+ VERIFY( a1.owner_hash() != a0.owner_hash() );
+
+ std::shared_ptr<B> b1(new B);
+ VERIFY( a1.owner_hash() != b1.owner_hash() );
+
+ std::shared_ptr<A> a2(a1);
+ VERIFY( a1.owner_hash() == a2.owner_hash() );
+ a2 = b1;
+ VERIFY( b1.owner_hash() == a2.owner_hash() );
+
+ std::weak_ptr<A> w1(a1);
+ VERIFY( a1.owner_hash() == w1.owner_hash() );
+ std::weak_ptr<A> w2(a2);
+ VERIFY( b1.owner_hash() == w2.owner_hash() );
+
+ static_assert( noexcept(a1.owner_hash()) );
+ static_assert( noexcept(b1.owner_hash()) );
+}
+
+// Aliasing
+void
+test03()
+{
+ std::shared_ptr<A> p1(new A());
+ std::shared_ptr<int> p2(p1, &p1->i);
+ VERIFY( p1.owner_hash() == p2.owner_hash() );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc
new file mode 100644
index 0000000..facbf00
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc
@@ -0,0 +1,6 @@
+// { dg-do run { target c++17 } }
+// { dg-require-gthreads "" }
+// Bug 118681 - unsynchronized_pool_resource may fail to respect alignment
+
+#define RESOURCE std::pmr::synchronized_pool_resource
+#include "../unsynchronized_pool_resource/118681.cc"
diff --git a/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc
new file mode 100644
index 0000000..9935f79
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/unsynchronized_pool_resource/118681.cc
@@ -0,0 +1,58 @@
+// { dg-do run { target c++17 } }
+// Bug 118681 - unsynchronized_pool_resource may fail to respect alignment
+
+#include <memory_resource>
+#include <cstdio>
+#include <testsuite_hooks.h>
+
+#ifndef RESOURCE
+# define RESOURCE std::pmr::unsynchronized_pool_resource
+#endif
+
+bool any_misaligned = false;
+
+bool
+is_aligned(void* p, [[maybe_unused]] std::size_t size, std::size_t alignment)
+{
+ const bool misaligned = reinterpret_cast<std::uintptr_t>(p) % alignment;
+#ifdef DEBUG
+ std::printf("allocate(%2zu, %2zu): %p is aligned %scorrectly\n",
+ size, alignment, p, misaligned ? "in" : "");
+ any_misaligned |= misaligned;
+ return true;
+#endif
+ return ! misaligned;
+}
+
+void
+test_alignment(std::pmr::memory_resource& res, bool dealloc)
+{
+ for (std::size_t alignment : { 8, 16, 32, 64 })
+ {
+ for (std::size_t size : { 9, 12, 24, 40, 48, 56, 72 })
+ {
+ void* p1 = res.allocate(size, alignment);
+ void* p2 = res.allocate(size, alignment);
+
+ VERIFY( is_aligned(p1, size, alignment) );
+ VERIFY( is_aligned(p2, size, alignment) );
+
+ if (dealloc)
+ {
+ res.deallocate(p1, size, alignment);
+ res.deallocate(p2, size, alignment);
+ }
+ }
+ }
+}
+
+int main()
+{
+ RESOURCE res;
+ test_alignment(res, true);
+ res.release();
+ test_alignment(res, false);
+ res.release();
+
+ VERIFY( ! any_misaligned );
+}
diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc
new file mode 100644
index 0000000..0217a6e
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_equal.cc
@@ -0,0 +1,52 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 20.3.2.3.6 weak_ptr observers [util.smartptr.weak.obs]
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+struct B { };
+
+void
+test01()
+{
+ // test empty weak_ptr owners compare equivalent
+ std::weak_ptr<A> p1;
+ std::weak_ptr<B> p2;
+ VERIFY( p1.owner_equal(p2) && p2.owner_equal(p1) );
+
+ std::shared_ptr<B> p3;
+ VERIFY( p1.owner_equal(p3) && p3.owner_equal(p1) );
+
+ static_assert( noexcept(p1.owner_equal(p1)) );
+ static_assert( noexcept(p1.owner_equal(p2)) );
+ static_assert( noexcept(p1.owner_equal(p3)) );
+ static_assert( noexcept(p2.owner_equal(p1)) );
+}
+
+
+void
+test02()
+{
+ std::shared_ptr<A> a0;
+ std::weak_ptr<A> w0(a0);
+
+ std::shared_ptr<A> a1(new A);
+ std::weak_ptr<A> w1(a1);
+ VERIFY( a1.owner_equal(w1) && w1.owner_equal(a1) );
+ VERIFY( !w1.owner_equal(w0) && !w0.owner_equal(w1) );
+ VERIFY( !w1.owner_equal(a0) && !a0.owner_equal(w1) );
+
+ std::shared_ptr<B> b1(new B);
+ VERIFY( !w1.owner_equal(b1) && !b1.owner_equal(w1) );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc
new file mode 100644
index 0000000..148a93b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/weak_ptr/observers/owner_hash.cc
@@ -0,0 +1,50 @@
+// { dg-do run { target c++26 } }
+// { dg-require-effective-target hosted }
+
+// N5008 20.3.2.3.6 weak_ptr observers [util.smartptr.weak.obs]
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct A { };
+struct B { };
+
+void
+test01()
+{
+ // test empty weak_ptr hashes compare equivalent
+ std::weak_ptr<A> p1;
+ std::weak_ptr<B> p2;
+ VERIFY( p1.owner_hash() == p2.owner_hash() );
+
+ std::shared_ptr<B> p3;
+ VERIFY( p1.owner_hash() == p3.owner_hash() );
+
+ static_assert( noexcept(p1.owner_hash()) );
+ static_assert( noexcept(p2.owner_hash()) );
+}
+
+
+void
+test02()
+{
+ std::shared_ptr<A> a0;
+ std::weak_ptr<A> w0(a0);
+
+ std::shared_ptr<A> a1(new A);
+ std::weak_ptr<A> w1(a1);
+ VERIFY( a1.owner_hash() == w1.owner_hash() );
+ VERIFY( w1.owner_hash() != w0.owner_hash() );
+ VERIFY( w1.owner_hash() != a0.owner_hash() );
+
+ std::shared_ptr<B> b1(new B);
+ VERIFY( w1.owner_hash() != b1.owner_hash() );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
index e71fdc5..bca8901 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
@@ -98,12 +98,32 @@ test_deduction(Extents... exts)
}
constexpr bool
+test_integral_constant_deduction()
+{
+ auto verify = [](auto actual, auto expected)
+ {
+ static_assert(std::same_as<decltype(actual), decltype(expected)>);
+ VERIFY(actual == expected);
+ };
+
+ constexpr auto c1 = std::integral_constant<size_t, 1>{};
+ constexpr auto c2 = std::integral_constant<int, 2>{};
+
+ verify(std::extents(1), std::extents<size_t, dyn>{1});
+ verify(std::extents(c1), std::extents<size_t, 1>{});
+ verify(std::extents(c2), std::extents<size_t, 2>{});
+ verify(std::extents(c1, 2), std::extents<size_t, 1, dyn>{2});
+ return true;
+}
+
+constexpr bool
test_deduction_all()
{
test_deduction<0>();
test_deduction<1>(1);
test_deduction<2>(1.0, 2.0f);
test_deduction<3>(int(1), short(2), size_t(3));
+ test_integral_constant_deduction();
return true;
}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
index 9252273..a650fb1 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc
@@ -246,6 +246,28 @@ test_from_pointer_and_shape()
}
constexpr bool
+test_from_pointer_and_integral_constant()
+{
+ std::array<double, 6> buffer{};
+ double * ptr = buffer.data();
+
+ auto verify = [ptr](auto actual, auto exts)
+ {
+ auto expected = std::mdspan<double, decltype(exts)>(ptr, exts);
+ static_assert(std::same_as<decltype(actual), decltype(expected)>);
+ VERIFY(actual.extents() == expected.extents());
+ };
+
+ auto c3 = std::integral_constant<int, 3>{};
+ auto c6 = std::integral_constant<int, 6>{};
+
+ verify(std::mdspan(ptr, 6), std::extents(6));
+ verify(std::mdspan(ptr, c6), std::extents(c6));
+ verify(std::mdspan(ptr, 2, c3), std::extents(2, c3));
+ return true;
+}
+
+constexpr bool
test_from_extents()
{
constexpr size_t n = 3*5*7;
@@ -616,6 +638,9 @@ main()
test_from_pointer_and_shape();
static_assert(test_from_pointer_and_shape());
+ test_from_pointer_and_integral_constant();
+ static_assert(test_from_pointer_and_integral_constant());
+
test_from_extents();
static_assert(test_from_extents());
diff --git a/libstdc++-v3/testsuite/23_containers/span/deduction.cc b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
index dce6ced..c66db90 100644
--- a/libstdc++-v3/testsuite/23_containers/span/deduction.cc
+++ b/libstdc++-v3/testsuite/23_containers/span/deduction.cc
@@ -80,4 +80,7 @@ test01()
std::span s12(const_cast<const std::span<int>&>(s5));
static_assert( is_dynamic_span<int>(s12) );
+
+ std::span s13(a.data(), std::integral_constant<size_t, 3>{});
+ static_assert( is_static_span<long, 3>(s13));
}
diff --git a/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc
new file mode 100644
index 0000000..9a6ed16
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/ranges/pr119861_neg.cc
@@ -0,0 +1,52 @@
+// { dg-do compile { target c++23 } }
+
+#include <format>
+#include <vector>
+
+// only format_kind::sequence provides set_brackets and set_separator methods
+
+template<std::range_format fk, typename T>
+struct MyCont : std::vector<T>
+{
+ using std::vector<T>::vector;
+};
+
+template<std::range_format fk, typename T>
+constexpr std::range_format std::format_kind<MyCont<fk, T>> = fk;
+
+void test_sequence()
+{
+ std::formatter<MyCont<std::range_format::sequence, int>, char> fmtter;
+ fmtter.set_brackets("{", "}");
+ fmtter.set_separator(",");
+}
+
+void test_map()
+{
+ std::formatter<MyCont<std::range_format::map, std::pair<int, int>>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_set()
+{
+ std::formatter<MyCont<std::range_format::set, int>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_string()
+{
+ std::formatter<MyCont<std::range_format::string, char>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+void test_debug_string()
+{
+ std::formatter<MyCont<std::range_format::debug_string, char>, char> fmtter;
+ fmtter.set_brackets("{", "}"); // { dg-error "here" }
+ fmtter.set_separator(","); // { dg-error "here" }
+}
+
+// { dg-error "no matching function for call to 'std::formatter<" "" { target *-*-* } 0 }
diff --git a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc
index 4739d9e..fbd783b 100644
--- a/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc
+++ b/libstdc++-v3/testsuite/std/ranges/iota/max_size_type.cc
@@ -352,6 +352,9 @@ static_assert(numeric_limits<max_size_t>::is_specialized);
static_assert(!numeric_limits<max_size_t>::is_signed);
static_assert(numeric_limits<max_size_t>::is_integer);
static_assert(numeric_limits<max_size_t>::is_exact);
+static_assert(numeric_limits<max_size_t>::is_bounded);
+static_assert(numeric_limits<max_size_t>::is_modulo);
+static_assert(numeric_limits<max_size_t>::radix == 2);
// We can't unconditionally use numeric_limits here because __int128 is an
// integral type only in GNU mode.
#if __SIZEOF_INT128__
@@ -379,6 +382,9 @@ static_assert(numeric_limits<max_diff_t>::is_specialized);
static_assert(numeric_limits<max_diff_t>::is_signed);
static_assert(numeric_limits<max_diff_t>::is_integer);
static_assert(numeric_limits<max_diff_t>::is_exact);
+static_assert(numeric_limits<max_diff_t>::is_bounded);
+static_assert(!numeric_limits<max_diff_t>::is_modulo);
+static_assert(numeric_limits<max_diff_t>::radix == 2);
static_assert(numeric_limits<max_diff_t>::digits
== numeric_limits<max_size_t>::digits - 1);
static_assert(numeric_limits<max_diff_t>::digits10
@@ -400,6 +406,31 @@ static_assert(max_diff_t(max_size_t(1)
<< (numeric_limits<max_size_t>::digits-1))
== numeric_limits<max_diff_t>::min());
+template <typename integer_class>
+constexpr bool verify_numeric_limits_values_not_meaningful_for = true
+ && (numeric_limits<integer_class>::max_digits10 == 0)
+ && (numeric_limits<integer_class>::min_exponent == 0)
+ && (numeric_limits<integer_class>::min_exponent10 == 0)
+ && (numeric_limits<integer_class>::max_exponent == 0)
+ && (numeric_limits<integer_class>::max_exponent10 == 0)
+ && !numeric_limits<integer_class>::is_iec559
+ && !numeric_limits<integer_class>::has_infinity
+ && !numeric_limits<integer_class>::has_quiet_NaN
+ && !numeric_limits<integer_class>::has_signaling_NaN
+ && !numeric_limits<integer_class>::has_denorm_loss
+ && !numeric_limits<integer_class>::tinyness_before
+ && (numeric_limits<integer_class>::has_denorm == std::denorm_absent)
+ && (numeric_limits<integer_class>::round_style == std::round_toward_zero)
+ && (numeric_limits<integer_class>::denorm_min() == 0)
+ && (numeric_limits<integer_class>::epsilon() == 0)
+ && (numeric_limits<integer_class>::round_error() == 0)
+ && (numeric_limits<integer_class>::infinity() == 0)
+ && (numeric_limits<integer_class>::quiet_NaN() == 0)
+ && (numeric_limits<integer_class>::signaling_NaN() == 0);
+
+static_assert(verify_numeric_limits_values_not_meaningful_for<max_size_t>);
+static_assert(verify_numeric_limits_values_not_meaningful_for<max_diff_t>);
+
// Verify that the types are structural types and can therefore be used
// as NTTP types.
template<max_size_t V> struct Su { static_assert(V*V == V+132); };