diff options
Diffstat (limited to 'libstdc++-v3')
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); }; |