diff options
Diffstat (limited to 'libstdc++-v3')
50 files changed, 2161 insertions, 268 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index abe6fed..090c5ce 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,216 @@ +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 + * include/bits/stl_iterator.h (__normal_iterator): Fix order of + always_inline and nodiscard attributes for Clang compatibility. + +2025-07-07 Jonathan Wakely <jwakely@redhat.com> + + * testsuite/util/testsuite_hooks.h (VERIFY): Define as variadic + macro. + * testsuite/ext/verify_neg.cc: New test. + +2025-07-07 Jonathan Wakely <jwakely@redhat.com> + + * include/std/mdspan (__mapping_of): Add template keyword. + +2025-07-07 XU Kailiang <xu2k3l4@outlook.com> + Tomasz Kaminski <tkaminsk@redhat.com> + + PR libstdc++/117214 + * include/bits/chrono_io.h (_ChronoSpec::_M_time_only): Remove. + (_ChronoSpec::_M_time_point): Define. + (__formatter_chrono::_M_parse): Use __parts to determine + interpretation of j. + (__formatter_chrono::_M_check_ok): Define. + (__formatter_chrono::_M_format_to): Invoke _M_check_ok. + (__formatter_chrono::_M_a_A, __formatter_chrono::_M_b_B): Move + exception throwing to _M_check_ok. + (__formatter_chrono::_M_j): Use _M_needs to define interpretation. + (__formatter_duration::_S_spec_for): Set _M_time_point. + * testsuite/std/time/format/format.cc: Test for exception for !ok() + months/weekday. + * testsuite/std/time/format/pr117214_custom_timeput.cc: New + test. + +2025-07-07 Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/120976 + * include/std/format (formatter<__float128, _Char_T): Define if + _GLIBCXX_FORMAT_F128 == 2. + 2025-07-06 Patrick Palka <ppalka@redhat.com> * include/bits/ranges_algo.h (shift_left, shift_right): Guard 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/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver index 2818ab3..1c423ff 100644 --- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver +++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver @@ -117,11 +117,11 @@ GLIBCXX_8.0 { _ZN9__gnu_cxx3__818stdio_sync_filebufI[cw]NSt3__811char_traitsI[cw]EEE[5-9]*; # debug mode - _ZN11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv; - _ZN11__gnu_debug19_Safe_sequence_base13_M_detach_allEv; - _ZN11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv; - _ZN11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv; - _ZN11__gnu_debug19_Safe_sequence_base7_M_swapERS0_; + _ZNK11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv; + _ZNK11__gnu_debug19_Safe_sequence_base13_M_detach_allEv; + _ZNK11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv; + _ZNK11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv; + _ZNK11__gnu_debug19_Safe_sequence_base7_M_swapERKS0_; _ZN11__gnu_debug19_Safe_iterator_base9_M_attach*; _ZN11__gnu_debug19_Safe_iterator_base16_M_attach_single*; @@ -136,11 +136,11 @@ GLIBCXX_8.0 { # __gnu_debug::_Safe_unordered_container_base # __gnu_debug::_Safe_local_iterator_base - _ZN11__gnu_debug30_Safe_unordered_container_base7_M_swapERS0_; - _ZN11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv; - _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPNS_19_Safe_sequence_baseEb; + _ZNK11__gnu_debug30_Safe_unordered_container_base7_M_swapERKS0_; + _ZNK11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv; + _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPKNS_30_Safe_unordered_container_baseEb; _ZN11__gnu_debug25_Safe_local_iterator_base9_M_detachEv; - _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPNS_19_Safe_sequence_baseEb; + _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPKNS_30_Safe_unordered_container_baseEb; # parallel mode _ZN14__gnu_parallel9_Settings3getEv; diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 73b6f33..b5a89c3 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2555,6 +2555,20 @@ GLIBCXX_3.4.35 { _ZNSt8__detail17__wait_until_implEPKvRNS_16__wait_args_baseERKNSt6chrono8durationI[lx]St5ratioIL[lx]1EL[lx]1000000000EEEE; _ZNSt8__detail11__wait_args22_M_load_proxy_wait_valEPKv; + # __gnu_debug::_Safe_iterator_base and _Safe_sequence_base const + _ZN11__gnu_debug19_Safe_iterator_base9_M_attachEPKNS_19_Safe_sequence_baseEb; + _ZN11__gnu_debug19_Safe_iterator_base16_M_attach_singleEPKNS_19_Safe_sequence_baseEb; + _ZNK11__gnu_debug19_Safe_sequence_base13_M_detach_allEv; + _ZNK11__gnu_debug19_Safe_sequence_base18_M_detach_singularEv; + _ZNK11__gnu_debug19_Safe_sequence_base12_M_get_mutexEv; + _ZNK11__gnu_debug19_Safe_sequence_base22_M_revalidate_singularEv; + _ZNK11__gnu_debug19_Safe_sequence_base7_M_swapERKS0_; + + # __gnu_debug::_Safe_local_iterator_base and _Safe_unordered_container_base const + _ZN11__gnu_debug25_Safe_local_iterator_base9_M_attachEPKNS_30_Safe_unordered_container_baseEb; + _ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPKNS_30_Safe_unordered_container_baseEb; + _ZNK11__gnu_debug30_Safe_unordered_container_base13_M_detach_allEv; + _ZNK11__gnu_debug30_Safe_unordered_container_base7_M_swapERKS0_; } GLIBCXX_3.4.34; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index a7188f4..75e794f 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1211,7 +1211,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else // Forward iterator requirements template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1220,7 +1220,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() == __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1229,7 +1229,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() == __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1238,7 +1238,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() != __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1248,15 +1248,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Random access iterator requirements template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR + _GLIBCXX_CONSTEXPR inline bool operator<(const __normal_iterator& __lhs, const __normal_iterator<_Iter, _Container>& __rhs) _GLIBCXX_NOEXCEPT { return __lhs.base() < __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX20_CONSTEXPR bool @@ -1265,15 +1266,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() < __rhs.base(); } template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR + _GLIBCXX_CONSTEXPR bool operator>(const __normal_iterator& __lhs, const __normal_iterator<_Iter, _Container>& __rhs) _GLIBCXX_NOEXCEPT { return __lhs.base() > __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1282,7 +1284,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() > __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1291,7 +1293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() <= __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1300,7 +1302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() <= __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1309,7 +1311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() >= __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1341,7 +1343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif { return __lhs.base() - __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR difference_type @@ -1349,7 +1351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() - __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR __normal_iterator diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 64f8190..f1015ab 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1007,9 +1007,8 @@ ftms = { ftms = { name = mdspan; - no_stdname = true; // FIXME: remove values = { - v = 1; // FIXME: 202207 + v = 202207; cxxmin = 23; }; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 744246a..80f6586 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1126,8 +1126,9 @@ #if !defined(__cpp_lib_mdspan) # if (__cplusplus >= 202100L) -# define __glibcxx_mdspan 1L +# define __glibcxx_mdspan 202207L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_mdspan) +# define __cpp_lib_mdspan 202207L # endif # endif #endif /* !defined(__cpp_lib_mdspan) && defined(__glibcxx_want_mdspan) */ diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque index 59d60b2..ed69eb8 100644 --- a/libstdc++-v3/include/debug/deque +++ b/libstdc++-v3/include/debug/deque @@ -650,7 +650,8 @@ namespace __debug else if (__first.base() == _Base::begin() || __last.base() == _Base::end()) { - this->_M_detach_singular(); + const deque* __this = this; + __this->_M_detach_singular(); for (_Base_const_iterator __position = __first.base(); __position != __last.base(); ++__position) { @@ -663,7 +664,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h index d80e8a7..8aa84ad 100644 --- a/libstdc++-v3/include/debug/formatter.h +++ b/libstdc++-v3/include/debug/formatter.h @@ -96,7 +96,7 @@ namespace __gnu_debug template<typename _Iterator, typename _Sequence, typename _Category> class _Safe_iterator; - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> class _Safe_local_iterator; template<typename _Sequence> @@ -316,8 +316,8 @@ namespace __gnu_debug } } - template<typename _Iterator, typename _Sequence> - _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it, + template<typename _Iterator, typename _UContainer> + _Parameter(_Safe_local_iterator<_Iterator, _UContainer> const& __it, const char* __name, _Is_iterator) : _M_kind(__iterator), _M_variant() { @@ -326,8 +326,8 @@ namespace __gnu_debug _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); _M_variant._M_iterator._M_constness = __it._S_constant() ? __const_iterator : __mutable_iterator; - _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); - _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); + _M_variant._M_iterator._M_sequence = __it._M_get_ucontainer(); + _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_UContainer); if (__it._M_singular()) { diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list index 60a2542..9da7dda 100644 --- a/libstdc++-v3/include/debug/forward_list +++ b/libstdc++-v3/include/debug/forward_list @@ -58,44 +58,44 @@ namespace __gnu_debug class _Safe_forward_list : public _Safe_sequence<_SafeSequence> { - _SafeSequence& - _M_this() noexcept - { return *static_cast<_SafeSequence*>(this); } + const _SafeSequence* + _M_this() const noexcept + { return static_cast<const _SafeSequence*>(this); } static void - _M_swap_aux(_Safe_sequence_base& __lhs, + _S_swap_aux(const _Safe_forward_list& __lhs, _Safe_iterator_base*& __lhs_iterators, - _Safe_sequence_base& __rhs, + const _Safe_forward_list& __rhs, _Safe_iterator_base*& __rhs_iterators); - void _M_swap_single(_Safe_sequence_base&) noexcept; + void _M_swap_single(const _Safe_forward_list&) const noexcept; protected: void - _M_invalidate_all() + _M_invalidate_all() const { - using _Base_const_iterator = __decltype(_M_this()._M_base().cend()); + using _Base_const_iterator = __decltype(_M_this()->_M_base().cend()); this->_M_invalidate_if([this](_Base_const_iterator __it) { - return __it != _M_this()._M_base().cbefore_begin() - && __it != _M_this()._M_base().cend(); }); + return __it != _M_this()->_M_base().cbefore_begin() + && __it != _M_this()->_M_base().cend(); }); } - void _M_swap(_Safe_sequence_base&) noexcept; + void + _M_swap(const _Safe_forward_list&) const noexcept; }; template<typename _SafeSequence> void _Safe_forward_list<_SafeSequence>:: - _M_swap_aux(_Safe_sequence_base& __lhs, + _S_swap_aux(const _Safe_forward_list& __lhs, _Safe_iterator_base*& __lhs_iterators, - _Safe_sequence_base& __rhs, + const _Safe_forward_list& __rhs, _Safe_iterator_base*& __rhs_iterators) { using const_iterator = typename _SafeSequence::const_iterator; _Safe_iterator_base* __bbegin_its = 0; _Safe_iterator_base* __last_bbegin = 0; - _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs); for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;) { @@ -104,7 +104,7 @@ namespace __gnu_debug const_iterator* __victim = static_cast<const_iterator*>(__victim_base); __iter = __iter->_M_next; - if (__victim->base() == __rseq._M_base().cbefore_begin()) + if (__victim->base() == __rhs._M_this()->_M_base().cbefore_begin()) { __victim->_M_unlink(); if (__lhs_iterators == __victim_base) @@ -136,21 +136,21 @@ namespace __gnu_debug template<typename _SafeSequence> void _Safe_forward_list<_SafeSequence>:: - _M_swap_single(_Safe_sequence_base& __other) noexcept + _M_swap_single(const _Safe_forward_list& __other) const noexcept { - std::swap(_M_this()._M_iterators, __other._M_iterators); - std::swap(_M_this()._M_const_iterators, __other._M_const_iterators); + std::swap(_M_this()->_M_iterators, __other._M_iterators); + std::swap(_M_this()->_M_const_iterators, __other._M_const_iterators); // Useless, always 1 on forward_list - //std::swap(_M_this()_M_version, __other._M_version); - _Safe_iterator_base* __this_its = _M_this()._M_iterators; - _M_swap_aux(__other, __other._M_iterators, - _M_this(), _M_this()._M_iterators); - _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators; - _M_swap_aux(__other, __other._M_const_iterators, - _M_this(), _M_this()._M_const_iterators); - _M_swap_aux(_M_this(), __this_its, + //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); + _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, __other, __other._M_iterators); - _M_swap_aux(_M_this(), __this_const_its, + _S_swap_aux(*_M_this(), __this_const_its, __other, __other._M_const_iterators); } @@ -159,13 +159,12 @@ namespace __gnu_debug template<typename _SafeSequence> void _Safe_forward_list<_SafeSequence>:: - _M_swap(_Safe_sequence_base& __other) noexcept + _M_swap(const _Safe_forward_list& __other) const noexcept { // We need to lock both sequences to swap using namespace __gnu_cxx; - __mutex *__this_mutex = &_M_this()._M_get_mutex(); - __mutex *__other_mutex = - &static_cast<_SafeSequence&>(__other)._M_get_mutex(); + __mutex *__this_mutex = &_M_this()->_M_get_mutex(); + __mutex *__other_mutex = &__other._M_get_mutex(); if (__this_mutex == __other_mutex) { __scoped_lock __lock(*__this_mutex); @@ -565,7 +564,8 @@ namespace __debug void resize(size_type __sz) { - this->_M_detach_singular(); + const forward_list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin+__sz, end() _Base_iterator __victim = _Base::begin(); @@ -585,7 +585,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } @@ -593,7 +593,8 @@ namespace __debug void resize(size_type __sz, const value_type& __val) { - this->_M_detach_singular(); + const forward_list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin+__sz, end()) _Base_iterator __victim = _Base::begin(); @@ -613,7 +614,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list index a9d974c..c502c7c 100644 --- a/libstdc++-v3/include/debug/list +++ b/libstdc++-v3/include/debug/list @@ -321,7 +321,8 @@ namespace __debug void resize(size_type __sz) { - this->_M_detach_singular(); + const list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); @@ -338,7 +339,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } @@ -346,7 +347,8 @@ namespace __debug void resize(size_type __sz, const _Tp& __c) { - this->_M_detach_singular(); + const list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); @@ -363,7 +365,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } @@ -371,7 +373,8 @@ namespace __debug void resize(size_type __sz, _Tp __c = _Tp()) { - this->_M_detach_singular(); + const list* __this = this; + __this->_M_detach_singular(); // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); @@ -388,7 +391,7 @@ namespace __debug } __catch(...) { - this->_M_revalidate_singular(); + __this->_M_revalidate_singular(); __throw_exception_again; } } diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h index cf3f170..4462297 100644 --- a/libstdc++-v3/include/debug/safe_base.h +++ b/libstdc++-v3/include/debug/safe_base.h @@ -53,8 +53,10 @@ namespace __gnu_debug public: /** The sequence this iterator references; may be NULL to indicate - a singular iterator. */ - _Safe_sequence_base* _M_sequence; + * a singular iterator. Stored as pointer-to-const because sequence + * could be declared as const. + */ + const _Safe_sequence_base* _M_sequence; /** The version number of this iterator. The sentinel value 0 is * used to indicate an invalidated iterator (i.e., one that is @@ -92,7 +94,7 @@ namespace __gnu_debug : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) { if (!std::__is_constant_evaluated()) - this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); + this->_M_attach(__seq, __constant); } /** Initializes the iterator to reference the same sequence that @@ -115,7 +117,7 @@ namespace __gnu_debug /** For use in _Safe_iterator. */ __gnu_cxx::__mutex& - _M_get_mutex() throw (); + _M_get_mutex() _GLIBCXX_USE_NOEXCEPT; /** Attaches this iterator to the given sequence, detaching it * from whatever sequence it was attached to originally. If the @@ -123,11 +125,12 @@ namespace __gnu_debug * unattached. */ void - _M_attach(_Safe_sequence_base* __seq, bool __constant); + _M_attach(const _Safe_sequence_base* __seq, bool __constant); /** Likewise, but not thread-safe. */ void - _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw (); + _M_attach_single(const _Safe_sequence_base* __seq, + bool __constant) _GLIBCXX_USE_NOEXCEPT; /** Detach the iterator for whatever sequence it is attached to, * if any. @@ -135,10 +138,23 @@ namespace __gnu_debug void _M_detach(); +#if !_GLIBCXX_INLINE_VERSION + private: + /***************************************************************/ + /** Not-const method preserved for abi backward compatibility. */ + void + _M_attach(_Safe_sequence_base* __seq, bool __constant); + + void + _M_attach_single(_Safe_sequence_base* __seq, + bool __constant) _GLIBCXX_USE_NOEXCEPT; + /***************************************************************/ +#endif + public: /** Likewise, but not thread-safe. */ void - _M_detach_single() throw (); + _M_detach_single() _GLIBCXX_USE_NOEXCEPT; /** Determines if we are attached to the given sequence. */ bool @@ -147,13 +163,13 @@ namespace __gnu_debug /** Is this iterator singular? */ _GLIBCXX_PURE bool - _M_singular() const throw (); + _M_singular() const _GLIBCXX_USE_NOEXCEPT; /** Can we compare this iterator to the given iterator @p __x? Returns true if both iterators are nonsingular and reference the same sequence. */ _GLIBCXX_PURE bool - _M_can_compare(const _Safe_iterator_base& __x) const throw (); + _M_can_compare(const _Safe_iterator_base& __x) const _GLIBCXX_USE_NOEXCEPT; /** Invalidate the iterator, making it singular. */ void @@ -162,11 +178,11 @@ namespace __gnu_debug /** Reset all member variables */ void - _M_reset() throw (); + _M_reset() _GLIBCXX_USE_NOEXCEPT; /** Unlink itself */ void - _M_unlink() throw () + _M_unlink() _GLIBCXX_USE_NOEXCEPT { if (_M_prior) _M_prior->_M_next = _M_next; @@ -246,14 +262,14 @@ namespace __gnu_debug /** Detach all iterators, leaving them singular. */ void - _M_detach_all(); + _M_detach_all() const; /** Detach all singular iterators. * @post for all iterators i attached to this sequence, * i->_M_version == _M_version. */ void - _M_detach_singular(); + _M_detach_singular() const; /** Revalidates all attached singular iterators. This method may * be used to validate iterators that were invalidated before @@ -261,7 +277,7 @@ namespace __gnu_debug * valid again). */ void - _M_revalidate_singular(); + _M_revalidate_singular() const; /** Swap this sequence with the given sequence. This operation * also swaps ownership of the iterators, so that when the @@ -269,11 +285,11 @@ namespace __gnu_debug * one container now reference the other container. */ void - _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; + _M_swap(const _Safe_sequence_base& __x) const _GLIBCXX_USE_NOEXCEPT; /** For use in _Safe_sequence. */ __gnu_cxx::__mutex& - _M_get_mutex() throw (); + _M_get_mutex() const _GLIBCXX_USE_NOEXCEPT; /** Invalidates all iterators. */ void @@ -281,21 +297,42 @@ namespace __gnu_debug { if (++_M_version == 0) _M_version = 1; } private: +#if !_GLIBCXX_INLINE_VERSION + /***************************************************************/ + /** Not-const method preserved for abi backward compatibility. */ + void + _M_detach_all(); + + void + _M_detach_singular(); + + void + _M_revalidate_singular(); + + void + _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; + + __gnu_cxx::__mutex& + _M_get_mutex() _GLIBCXX_USE_NOEXCEPT; + /***************************************************************/ +#endif + /** Attach an iterator to this sequence. */ void - _M_attach(_Safe_iterator_base* __it, bool __constant); + _M_attach(_Safe_iterator_base* __it, bool __constant) const; /** Likewise but not thread safe. */ void - _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw (); + _M_attach_single(_Safe_iterator_base* __it, + bool __constant) const _GLIBCXX_USE_NOEXCEPT; /** Detach an iterator from this sequence */ void - _M_detach(_Safe_iterator_base* __it); + _M_detach(_Safe_iterator_base* __it) const; /** Likewise but not thread safe. */ void - _M_detach_single(_Safe_iterator_base* __it) throw (); + _M_detach_single(_Safe_iterator_base* __it) const _GLIBCXX_USE_NOEXCEPT; }; } // namespace __gnu_debug diff --git a/libstdc++-v3/include/debug/safe_container.h b/libstdc++-v3/include/debug/safe_container.h index cb1e69a..3341806 100644 --- a/libstdc++-v3/include/debug/safe_container.h +++ b/libstdc++-v3/include/debug/safe_container.h @@ -44,9 +44,9 @@ namespace __gnu_debug typedef _SafeBase<_SafeContainer> _Base; _GLIBCXX20_CONSTEXPR - _SafeContainer& - _M_cont() _GLIBCXX_NOEXCEPT - { return *static_cast<_SafeContainer*>(this); } + const _SafeContainer& + _M_cont() const _GLIBCXX_NOEXCEPT + { return *static_cast<const _SafeContainer*>(this); } protected: #if __cplusplus >= 201103L @@ -56,6 +56,11 @@ namespace __gnu_debug private: _GLIBCXX20_CONSTEXPR + void + _M_swap_base(const _Safe_container& __x) const noexcept + { _Base::_M_swap(__x); } + + _GLIBCXX20_CONSTEXPR _Safe_container(_Safe_container&& __x, const _Alloc&, std::true_type) : _Safe_container(std::move(__x)) { } @@ -67,7 +72,7 @@ namespace __gnu_debug if (!std::__is_constant_evaluated()) { if (__x._M_cont().get_allocator() == __a) - _Base::_M_swap(__x); + _M_swap_base(__x); else __x._M_invalidate_all(); } @@ -115,12 +120,12 @@ namespace __gnu_debug bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() || _M_cont().get_allocator() == __x._M_cont().get_allocator(); if (__xfer_memory) - _Base::_M_swap(__x); + _M_swap_base(__x); else this->_M_invalidate_all(); } else - _Base::_M_swap(__x); + _M_swap_base(__x); __x._M_invalidate_all(); return *this; @@ -128,7 +133,7 @@ namespace __gnu_debug _GLIBCXX20_CONSTEXPR void - _M_swap(_Safe_container& __x) noexcept + _M_swap(const _Safe_container& __x) const noexcept { if (_IsCxx11AllocatorAware) { @@ -139,8 +144,12 @@ namespace __gnu_debug __x._M_cont()._M_base()); } - _Base::_M_swap(__x); + _M_swap_base(__x); } +#else + void + _M_swap(const _Safe_container& __x) const throw() + { _Base::_M_swap(__x); } #endif }; diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h index 7c56338..e0b1b46 100644 --- a/libstdc++-v3/include/debug/safe_iterator.h +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -224,7 +224,7 @@ namespace __gnu_debug _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _Safe_sequence_base* __seq = __x._M_sequence; + const _Safe_sequence_base* __seq = __x._M_sequence; __x._M_detach(); std::swap(base(), __x.base()); _M_attach(__seq); @@ -445,12 +445,12 @@ namespace __gnu_debug /** Attach iterator to the given sequence. */ void - _M_attach(_Safe_sequence_base* __seq) + _M_attach(const _Safe_sequence_base* __seq) { _Safe_base::_M_attach(__seq, _S_constant()); } /** Likewise, but not thread-safe. */ void - _M_attach_single(_Safe_sequence_base* __seq) + _M_attach_single(const _Safe_sequence_base* __seq) { _Safe_base::_M_attach_single(__seq, _S_constant()); } /// Is the iterator dereferenceable? @@ -500,7 +500,13 @@ namespace __gnu_debug typename __gnu_cxx::__conditional_type< _IsConstant::__value, const _Sequence*, _Sequence*>::__type _M_get_sequence() const - { return static_cast<_Sequence*>(_M_sequence); } + { + // Looks like not const-correct, but if _IsConstant the constness + // is restored when returning the sequence pointer and if not + // _IsConstant we are allowed to remove constness. + return static_cast<_Sequence*> + (const_cast<_Safe_sequence_base*>(_M_sequence)); + } // Get distance to __rhs. typename _Distance_traits<_Iterator>::__type diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h index c84f4f1..47b3a80 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.h +++ b/libstdc++-v3/include/debug/safe_local_iterator.h @@ -52,15 +52,15 @@ namespace __gnu_debug /** \brief Safe iterator wrapper. * * The class template %_Safe_local_iterator is a wrapper around an - * iterator that tracks the iterator's movement among sequences and - * checks that operations performed on the "safe" iterator are + * iterator that tracks the iterator's movement among unordered containers + * and checks that operations performed on the "safe" iterator are * legal. In additional to the basic iterator operations (which are * validated, and then passed to the underlying iterator), * %_Safe_local_iterator has member functions for iterator invalidation, - * attaching/detaching the iterator from sequences, and querying + * attaching/detaching the iterator from unordered containers, and querying * the iterator's state. */ - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> class _Safe_local_iterator : private _Iterator , public _Safe_local_iterator_base @@ -68,28 +68,27 @@ namespace __gnu_debug typedef _Iterator _Iter_base; typedef _Safe_local_iterator_base _Safe_base; - typedef typename _Sequence::size_type size_type; + typedef typename _UContainer::size_type size_type; typedef std::iterator_traits<_Iterator> _Traits; - typedef std::__are_same< - typename _Sequence::_Base::const_local_iterator, - _Iterator> _IsConstant; + using _IsConstant = std::__are_same< + typename _UContainer::_Base::const_local_iterator, _Iterator>; - typedef typename __gnu_cxx::__conditional_type<_IsConstant::__value, - typename _Sequence::_Base::local_iterator, - typename _Sequence::_Base::const_local_iterator>::__type - _OtherIterator; + using _OtherIterator = std::__conditional_t< + _IsConstant::__value, + typename _UContainer::_Base::local_iterator, + typename _UContainer::_Base::const_local_iterator>; typedef _Safe_local_iterator _Self; - typedef _Safe_local_iterator<_OtherIterator, _Sequence> _OtherSelf; + typedef _Safe_local_iterator<_OtherIterator, _UContainer> _OtherSelf; struct _Unchecked { }; _Safe_local_iterator(const _Safe_local_iterator& __x, _Unchecked) noexcept : _Iter_base(__x.base()) - { _M_attach(__x._M_sequence); } + { _M_attach(__x._M_safe_container()); } public: typedef _Iterator iterator_type; @@ -104,12 +103,13 @@ namespace __gnu_debug /** * @brief Safe iterator construction from an unsafe iterator and - * its sequence. + * its unordered container. * - * @pre @p seq is not NULL + * @pre @p cont is not NULL * @post this is not singular */ - _Safe_local_iterator(_Iterator __i, const _Safe_sequence_base* __cont) + _Safe_local_iterator(_Iterator __i, + const _Safe_unordered_container_base* __cont) : _Iter_base(__i), _Safe_base(__cont, _S_constant()) { } @@ -126,7 +126,7 @@ namespace __gnu_debug _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _M_attach(__x._M_sequence); + _M_attach(__x._M_safe_container()); } /** @@ -141,7 +141,7 @@ namespace __gnu_debug _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - auto __cont = __x._M_sequence; + auto __cont = __x._M_safe_container(); __x._M_detach(); std::swap(base(), __x.base()); _M_attach(__cont); @@ -156,7 +156,7 @@ namespace __gnu_debug const _Safe_local_iterator<_MutableIterator, typename __gnu_cxx::__enable_if<_IsConstant::__value && std::__are_same<_MutableIterator, _OtherIterator>::__value, - _Sequence>::__type>& __x) noexcept + _UContainer>::__type>& __x) noexcept : _Iter_base(__x.base()) { // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -166,7 +166,7 @@ namespace __gnu_debug _M_message(__msg_init_const_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); - _M_attach(__x._M_sequence); + _M_attach(__x._M_safe_container()); } /** @@ -193,7 +193,7 @@ namespace __gnu_debug { _M_detach(); base() = __x.base(); - _M_attach(__x._M_sequence); + _M_attach(__x._M_safe_container()); } return *this; @@ -225,7 +225,7 @@ namespace __gnu_debug { _M_detach(); base() = __x.base(); - _M_attach(__x._M_sequence); + _M_attach(__x._M_safe_container()); } __x._M_detach(); @@ -318,15 +318,15 @@ namespace __gnu_debug */ operator _Iterator() const { return *this; } - /** Attach iterator to the given sequence. */ + /** Attach iterator to the given unordered container. */ void - _M_attach(_Safe_sequence_base* __seq) - { _Safe_base::_M_attach(__seq, _S_constant()); } + _M_attach(const _Safe_unordered_container_base* __cont) + { _Safe_base::_M_attach(__cont, _S_constant()); } /** Likewise, but not thread-safe. */ void - _M_attach_single(_Safe_sequence_base* __seq) - { _Safe_base::_M_attach_single(__seq, _S_constant()); } + _M_attach_single(const _Safe_unordered_container_base* __cont) + { _Safe_base::_M_attach_single(__cont, _S_constant()); } /// Is the iterator dereferenceable? bool @@ -353,25 +353,31 @@ namespace __gnu_debug typename _Distance_traits<_Iterator>::__type _M_get_distance_to(const _Safe_local_iterator& __rhs) const; - // The sequence this iterator references. - typename __gnu_cxx::__conditional_type< - _IsConstant::__value, const _Sequence*, _Sequence*>::__type - _M_get_sequence() const - { return static_cast<_Sequence*>(_M_sequence); } + // The unordered container this iterator references. + std::__conditional_t< + _IsConstant::__value, const _UContainer*, _UContainer*> + _M_get_ucontainer() const + { + // Looks like not const-correct, but if _IsConstant the constness + // is restored when returning the container pointer and if not + // _IsConstant we are allowed to remove constness. + return static_cast<_UContainer*> + (const_cast<_Safe_unordered_container_base*>(_M_safe_container())); + } - /// Is this iterator equal to the sequence's begin(bucket) iterator? + /// Is this iterator equal to the container's begin(bucket) iterator? bool _M_is_begin() const - { return base() == _M_get_sequence()->_M_base().begin(bucket()); } + { return base() == _M_get_ucontainer()->_M_base().begin(bucket()); } - /// Is this iterator equal to the sequence's end(bucket) iterator? + /// Is this iterator equal to the container's end(bucket) iterator? bool _M_is_end() const - { return base() == _M_get_sequence()->_M_base().end(bucket()); } + { return base() == _M_get_ucontainer()->_M_base().end(bucket()); } /// Is this iterator part of the same bucket as the other one? template<typename _Other> bool _M_in_same_bucket(const _Safe_local_iterator<_Other, - _Sequence>& __other) const + _UContainer>& __other) const { return bucket() == __other.bucket(); } friend inline bool @@ -404,31 +410,31 @@ namespace __gnu_debug }; /** Safe local iterators know how to check if they form a valid range. */ - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> inline bool - __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first, - const _Safe_local_iterator<_Iterator, _Sequence>& __last, + __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first, + const _Safe_local_iterator<_Iterator, _UContainer>& __last, typename _Distance_traits<_Iterator>::__type& __dist_info) { return __first._M_valid_range(__last, __dist_info); } - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> inline bool - __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>& __first, - const _Safe_local_iterator<_Iterator, _Sequence>& __last) + __valid_range(const _Safe_local_iterator<_Iterator, _UContainer>& __first, + const _Safe_local_iterator<_Iterator, _UContainer>& __last) { typename _Distance_traits<_Iterator>::__type __dist_info; return __first._M_valid_range(__last, __dist_info); } #if __cplusplus < 201103L - template<typename _Iterator, typename _Sequence> - struct _Unsafe_type<_Safe_local_iterator<_Iterator, _Sequence> > + template<typename _Iterator, typename _UContainer> + struct _Unsafe_type<_Safe_local_iterator<_Iterator, _UContainer> > { typedef _Iterator _Type; }; #endif - template<typename _Iterator, typename _Sequence> + template<typename _Iterator, typename _UContainer> inline _Iterator - __unsafe(const _Safe_local_iterator<_Iterator, _Sequence>& __it) + __unsafe(const _Safe_local_iterator<_Iterator, _UContainer>& __it) { return __it.base(); } } // namespace __gnu_debug diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc b/libstdc++-v3/include/debug/safe_local_iterator.tcc index 71e5320..10fec3f 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.tcc +++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc @@ -44,7 +44,7 @@ namespace __gnu_debug if (__rhs._M_is_end()) return { - _M_get_sequence()->bucket_size(bucket()), + _M_get_ucontainer()->bucket_size(bucket()), __dp_exact }; @@ -56,7 +56,7 @@ namespace __gnu_debug if (__rhs._M_is_begin()) return { - -_M_get_sequence()->bucket_size(bucket()), + -_M_get_ucontainer()->bucket_size(bucket()), __dp_exact }; diff --git a/libstdc++-v3/include/debug/safe_sequence.h b/libstdc++-v3/include/debug/safe_sequence.h index 6b35afa..e10474a 100644 --- a/libstdc++-v3/include/debug/safe_sequence.h +++ b/libstdc++-v3/include/debug/safe_sequence.h @@ -114,7 +114,7 @@ namespace __gnu_debug in the safe ones. */ template<typename _Predicate> void - _M_invalidate_if(_Predicate __pred); + _M_invalidate_if(_Predicate __pred) const; /** Transfers all iterators @c x that reference @c from sequence, are not singular, and for which @c __pred(x) returns @c @@ -122,7 +122,8 @@ namespace __gnu_debug in the safe ones. */ template<typename _Predicate> void - _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred); + _M_transfer_from_if(const _Safe_sequence& __from, + _Predicate __pred) const; }; /// Like _Safe_sequence but with a special _M_invalidate_all implementation @@ -133,12 +134,12 @@ namespace __gnu_debug { protected: void - _M_invalidate_all() + _M_invalidate_all() const { typedef typename _Sequence::const_iterator _Const_iterator; typedef typename _Const_iterator::iterator_type _Base_const_iterator; typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; - const _Sequence& __seq = *static_cast<_Sequence*>(this); + const _Sequence& __seq = *static_cast<const _Sequence*>(this); this->_M_invalidate_if(_Not_equal(__seq._M_base().end())); } }; diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc b/libstdc++-v3/include/debug/safe_sequence.tcc index 336bf2a..053361d 100644 --- a/libstdc++-v3/include/debug/safe_sequence.tcc +++ b/libstdc++-v3/include/debug/safe_sequence.tcc @@ -35,7 +35,7 @@ namespace __gnu_debug template<typename _Predicate> void _Safe_sequence<_Sequence>:: - _M_invalidate_if(_Predicate __pred) + _M_invalidate_if(_Predicate __pred) const { typedef typename _Sequence::iterator iterator; typedef typename _Sequence::const_iterator const_iterator; @@ -66,7 +66,7 @@ namespace __gnu_debug template<typename _Predicate> void _Safe_sequence<_Sequence>:: - _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred) + _M_transfer_from_if(const _Safe_sequence& __from, _Predicate __pred) const { if (this == std::__addressof(__from)) return; @@ -104,7 +104,7 @@ namespace __gnu_debug } for (_Safe_iterator_base* __iter2 = __from._M_const_iterators; - __iter2;) + __iter2;) { _Safe_iterator_base* __victim_base = __iter2; const_iterator* __victim = diff --git a/libstdc++-v3/include/debug/safe_unordered_base.h b/libstdc++-v3/include/debug/safe_unordered_base.h index 1547f5b..55cf581 100644 --- a/libstdc++-v3/include/debug/safe_unordered_base.h +++ b/libstdc++-v3/include/debug/safe_unordered_base.h @@ -49,6 +49,10 @@ namespace __gnu_debug */ class _Safe_local_iterator_base : public _Safe_iterator_base { + public: + const _Safe_unordered_container_base* + _M_safe_container() const noexcept; + protected: /** Initializes the iterator and makes it singular. */ _Safe_local_iterator_base() @@ -61,32 +65,32 @@ namespace __gnu_debug * singular. Otherwise, the iterator will reference @p __seq and * be nonsingular. */ - _Safe_local_iterator_base(const _Safe_sequence_base* __seq, bool __constant) - { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); } + _Safe_local_iterator_base(const _Safe_unordered_container_base* __seq, + bool __constant) + { _M_attach(__seq, __constant); } /** Initializes the iterator to reference the same container that @p __x does. @p __constant is true if this is a constant iterator, and false if it is mutable. */ _Safe_local_iterator_base(const _Safe_local_iterator_base& __x, bool __constant) - { this->_M_attach(__x._M_sequence, __constant); } + { this->_M_attach(__x._M_safe_container(), __constant); } ~_Safe_local_iterator_base() { this->_M_detach(); } - _Safe_unordered_container_base* - _M_get_container() const noexcept; - /** Attaches this iterator to the given container, detaching it * from whatever container it was attached to originally. If the * new container is the NULL pointer, the iterator is left * unattached. */ void - _M_attach(_Safe_sequence_base* __seq, bool __constant); + _M_attach(const _Safe_unordered_container_base* __cont, + bool __constant); /** Likewise, but not thread-safe. */ void - _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw (); + _M_attach_single(const _Safe_unordered_container_base* __cont, + bool __constant) noexcept; /** Detach the iterator for whatever container it is attached to, * if any. @@ -96,7 +100,19 @@ namespace __gnu_debug /** Likewise, but not thread-safe. */ void - _M_detach_single() throw (); + _M_detach_single() noexcept; + +#if !_GLIBCXX_INLINE_VERSION + private: + /***************************************************************/ + /** Not-const method preserved for abi backward compatibility. */ + void + _M_attach(_Safe_sequence_base* __seq, bool __constant); + + void + _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept; + /***************************************************************/ +#endif }; /** @@ -124,10 +140,10 @@ namespace __gnu_debug public: /// The list of mutable local iterators that reference this container - _Safe_iterator_base* _M_local_iterators; + mutable _Safe_iterator_base* _M_local_iterators; /// The list of constant local iterators that reference this container - _Safe_iterator_base* _M_const_local_iterators; + mutable _Safe_iterator_base* _M_const_local_iterators; protected: // Initialize with a version number of 1 and no iterators @@ -153,7 +169,7 @@ namespace __gnu_debug /** Detach all iterators, leaving them singular. */ void - _M_detach_all(); + _M_detach_all() const; /** Swap this container with the given container. This operation * also swaps ownership of the iterators, so that when the @@ -161,25 +177,42 @@ namespace __gnu_debug * one container now reference the other container. */ void - _M_swap(_Safe_unordered_container_base& __x) noexcept; + _M_swap(const _Safe_unordered_container_base& __x) const noexcept; private: +#if !_GLIBCXX_INLINE_VERSION + /***************************************************************/ + /** Not-const method preserved for abi backward compatibility. */ + void + _M_detach_all(); + + void + _M_swap(_Safe_unordered_container_base& __x) noexcept; + /***************************************************************/ +#endif + /** Attach an iterator to this container. */ void - _M_attach_local(_Safe_iterator_base* __it, bool __constant); + _M_attach_local(_Safe_iterator_base* __it, bool __constant) const; /** Likewise but not thread safe. */ void - _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw (); + _M_attach_local_single(_Safe_iterator_base* __it, + bool __constant) const noexcept; /** Detach an iterator from this container */ void - _M_detach_local(_Safe_iterator_base* __it); + _M_detach_local(_Safe_iterator_base* __it) const; /** Likewise but not thread safe. */ void - _M_detach_local_single(_Safe_iterator_base* __it) throw (); + _M_detach_local_single(_Safe_iterator_base* __it) const noexcept; }; + + inline const _Safe_unordered_container_base* + _Safe_local_iterator_base:: + _M_safe_container() const noexcept + { return static_cast<const _Safe_unordered_container_base*>(_M_sequence); } } // namespace __gnu_debug #endif diff --git a/libstdc++-v3/include/debug/safe_unordered_container.h b/libstdc++-v3/include/debug/safe_unordered_container.h index 2ba27db..b67b7e0 100644 --- a/libstdc++-v3/include/debug/safe_unordered_container.h +++ b/libstdc++-v3/include/debug/safe_unordered_container.h @@ -62,6 +62,10 @@ namespace __gnu_debug _M_cont() noexcept { return *static_cast<_Container*>(this); } + const _Safe_unordered_container* + _M_self() const + { return this; } + protected: void _M_invalidate_locals() diff --git a/libstdc++-v3/include/debug/safe_unordered_container.tcc b/libstdc++-v3/include/debug/safe_unordered_container.tcc index 6819389..0732e63 100644 --- a/libstdc++-v3/include/debug/safe_unordered_container.tcc +++ b/libstdc++-v3/include/debug/safe_unordered_container.tcc @@ -40,7 +40,7 @@ namespace __gnu_debug typedef typename _Container::iterator iterator; typedef typename _Container::const_iterator const_iterator; - __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex()); for (_Safe_iterator_base* __iter = _M_iterators; __iter;) { iterator* __victim = static_cast<iterator*>(__iter); @@ -72,7 +72,7 @@ namespace __gnu_debug typedef typename _Container::local_iterator local_iterator; typedef typename _Container::const_local_iterator const_local_iterator; - __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex()); for (_Safe_iterator_base* __iter = _M_local_iterators; __iter;) { local_iterator* __victim = static_cast<local_iterator*>(__iter); 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 4a06fb2..5d16de5 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -111,9 +111,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template<size_t _OtherRank, typename _GetOtherExtent> + static constexpr bool + _S_is_compatible_extents(_GetOtherExtent __get_extent) noexcept + { + if constexpr (_OtherRank == _S_rank) + for (size_t __i = 0; __i < _S_rank; ++__i) + if (_Extents[__i] != dynamic_extent + && !cmp_equal(_Extents[__i], _S_int_cast(__get_extent(__i)))) + return false; + return true; + } + + template<size_t _OtherRank, typename _GetOtherExtent> constexpr void _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept { + __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent)); for (size_t __i = 0; __i < _S_rank_dynamic; ++__i) { size_t __di = __i; @@ -385,13 +398,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __rev_prod(const _Extents& __exts, size_t __r) noexcept { return __exts_prod(__exts, __r + 1, __exts.rank()); } + template<typename _Extents> + constexpr typename _Extents::index_type + __size(const _Extents& __exts) noexcept + { return __fwd_prod(__exts, __exts.rank()); } + 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> @@ -401,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 { @@ -441,6 +455,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _IndexType __mult = 1; auto __update = [&, __pos = 0u](_IndexType __idx) mutable { + _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos))); __res += __idx * __mult; __mult *= __exts.extent(__pos); ++__pos; @@ -577,7 +592,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr index_type required_span_size() const noexcept - { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); } + { return __mdspan::__size(_M_extents); } template<__mdspan::__valid_index_type<index_type>... _Indices> requires (sizeof...(_Indices) == extents_type::rank()) @@ -651,6 +666,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto __update = [&, __pos = __exts.rank()](_IndexType) mutable { --__pos; + _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos], + __exts.extent(__pos))); __res += __ind_arr[__pos] * __mult; __mult *= __exts.extent(__pos); }; @@ -714,7 +731,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr index_type required_span_size() const noexcept - { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); } + { return __mdspan::__size(_M_extents); } template<__mdspan::__valid_index_type<index_type>... _Indices> requires (sizeof...(_Indices) == extents_type::rank()) @@ -822,6 +839,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { auto __update = [&, __pos = 0u](_IndexType __idx) mutable { + _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, + __m.extents().extent(__pos))); __res += __idx * __m.stride(__pos++); }; (__update(__indices), ...); @@ -968,8 +987,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if constexpr (!is_always_exhaustive()) { - constexpr auto __rank = extents_type::rank(); - auto __size = __mdspan::__fwd_prod(_M_extents, __rank); + auto __size = __mdspan::__size(_M_extents); if(__size > 0) return __size == required_span_size(); } @@ -1035,6 +1053,291 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __p + __i; } }; + namespace __mdspan + { + template<typename _Extents, typename _IndexType, size_t _Nm> + constexpr bool + __is_multi_index(const _Extents& __exts, span<_IndexType, _Nm> __indices) + { + static_assert(__exts.rank() == _Nm); + for (size_t __i = 0; __i < __exts.rank(); ++__i) + if (__indices[__i] >= __exts.extent(__i)) + return false; + return true; + } + } + + template<typename _ElementType, typename _Extents, + typename _LayoutPolicy = layout_right, + typename _AccessorPolicy = default_accessor<_ElementType>> + class mdspan + { + static_assert(!is_array_v<_ElementType>, + "ElementType must not be an array type"); + static_assert(!is_abstract_v<_ElementType>, + "ElementType must not be an abstract class type"); + static_assert(__mdspan::__is_extents<_Extents>, + "Extents must be a specialization of std::extents"); + static_assert(is_same_v<_ElementType, + typename _AccessorPolicy::element_type>); + + public: + using extents_type = _Extents; + using layout_type = _LayoutPolicy; + using accessor_type = _AccessorPolicy; + using mapping_type = typename layout_type::template mapping<extents_type>; + using element_type = _ElementType; + using value_type = remove_cv_t<element_type>; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using data_handle_type = typename accessor_type::data_handle_type; + using reference = typename accessor_type::reference; + + static constexpr rank_type + rank() noexcept { return extents_type::rank(); } + + static constexpr rank_type + rank_dynamic() noexcept { return extents_type::rank_dynamic(); } + + static constexpr size_t + static_extent(rank_type __r) noexcept + { return extents_type::static_extent(__r); } + + constexpr index_type + extent(rank_type __r) const noexcept { return extents().extent(__r); } + + constexpr + mdspan() + requires (rank_dynamic() > 0) + && is_default_constructible_v<data_handle_type> + && is_default_constructible_v<mapping_type> + && is_default_constructible_v<accessor_type> + : _M_accessor(), _M_mapping(), _M_handle() + { } + + constexpr + mdspan(const mdspan& __other) = default; + + constexpr + mdspan(mdspan&& __other) = default; + + template<__mdspan::__valid_index_type<index_type>... _OIndexTypes> + requires (sizeof...(_OIndexTypes) == rank() + || sizeof...(_OIndexTypes) == rank_dynamic()) + && is_constructible_v<mapping_type, extents_type> + && is_default_constructible_v<accessor_type> + constexpr explicit + mdspan(data_handle_type __handle, _OIndexTypes... __exts) + : _M_accessor(), + _M_mapping(_Extents(static_cast<index_type>(std::move(__exts))...)), + _M_handle(std::move(__handle)) + { } + + template<__mdspan::__valid_index_type<index_type> _OIndexType, + size_t _Nm> + requires (_Nm == rank() || _Nm == rank_dynamic()) + && is_constructible_v<mapping_type, extents_type> + && is_default_constructible_v<accessor_type> + constexpr explicit(_Nm != rank_dynamic()) + mdspan(data_handle_type __handle, span<_OIndexType, _Nm> __exts) + : _M_accessor(), _M_mapping(extents_type(__exts)), + _M_handle(std::move(__handle)) + { } + + template<__mdspan::__valid_index_type<index_type> _OIndexType, + size_t _Nm> + requires (_Nm == rank() || _Nm == rank_dynamic()) + && is_constructible_v<mapping_type, extents_type> + && is_default_constructible_v<accessor_type> + constexpr explicit(_Nm != rank_dynamic()) + mdspan(data_handle_type __handle, const array<_OIndexType, _Nm>& __exts) + : _M_accessor(), _M_mapping(extents_type(__exts)), + _M_handle(std::move(__handle)) + { } + + constexpr + mdspan(data_handle_type __handle, const extents_type& __exts) + requires is_constructible_v<mapping_type, const extents_type&> + && is_default_constructible_v<accessor_type> + : _M_accessor(), _M_mapping(__exts), _M_handle(std::move(__handle)) + { } + + constexpr + mdspan(data_handle_type __handle, const mapping_type& __mapping) + requires is_default_constructible_v<accessor_type> + : _M_accessor(), _M_mapping(__mapping), _M_handle(std::move(__handle)) + { } + + constexpr + mdspan(data_handle_type __handle, const mapping_type& __mapping, + const accessor_type& __accessor) + : _M_accessor(__accessor), _M_mapping(__mapping), + _M_handle(std::move(__handle)) + { } + + template<typename _OElementType, typename _OExtents, typename _OLayout, + typename _OAccessor> + requires is_constructible_v<mapping_type, + const typename _OLayout::mapping<_OExtents>&> + && is_constructible_v<accessor_type, const _OAccessor&> + constexpr explicit(!is_convertible_v< + const typename _OLayout::mapping<_OExtents>&, mapping_type> + || !is_convertible_v<const _OAccessor&, accessor_type>) + mdspan(const mdspan<_OElementType, _OExtents, _OLayout, _OAccessor>& + __other) + : _M_accessor(__other.accessor()), _M_mapping(__other.mapping()), + _M_handle(__other.data_handle()) + { + static_assert(is_constructible_v<data_handle_type, + const typename _OAccessor::data_handle_type&>); + static_assert(is_constructible_v<extents_type, _OExtents>); + } + + constexpr mdspan& + operator=(const mdspan& __other) = default; + + constexpr mdspan& + operator=(mdspan&& __other) = default; + + template<__mdspan::__valid_index_type<index_type>... _OIndexTypes> + requires (sizeof...(_OIndexTypes) == rank()) + constexpr reference + operator[](_OIndexTypes... __indices) const + { + auto __checked_call = [this](auto... __idxs) -> index_type + { + if constexpr (sizeof...(__idxs) > 0) + __glibcxx_assert(__mdspan::__is_multi_index(extents(), + span<const index_type, sizeof...(__idxs)>({__idxs...}))); + return _M_mapping(__idxs...); + }; + + auto __index = __checked_call( + static_cast<index_type>(std::move(__indices))...); + return _M_accessor.access(_M_handle, __index); + } + + template<__mdspan::__valid_index_type<index_type> _OIndexType> + constexpr reference + operator[](span<_OIndexType, rank()> __indices) const + { + auto __call = [&]<size_t... _Counts>(index_sequence<_Counts...>) + -> reference + { return (*this)[index_type(as_const(__indices[_Counts]))...]; }; + return __call(make_index_sequence<rank()>()); + } + + template<__mdspan::__valid_index_type<index_type> _OIndexType> + constexpr reference + operator[](const array<_OIndexType, rank()>& __indices) const + { return (*this)[span<const _OIndexType, rank()>(__indices)]; } + + constexpr size_type + size() const noexcept + { + __glibcxx_assert(cmp_less_equal(_M_mapping.required_span_size(), + numeric_limits<size_t>::max())); + return size_type(__mdspan::__size(extents())); + } + + [[nodiscard]] + constexpr bool + empty() const noexcept + { + return __mdspan::__empty(extents()); + } + + friend constexpr void + swap(mdspan& __x, mdspan& __y) noexcept + { + using std::swap; + swap(__x._M_mapping, __y._M_mapping); + swap(__x._M_accessor, __y._M_accessor); + swap(__x._M_handle, __y._M_handle); + } + + constexpr const extents_type& + extents() const noexcept { return _M_mapping.extents(); } + + constexpr const data_handle_type& + data_handle() const noexcept { return _M_handle; } + + constexpr const mapping_type& + mapping() const noexcept { return _M_mapping; } + + constexpr const accessor_type& + accessor() const noexcept { return _M_accessor; } + + static constexpr bool + is_always_unique() { return mapping_type::is_always_unique(); } + + static constexpr bool + is_always_exhaustive() { return mapping_type::is_always_exhaustive(); } + + static constexpr bool + is_always_strided() { return mapping_type::is_always_strided(); } + + constexpr bool + is_unique() const { return _M_mapping.is_unique(); } + + constexpr bool + is_exhaustive() const { return _M_mapping.is_exhaustive(); } + + constexpr bool + is_strided() const { return _M_mapping. is_strided(); } + + constexpr index_type + stride(rank_type __r) const { return _M_mapping.stride(__r); } + + private: + [[no_unique_address]] accessor_type _M_accessor; + [[no_unique_address]] mapping_type _M_mapping; + [[no_unique_address]] data_handle_type _M_handle; + }; + + template<typename _CArray> + requires is_array_v<_CArray> && (rank_v<_CArray> == 1) + mdspan(_CArray&) + -> mdspan<remove_all_extents_t<_CArray>, + extents<size_t, extent_v<_CArray, 0>>>; + + template<typename _Pointer> + requires is_pointer_v<remove_reference_t<_Pointer>> + mdspan(_Pointer&&) + -> mdspan<remove_pointer_t<remove_reference_t<_Pointer>>, extents<size_t>>; + + template<typename _ElementType, typename... _Integrals> + requires (is_convertible_v<_Integrals, size_t> && ...) + && (sizeof...(_Integrals) > 0) + explicit mdspan(_ElementType*, _Integrals...) + -> mdspan<_ElementType, + extents<size_t, __detail::__maybe_static_ext<_Integrals>...>>; + + template<typename _ElementType, typename _OIndexType, size_t _Nm> + mdspan(_ElementType*, span<_OIndexType, _Nm>) + -> mdspan<_ElementType, dextents<size_t, _Nm>>; + + template<typename _ElementType, typename _OIndexType, size_t _Nm> + mdspan(_ElementType*, const array<_OIndexType, _Nm>&) + -> mdspan<_ElementType, dextents<size_t, _Nm>>; + + template<typename _ElementType, typename _IndexType, size_t... _ExtentsPack> + mdspan(_ElementType*, const extents<_IndexType, _ExtentsPack...>&) + -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>; + + template<typename _ElementType, typename _MappingType> + mdspan(_ElementType*, const _MappingType&) + -> mdspan<_ElementType, typename _MappingType::extents_type, + typename _MappingType::layout_type>; + + template<typename _MappingType, typename _AccessorType> + mdspan(const typename _AccessorType::data_handle_type&, const _MappingType&, + const _AccessorType&) + -> mdspan<typename _AccessorType::element_type, + typename _MappingType::extents_type, + typename _MappingType::layout_type, _AccessorType>; + _GLIBCXX_END_NAMESPACE_VERSION } #endif diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue index 9052589..1b76088 100644 --- a/libstdc++-v3/include/std/queue +++ b/libstdc++-v3/include/std/queue @@ -105,7 +105,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_f.format(__a.c, __fc); } private: - // Standard uses formatter<ref_view<_Container>, _CharT>. + // Standard uses formatter<ref_view<_Container>, _CharT>, but range_formatter + // provides same behavior. + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3881. Incorrect formatting of container adapters backed by std::string range_formatter<_Tp, _CharT> _M_f; }; @@ -136,7 +139,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_f.format(__a.c, __fc); } private: - // Standard uses formatter<ref_view<_Container>, _CharT>. + // Standard uses formatter<ref_view<_Container>, _CharT>, but range_formatter + // provides same behavior. + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3881. Incorrect formatting of container adapters backed by std::string range_formatter<_Tp, _CharT> _M_f; }; 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++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc index 3533b5e..c6f6ef7 100644 --- a/libstdc++-v3/src/c++11/debug.cc +++ b/libstdc++-v3/src/c++11/debug.cc @@ -54,7 +54,7 @@ namespace * in order to limit contention without breaking current library binary * compatibility. */ __gnu_cxx::__mutex& - get_safe_base_mutex(void* address) + get_safe_base_mutex(const void* address) { // Use arbitrarily __gnu_debug::vector<int> as the container giving // alignment of debug containers. @@ -70,9 +70,9 @@ namespace #pragma GCC diagnostic warning "-Wabi=6" void - swap_its(__gnu_debug::_Safe_sequence_base& __lhs, + swap_its(const __gnu_debug::_Safe_sequence_base& __lhs, __gnu_debug::_Safe_iterator_base*& __lhs_its, - __gnu_debug::_Safe_sequence_base& __rhs, + const __gnu_debug::_Safe_sequence_base& __rhs, __gnu_debug::_Safe_iterator_base*& __rhs_its) { swap(__lhs_its, __rhs_its); @@ -84,8 +84,8 @@ namespace } void - swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs, - __gnu_debug::_Safe_sequence_base& __rhs) + swap_seq_single(const __gnu_debug::_Safe_sequence_base& __lhs, + const __gnu_debug::_Safe_sequence_base& __rhs) { swap(__lhs._M_version, __rhs._M_version); swap_its(__lhs, __lhs._M_iterators, @@ -118,17 +118,17 @@ namespace void swap_seq(__gnu_cxx::__mutex& lhs_mutex, - __gnu_debug::_Safe_sequence_base& lhs, + const __gnu_debug::_Safe_sequence_base& lhs, __gnu_cxx::__mutex& rhs_mutex, - __gnu_debug::_Safe_sequence_base& rhs) + const __gnu_debug::_Safe_sequence_base& rhs) { lock_and_run(lhs_mutex, rhs_mutex, [&lhs, &rhs]() { swap_seq_single(lhs, rhs); }); } void - swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs, - __gnu_debug::_Safe_unordered_container_base& __rhs) + swap_ucont_single(const __gnu_debug::_Safe_unordered_container_base& __lhs, + const __gnu_debug::_Safe_unordered_container_base& __rhs) { swap_seq_single(__lhs, __rhs); swap_its(__lhs, __lhs._M_local_iterators, @@ -139,9 +139,9 @@ namespace void swap_ucont(__gnu_cxx::__mutex& lhs_mutex, - __gnu_debug::_Safe_unordered_container_base& lhs, + const __gnu_debug::_Safe_unordered_container_base& lhs, __gnu_cxx::__mutex& rhs_mutex, - __gnu_debug::_Safe_unordered_container_base& rhs) + const __gnu_debug::_Safe_unordered_container_base& rhs) { lock_and_run(lhs_mutex, rhs_mutex, [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); }); @@ -158,8 +158,8 @@ namespace } } - void* - acquire_sequence_ptr_for_lock(__gnu_debug::_Safe_sequence_base*& seq) + const void* + acquire_sequence_ptr_for_lock(__gnu_debug::_Safe_sequence_base const*& seq) { #ifdef __GTHREADS if (!__gnu_cxx::__is_single_threaded()) @@ -169,7 +169,7 @@ namespace } void - reset_sequence_ptr(__gnu_debug::_Safe_sequence_base*& seq) + reset_sequence_ptr(__gnu_debug::_Safe_sequence_base const*& seq) { #ifdef __GTHREADS if (!__gnu_cxx::__is_single_threaded()) @@ -327,7 +327,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_detach_all() + _M_detach_all() const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); detach_all(_M_iterators); @@ -339,7 +339,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_detach_singular() + _M_detach_singular() const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); for (_Safe_iterator_base* __iter = _M_iterators; __iter;) @@ -361,7 +361,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_revalidate_singular() + _M_revalidate_singular() const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); for (_Safe_iterator_base* __iter = _M_iterators; __iter; @@ -375,17 +375,59 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_swap(_Safe_sequence_base& __x) noexcept + _M_swap(const _Safe_sequence_base& __x) const noexcept { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } __gnu_cxx::__mutex& _Safe_sequence_base:: - _M_get_mutex() noexcept + _M_get_mutex() const noexcept { return get_safe_base_mutex(this); } +#if !_GLIBCXX_INLINE_VERSION + void + _Safe_sequence_base:: + _M_detach_all() + { + const _Safe_sequence_base* __this = this; + __this->_M_detach_all(); + } + + void + _Safe_sequence_base:: + _M_detach_singular() + { + const _Safe_sequence_base* __this = this; + __this->_M_detach_singular(); + } + + void + _Safe_sequence_base:: + _M_revalidate_singular() + { + const _Safe_sequence_base* __this = this; + __this->_M_revalidate_singular(); + } + void _Safe_sequence_base:: - _M_attach(_Safe_iterator_base* __it, bool __constant) + _M_swap(_Safe_sequence_base& __x) noexcept + { + const _Safe_sequence_base* __this = this; + __this->_M_swap(__x); + } + + __gnu_cxx::__mutex& + _Safe_sequence_base:: + _M_get_mutex() noexcept + { + const _Safe_sequence_base* __this = this; + return __this->_M_get_mutex(); + } +#endif + + void + _Safe_sequence_base:: + _M_attach(_Safe_iterator_base* __it, bool __constant) const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); _M_attach_single(__it, __constant); @@ -393,7 +435,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_attach_single(_Safe_iterator_base* __it, bool __constant) noexcept + _M_attach_single(_Safe_iterator_base* __it, bool __constant) const noexcept { _Safe_iterator_base*& __its = __constant ? _M_const_iterators : _M_iterators; @@ -405,7 +447,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_detach(_Safe_iterator_base* __it) + _M_detach(_Safe_iterator_base* __it) const { // Remove __it from this sequence's list __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); @@ -414,7 +456,7 @@ namespace __gnu_debug void _Safe_sequence_base:: - _M_detach_single(_Safe_iterator_base* __it) noexcept + _M_detach_single(_Safe_iterator_base* __it) const noexcept { // Remove __it from this sequence's list __it->_M_unlink(); @@ -426,7 +468,7 @@ namespace __gnu_debug void _Safe_iterator_base:: - _M_attach(_Safe_sequence_base* __seq, bool __constant) + _M_attach(const _Safe_sequence_base* __seq, bool __constant) { _M_detach(); @@ -443,7 +485,7 @@ namespace __gnu_debug void _Safe_iterator_base:: - _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept + _M_attach_single(const _Safe_sequence_base* __seq, bool __constant) noexcept { _M_detach_single(); @@ -514,14 +556,27 @@ namespace __gnu_debug _M_get_mutex() noexcept { return _M_sequence->_M_get_mutex(); } - _Safe_unordered_container_base* - _Safe_local_iterator_base:: - _M_get_container() const noexcept - { return static_cast<_Safe_unordered_container_base*>(_M_sequence); } +#if !_GLIBCXX_INLINE_VERSION + void + _Safe_iterator_base:: + _M_attach(_Safe_sequence_base* __seq, bool __constant) + { + const _Safe_sequence_base* __cseq = __seq; + _M_attach(__cseq, __constant); + } + + void + _Safe_iterator_base:: + _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept + { + const _Safe_sequence_base* __cseq = __seq; + _M_attach_single(__cseq, __constant); + } +#endif void _Safe_local_iterator_base:: - _M_attach(_Safe_sequence_base* __cont, bool __constant) + _M_attach(const _Safe_unordered_container_base* __cont, bool __constant) { _M_detach(); @@ -530,7 +585,7 @@ namespace __gnu_debug { _M_sequence = __cont; _M_version = _M_sequence->_M_version; - _M_get_container()->_M_attach_local(this, __constant); + _M_safe_container()->_M_attach_local(this, __constant); } else _M_version = 0; @@ -538,7 +593,8 @@ namespace __gnu_debug void _Safe_local_iterator_base:: - _M_attach_single(_Safe_sequence_base* __cont, bool __constant) noexcept + _M_attach_single(const _Safe_unordered_container_base* __cont, + bool __constant) noexcept { _M_detach_single(); @@ -547,7 +603,7 @@ namespace __gnu_debug { _M_sequence = __cont; _M_version = _M_sequence->_M_version; - _M_get_container()->_M_attach_local_single(this, __constant); + _M_safe_container()->_M_attach_local_single(this, __constant); } else _M_version = 0; @@ -570,14 +626,34 @@ namespace __gnu_debug { if (_M_sequence) { - _M_get_container()->_M_detach_local_single(this); + _M_safe_container()->_M_detach_local_single(this); _M_reset(); } } +#if !_GLIBCXX_INLINE_VERSION + void + _Safe_local_iterator_base:: + _M_attach(_Safe_sequence_base* __seq, bool __constant) + { + const _Safe_unordered_container_base* __cont + = static_cast<_Safe_unordered_container_base*>(__seq); + _M_attach(__cont, __constant); + } + + void + _Safe_local_iterator_base:: + _M_attach_single(_Safe_sequence_base* __seq, bool __constant) noexcept + { + const _Safe_unordered_container_base* __cont + = static_cast<_Safe_unordered_container_base*>(__seq); + _M_attach_single(__cont, __constant); + } +#endif + void _Safe_unordered_container_base:: - _M_detach_all() + _M_detach_all() const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); detach_all(_M_iterators); @@ -595,12 +671,12 @@ namespace __gnu_debug void _Safe_unordered_container_base:: - _M_swap(_Safe_unordered_container_base& __x) noexcept + _M_swap(const _Safe_unordered_container_base& __x) const noexcept { swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } void _Safe_unordered_container_base:: - _M_attach_local(_Safe_iterator_base* __it, bool __constant) + _M_attach_local(_Safe_iterator_base* __it, bool __constant) const { __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); _M_attach_local_single(__it, __constant); @@ -608,7 +684,7 @@ namespace __gnu_debug void _Safe_unordered_container_base:: - _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) noexcept + _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) const noexcept { _Safe_iterator_base*& __its = __constant ? _M_const_local_iterators : _M_local_iterators; @@ -620,7 +696,7 @@ namespace __gnu_debug void _Safe_unordered_container_base:: - _M_detach_local(_Safe_iterator_base* __it) + _M_detach_local(_Safe_iterator_base* __it) const { // Remove __it from this container's list __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); @@ -629,7 +705,7 @@ namespace __gnu_debug void _Safe_unordered_container_base:: - _M_detach_local_single(_Safe_iterator_base* __it) noexcept + _M_detach_local_single(_Safe_iterator_base* __it) const noexcept { // Remove __it from this container's list __it->_M_unlink(); @@ -638,6 +714,24 @@ namespace __gnu_debug if (_M_local_iterators == __it) _M_local_iterators = __it->_M_next; } + +#if !_GLIBCXX_INLINE_VERSION + void + _Safe_unordered_container_base:: + _M_detach_all() + { + const _Safe_unordered_container_base* __this = this; + __this->_M_detach_all(); + } + + void + _Safe_unordered_container_base:: + _M_swap(_Safe_unordered_container_base& __x) noexcept + { + const _Safe_unordered_container_base* __this = this; + __this->_M_swap(__x); + } +#endif } namespace diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc index fac4c78..fddfe2c 100644 --- a/libstdc++-v3/src/c++17/memory_resource.cc +++ b/libstdc++-v3/src/c++17/memory_resource.cc @@ -1242,12 +1242,30 @@ namespace pmr return pools; } + 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(); + } + // Override for memory_resource::do_allocate void* 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 +1312,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 +1471,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 +1488,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/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in index 86e6d88..dd05a83 100644 --- a/libstdc++-v3/src/c++23/std.cc.in +++ b/libstdc++-v3/src/c++23/std.cc.in @@ -1846,7 +1846,8 @@ export namespace std using std::layout_right; using std::layout_stride; using std::default_accessor; - // FIXME layout_left_padded, layout_right_padded, aligned_accessor and mdspan + using std::mdspan; + // FIXME layout_left_padded, layout_right_padded, aligned_accessor, mdsubspan } #endif 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..6d7434f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/synchronized_pool_resource/118681.cc @@ -0,0 +1,5 @@ +// { dg-do run { target c++17 } } +// 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/23_containers/mdspan/class_mandate_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc new file mode 100644 index 0000000..de19b6d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/class_mandate_neg.cc @@ -0,0 +1,41 @@ +// { dg-do compile { target c++23 } } +#include<mdspan> + +#include <cstdint> +#include "layout_like.h" + +struct ExtentsLike +{ + using index_type = int; + using size_type = unsigned int; + using rank_type = size_t; + + static constexpr size_t rank() { return 1; } + static constexpr size_t rank_dynamic() { return 0; } +}; + +constexpr bool +test_custom_extents_type() +{ + std::mdspan<double, ExtentsLike> md1; // { dg-error "required from here" } + return true; +} +static_assert(test_custom_extents_type()); + +constexpr bool +test_element_type_mismatch() +{ + using E = std::extents<int, 1>; + using L = std::layout_right; + using A = std::default_accessor<double>; + + [[maybe_unused]] std::mdspan<float, E, L, A> md2; // { dg-error "required from here" } + return true; +}; +static_assert(test_element_type_mismatch()); + +// { dg-prune-output "Extents must be a specialization of std::extents" } +// { dg-prune-output "no type named '_S_storage'" } +// { dg-prune-output "non-constant condition" } +// { dg-prune-output "static assertion failed" } +// { dg-prune-output "__glibcxx_assert" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc index f9c1c01..67d18fe 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc @@ -7,6 +7,8 @@ std::extents<uint8_t, size_t(1) << 9> e1; // { dg-error "from here" } std::extents<char, 1> e2; // { dg-error "from here" } std::extents<bool, 1> e3; // { dg-error "from here" } std::extents<double, 1> e4; // { dg-error "from here" } + // { dg-prune-output "dynamic or representable as IndexType" } // { dg-prune-output "signed or unsigned integer" } // { dg-prune-output "invalid use of incomplete type" } +// { dg-prune-output "non-constant condition for static assertion" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc index 2907ad1..404755b 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc @@ -2,38 +2,13 @@ #include <mdspan> #include <testsuite_hooks.h> +#include "int_like.h" // Test construction from a custom integer-like object, that has // no copy/move ctor or copy/move assignment operator. constexpr size_t dyn = std::dynamic_extent; -class IntLike -{ -public: - explicit - IntLike(int i) - : _M_i(i) - { } - - IntLike() = delete; - IntLike(const IntLike&) = delete; - IntLike(IntLike&&) = delete; - - const IntLike& - operator=(const IntLike&) = delete; - - const IntLike& - operator=(IntLike&&) = delete; - - constexpr - operator int() const noexcept - { return _M_i; } - -private: - int _M_i; -}; - static_assert(std::is_convertible_v<IntLike, int>); static_assert(std::is_nothrow_constructible_v<int, IntLike>); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc new file mode 100644 index 0000000..b35e531 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc @@ -0,0 +1,35 @@ +// { dg-do compile { target c++23 } } +#include<mdspan> + +#include <cstdint> + +constexpr size_t dyn = std::dynamic_extent; + +constexpr bool +test_dyn2sta_extents_mismatch_00() +{ + auto e0 = std::extents<int, dyn>{1}; + [[maybe_unused]] auto e1 = std::extents<int, 2>{e0}; // { dg-error "expansion of" } + return true; +} +static_assert(test_dyn2sta_extents_mismatch_00()); // { dg-error "expansion of" } + +constexpr bool +test_dyn2sta_extents_mismatch_01() +{ + [[maybe_unused]] auto e = std::extents<int, 1, dyn>{2, 2}; // { dg-error "expansion of" } + return true; +} +static_assert(test_dyn2sta_extents_mismatch_01()); // { dg-error "expansion of" } + +constexpr bool +test_dyn2sta_extents_mismatch_02() +{ + std::array<int, 2> exts{2, 2}; + [[maybe_unused]] auto e = std::extents<int, 1, dyn>{exts}; // { dg-error "expansion of" } + return true; +} +static_assert(test_dyn2sta_extents_mismatch_02()); // { dg-error "expansion of" } + +// { dg-prune-output "non-constant condition for static assertion" } +// { dg-prune-output "__glibcxx_assert" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h b/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h new file mode 100644 index 0000000..f39f4cc --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/int_like.h @@ -0,0 +1,30 @@ +#ifndef TEST_MDSPAN_INT_LIKE_H +#define TEST_MDSPAN_INT_LIKE_H + +class IntLike +{ +public: + explicit + IntLike(int i) + : _M_i(i) + { } + + IntLike() = delete; + IntLike(const IntLike&) = delete; + IntLike(IntLike&&) = delete; + + const IntLike& + operator=(const IntLike&) = delete; + + const IntLike& + operator=(IntLike&&) = delete; + + constexpr + operator int() const noexcept + { return _M_i; } + +private: + int _M_i; +}; + +#endif // TEST_MDSPAN_INT_LIKE_H 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/layout_like.h b/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h new file mode 100644 index 0000000..6a0f8ca --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layout_like.h @@ -0,0 +1,83 @@ +#ifndef TEST_MDSPAN_LAYOUT_LIKE_H +#define TEST_MDSPAN_LAYOUT_LIKE_H 1 + +struct LayoutLike +{ + template<typename Extents> + class mapping + { + public: + using extents_type = Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = LayoutLike; + + constexpr + mapping() noexcept = default; + + constexpr + mapping(Extents exts) + : m_exts(exts) + { } + + constexpr const extents_type& + extents() const noexcept { return m_exts; } + + constexpr index_type + required_span_size() const noexcept + { + for (size_t i = 0; i < extents_type::rank(); ++i) + if (m_exts.extent(i) == 0) + return 0; + return 1; + } + + template<typename... Indices> + requires (sizeof...(Indices) == extents_type::rank()) + constexpr index_type + operator()(Indices...) const noexcept + { return 0; } + + static constexpr index_type + stride(rank_type) noexcept + { return 0; } + + static constexpr bool + is_always_unique() noexcept + { return false; } + + static constexpr bool + is_always_exhaustive() noexcept + { return true; } + + static constexpr bool + is_always_strided() noexcept + { return true; } + + constexpr bool + is_unique() noexcept + { + if (required_span_size() == 0) + return true; + + for (size_t i = 0; i < extents_type::rank(); ++i) + if (m_exts.extent(i) > 1) + return false; + return true; + } + + static constexpr bool + is_exhaustive() noexcept + { return true; } + + static constexpr bool + is_strided() noexcept + { return true; } + + private: + Extents m_exts; + }; +}; + +#endif diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc new file mode 100644 index 0000000..fb8ff01 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc @@ -0,0 +1,30 @@ +// { dg-do compile { target c++23 } } +// { dg-require-debug-mode "" } +#include<mdspan> + +template<typename Layout> + constexpr bool + test_out_of_bounds_1d() + { + auto m = typename Layout::mapping<std::extents<int, 0>>{}; + (void) m(0); // { dg-error "expansion of" } + return true; + } +static_assert(test_out_of_bounds_1d<std::layout_left>()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_1d<std::layout_right>()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_1d<std::layout_stride>()); // { dg-error "expansion of" } + +template<typename Layout> + constexpr bool + test_out_of_bounds_3d() + { + auto m = typename Layout::mapping<std::extents<int, 3, 5, 7>>{}; + (void) m(2, 5, 5); // { dg-error "expansion of" } + return true; + } +static_assert(test_out_of_bounds_3d<std::layout_left>()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_3d<std::layout_right>()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_3d<std::layout_stride>()); // { dg-error "expansion of" } + +// { dg-prune-output "non-constant condition for static assertion" } +// { dg-prune-output "__glibcxx_assert" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc new file mode 100644 index 0000000..a650fb1 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/mdspan.cc @@ -0,0 +1,668 @@ +// { dg-do run { target c++23 } } +#include <mdspan> + +#include <testsuite_hooks.h> +#include "extents/int_like.h" +#include "layout_like.h" + +constexpr auto dyn = std::dynamic_extent; + +template<typename MDSpan, typename T, typename E, typename L = std::layout_right, + typename A = std::default_accessor<T>> + constexpr void + assert_typedefs() + { + static_assert(std::same_as<typename MDSpan::extents_type, E>); + static_assert(std::same_as<typename MDSpan::layout_type, L>); + static_assert(std::same_as<typename MDSpan::accessor_type, A>); + static_assert(std::same_as<typename MDSpan::mapping_type, + typename L::mapping<E>>); + static_assert(std::same_as<typename MDSpan::element_type, T>); + static_assert(std::same_as<typename MDSpan::value_type, + std::remove_const_t<T>>); + static_assert(std::same_as<typename MDSpan::index_type, + typename E::index_type>); + static_assert(std::same_as<typename MDSpan::size_type, + typename E::size_type>); + static_assert(std::same_as<typename MDSpan::rank_type, + typename E::rank_type>); + static_assert(std::same_as<typename MDSpan::data_handle_type, + typename A::data_handle_type>); + static_assert(std::same_as<typename MDSpan::reference, + typename A::reference>); + } + +template<typename T, typename E, typename L, template<typename U> typename A> + constexpr void + test_typedefs() + { assert_typedefs<std::mdspan<T, E, L, A<T>>, T, E, L, A<T>>(); } + +constexpr void +test_typedefs_all() +{ + using E = std::extents<int, 1, 2>; + using L = std::layout_left; + + test_typedefs<double, E, L, std::default_accessor>(); + test_typedefs<const double, E, L, std::default_accessor>(); +} + +template<typename MDSpan> + constexpr void + test_rank() + { + using Extents = typename MDSpan::extents_type; + static_assert(MDSpan::rank() == Extents::rank()); + static_assert(MDSpan::rank_dynamic() == Extents::rank_dynamic()); + } + +constexpr bool +test_rank_all() +{ + test_rank<std::mdspan<double, std::extents<int>>>(); + test_rank<std::mdspan<double, std::extents<int, 1>>>(); + test_rank<std::mdspan<double, std::extents<int, dyn>>>(); + return true; +} + +template<typename Extents> + constexpr void + test_extent(Extents exts) + { + double data = 1.0; + auto md = std::mdspan(&data, exts); + using MDSpan = decltype(md); + + for(size_t i = 0; i < MDSpan::rank(); ++i) + { + VERIFY(MDSpan::static_extent(i) == Extents::static_extent(i)); + VERIFY(md.extent(i) == exts.extent(i)); + } + } + +constexpr bool +test_extent_all() +{ + // For rank == 0, check existence of the methods without calling them. + test_extent(std::extents<int>{}); + test_extent(std::extents<int, 0>{}); + test_extent(std::extents<int, dyn>{}); + return true; +} + +template<typename MDSpan> + constexpr void + test_class_properties() + { + static_assert(std::copyable<MDSpan>); + static_assert(std::is_nothrow_move_constructible_v<MDSpan>); + static_assert(std::is_nothrow_move_assignable_v<MDSpan>); + static_assert(std::is_nothrow_swappable_v<MDSpan>); + constexpr bool trivially_copyable = + std::is_trivially_copyable_v<typename MDSpan::accessor_type> + && std::is_trivially_copyable_v<typename MDSpan::mapping_type> + && std::is_trivially_copyable_v<typename MDSpan::data_handle_type>; + static_assert(std::is_trivially_copyable_v<MDSpan> == trivially_copyable); + } + +constexpr bool +test_class_properties_all() +{ + test_class_properties<std::mdspan<double, std::extents<int>>>(); + test_class_properties<std::mdspan<double, std::extents<int, 1>>>(); + test_class_properties<std::mdspan<double, std::extents<int, dyn>>>(); + return true; +} + +constexpr bool +test_default_ctor() +{ + static_assert(!std::is_default_constructible_v<std::mdspan<double, + std::extents<int>>>); + static_assert(!std::is_default_constructible_v<std::mdspan<double, + std::extents<int, 1>>>); + static_assert(std::is_default_constructible_v<std::mdspan<double, + std::extents<int, dyn>>>); + + std::mdspan<double, std::extents<int, dyn>> md; + VERIFY(md.data_handle() == nullptr); + VERIFY(md.empty()); + return true; +} + +constexpr bool +test_from_other() +{ + using Extents = std::extents<int, 3, 5, 7>; + auto exts = Extents{}; + + auto mapping = std::layout_right::mapping(exts); + constexpr size_t n = mapping.required_span_size(); + std::array<double, n> storage{}; + + auto md1 = std::mdspan(storage.data(), exts); + auto md2 = std::mdspan<double, std::dextents<int, 3>>(md1); + + VERIFY(md1.data_handle() == md2.data_handle()); + VERIFY(md1.size() == md2.size()); + + static_assert(!std::is_convertible_v< + std::mdspan<double, std::extents<unsigned int, 2>>, + std::mdspan<double, std::extents<int, 2>>>); + + static_assert(std::is_convertible_v< + std::mdspan<double, std::extents<int, 2>>, + std::mdspan<const double, std::extents<int, 2>>>); + + static_assert(!std::is_constructible_v< + std::mdspan<double, std::extents<int, 2>>, + std::mdspan<const double, std::extents<int, 2>>>); + + return true; +} + +template<typename T, typename E, typename L = std::layout_right, + typename A = std::default_accessor<T>> + constexpr void + assert_deduced_typedefs(auto md) + { assert_typedefs<decltype(md), T, E, L, A>(); } + +constexpr bool +test_from_carray() +{ + constexpr size_t n = 5; + double data[n] = {1.1, 2.2, 3.3, 4.4, 5.5}; + + auto md = std::mdspan(data); + assert_deduced_typedefs<double, std::extents<size_t, n>>(md); + VERIFY(md.rank() == 1); + VERIFY(md.rank_dynamic() == 0); + VERIFY(md[2] == data[2]); + return true; +} + +constexpr bool +test_from_pointer() +{ + double value = 12.3; + auto md = std::mdspan(&value); + assert_deduced_typedefs<double, std::extents<size_t>>(md); + VERIFY(md.rank() == 0); + VERIFY(md.rank_dynamic() == 0); + VERIFY(md[] == value); + return true; +} + +constexpr bool +test_from_pointer_and_shape() +{ + constexpr size_t n = 6; + std::array<double, n> data{1.1, 2.2, 3.3, 4.4, 5.5, 6.6}; + std::array<int, 2> shape{2, 3}; + std::span<const int, 2> shape_view(shape); + + auto verify = [&data](auto md) + { + assert_deduced_typedefs<double, std::dextents<size_t, 2>>(md); + VERIFY(md.rank() == 2); + VERIFY(md.rank_dynamic() == 2); + VERIFY((md[0, 0]) == data[0]); + VERIFY((md[0, 1]) == data[1]); + VERIFY((md[1, 0]) == data[3]); + }; + + verify(std::mdspan(data.data(), shape[0], shape[1])); + verify(std::mdspan(data.data(), shape)); + verify(std::mdspan(data.data(), shape_view)); + + std::mdspan<double, std::dextents<size_t, 2>> md1 = {data.data(), shape}; + verify(md1); + + std::mdspan<double, std::dextents<size_t, 2>> md2 = {data.data(), shape_view}; + verify(md2); + + static_assert(std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*>); + static_assert(!std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*, int>); + static_assert(std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*, int, int>); + static_assert(std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*, std::span<int, 0>>); + static_assert(std::is_constructible_v< + std::mdspan<float, std::extents<int, 3, 5>>, float*, std::span<int, 2>>); + static_assert(!std::is_convertible_v< + float*, std::mdspan<float, std::extents<int, 3, 5>>>); + + static_assert(std::is_constructible_v< + std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 2>>); + static_assert(!std::is_constructible_v< + std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 1>>); + static_assert(!std::is_constructible_v< + std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, 3>>); + static_assert(!std::is_constructible_v< + std::mdspan<float, std::dextents<int, 2>>, float*, std::span<int, dyn>>); + return true; +} + +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; + std::array<double, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + auto exts = Extents{}; + auto md = std::mdspan(storage.data(), exts); + + assert_deduced_typedefs<double, Extents>(md); + VERIFY(md.data_handle() == storage.data()); + VERIFY(md.extents() == exts); + return true; +} + +constexpr bool +test_from_mapping() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + + auto exts = Extents{}; + auto m = std::layout_left::mapping(exts); + auto md = std::mdspan(storage.data(), m); + + assert_deduced_typedefs<double, Extents, std::layout_left>(md); + VERIFY(md.data_handle() == storage.data()); + VERIFY(md.mapping() == m); + return true; +} + +constexpr bool +test_from_accessor() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + + auto exts = Extents{}; + auto m = std::layout_left::mapping(exts); + auto a = std::default_accessor<double>{}; + auto md = std::mdspan(storage.data(), m, a); + + assert_deduced_typedefs<double, Extents, std::layout_left>(md); + VERIFY(md.data_handle() == storage.data()); + VERIFY(md.mapping() == m); + return true; +} + +void +test_from_int_like() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + + auto verify = [&](auto md) + { + VERIFY(md.data_handle() == storage.data()); + VERIFY(md.extent(0) == 3); + VERIFY(md.extent(1) == 5); + VERIFY(md.extent(2) == 7); + + VERIFY((md[IntLike(0), 0, IntLike(0)]) == 0.0); + auto zero = std::array{IntLike(0), IntLike(0), IntLike(0)}; + auto zero_view = std::span<IntLike, 3>{zero}; + VERIFY((md[zero]) == 0.0); + VERIFY((md[zero_view]) == 0.0); + }; + + auto shape = std::array{IntLike(3), IntLike(5), IntLike(7)}; + auto shape_view = std::span<IntLike, 3>{shape}; + verify(std::mdspan(storage.data(), IntLike(3), 5, IntLike(7))); + verify(std::mdspan(storage.data(), shape)); + verify(std::mdspan(storage.data(), shape_view)); +} + +template<typename T, bool NothrowConstructible = true, + bool NothrowAssignable = true> + class OpaqueAccessor + { + struct Handle + { + constexpr + Handle(T * other) + : ptr(other) + { } + + constexpr + Handle(const Handle&) noexcept(NothrowConstructible) = default; + + constexpr + Handle(Handle&&) noexcept(NothrowConstructible) = default; + + constexpr Handle& + operator=(const Handle&) noexcept(NothrowAssignable) = default; + + constexpr Handle& + operator=(Handle&&) noexcept(NothrowAssignable) = default; + + T * ptr; + }; + + public: + using element_type = T; + using reference = T&; + using data_handle_type = Handle; + using offset_policy = OpaqueAccessor; + + reference + access(data_handle_type p, size_t i) const + { + ++access_count; + return p.ptr[i]; + } + + typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const + { + ++offset_count; + return typename offset_policy::data_handle_type{(void*)(p.ptr + i)}; + } + + mutable size_t access_count = 0; + mutable size_t offset_count = 0; + }; + +void +test_from_opaque_accessor() +{ + constexpr size_t n = 3*5*7; + std::array<double, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + + auto exts = Extents{}; + auto m = std::layout_left::mapping(exts); + auto a = OpaqueAccessor<double>{}; + auto handle = OpaqueAccessor<double>::data_handle_type{storage.data()}; + auto md = std::mdspan(handle, m, a); + + using MDSpan = decltype(md); + static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>); + + VERIFY((md[0, 0, 0]) == 0.0); + VERIFY(md.accessor().access_count == 1); + + VERIFY((md[2, 4, 6]) == 0.0); + VERIFY(md.accessor().access_count == 2); +} + +template<typename T, typename Base> + class BaseClassAccessor + { + public: + using element_type = T; + using reference = Base&; + using data_handle_type = T*; + using offset_policy = BaseClassAccessor; + + static_assert(std::common_reference_with<reference&&, element_type&>); + + reference + access(data_handle_type p, size_t i) const + { return p[i]; } + + typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const + { return typename offset_policy::data_handle_type{p + i}; } + }; + +struct Base +{ + double value = 1.0; +}; + +struct Derived : Base +{ + double value = 2.0; +}; + +void +test_from_base_class_accessor() +{ + constexpr size_t n = 3*5*7; + std::array<Derived, n> storage{}; + using Extents = std::extents<int, 3, 5, 7>; + + auto exts = Extents{}; + auto m = std::layout_left::mapping(exts); + auto a = BaseClassAccessor<Derived, Base>{}; + auto md = std::mdspan(storage.data(), m, a); + + using MDSpan = decltype(md); + static_assert(std::same_as<MDSpan::accessor_type, decltype(a)>); + static_assert(std::same_as<decltype(md[0, 0, 0]), Base&>); + VERIFY((md[0, 0, 0].value) == 1.0); + VERIFY((md[2, 4, 6].value) == 1.0); +} + +constexpr bool +test_from_mapping_like() +{ + double data = 1.1; + auto m = LayoutLike::mapping<std::extents<int, 1, 2, 3>>{}; + auto md = std::mdspan(&data, m); + VERIFY((md[0, 0, 0]) == data); + VERIFY((md[0, 1, 2]) == data); + return true; +} + +template<typename MDSpan> + constexpr void + test_empty(MDSpan md) + { + VERIFY(md.empty() == (md.size() == 0)); + } + +constexpr bool +test_empty_all() +{ + test_empty(std::mdspan<double, std::extents<int, dyn>>{}); + return true; +} + +constexpr bool +test_access() +{ + using Extents = std::extents<int, 3, 5, 7>; + auto exts = Extents{}; + + auto mapping = std::layout_left::mapping(exts); + constexpr size_t n = mapping.required_span_size(); + std::array<double, n> storage{}; + + auto md = std::mdspan(storage.data(), mapping); + static_assert(std::__mdspan::__mapping_alike<decltype(md)>); + + for(int i = 0; i < exts.extent(0); ++i) + for(int j = 0; j < exts.extent(1); ++j) + for(int k = 0; k < exts.extent(2); ++k) + { + std::array<int, 3> ijk{i, j, k}; + storage[mapping(i, j, k)] = 1.0; + VERIFY((md[i, j, k]) == 1.0); + VERIFY((md[ijk]) == 1.0); + VERIFY((md[std::span(ijk)]) == 1.0); + storage[mapping(i, j, k)] = 0.0; + } + return true; +} + +constexpr bool +test_swap() +{ + using Extents = std::dextents<int, 2>; + auto e1 = Extents{3, 5}; + auto e2 = Extents{7, 11}; + + std::array<double, 3*5> s1{}; + std::array<double, 7*11> s2{}; + + auto md1 = std::mdspan(s1.data(), e1); + auto md2 = std::mdspan(s2.data(), e2); + + std::swap(md1, md2); + + VERIFY(md1.data_handle() == s2.data()); + VERIFY(md2.data_handle() == s1.data()); + + VERIFY(md1.size() == s2.size()); + VERIFY(md2.size() == s1.size()); + return true; +} + +namespace adl +{ + template<typename T> + struct SwappableAccessor + { + using element_type = T; + using reference = T&; + using data_handle_type = T*; + using offset_policy = SwappableAccessor; + + reference + access(data_handle_type p, size_t i) const + { return p[i]; } + + typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const + { return p + i; } + + friend void + swap(SwappableAccessor&, SwappableAccessor&) + { ++swap_count; } + + static inline size_t swap_count = 0; + }; +} + +void +test_swap_adl() +{ + using Extents = std::extents<int, dyn>; + using Layout = std::layout_left; + using Accessor = adl::SwappableAccessor<double>; + Accessor::swap_count = 0; + + std::mdspan<double, Extents, Layout, Accessor> m1, m2; + swap(m1, m2); + VERIFY(Accessor::swap_count == 1); +} + +template<bool Constructible, bool Assignable> +constexpr void +test_nothrow_movable() +{ + using Layout = std::layout_left; + using Extents = std::dextents<int, 3>; + using Accessor = OpaqueAccessor<int, Constructible, Assignable>; + using Handle = Accessor::data_handle_type; + static_assert(std::is_nothrow_move_assignable_v<Accessor>); + static_assert(std::is_nothrow_move_constructible_v<Accessor>); + static_assert(std::is_nothrow_move_assignable_v<Handle> == Assignable); + static_assert(std::is_nothrow_move_constructible_v<Handle> == Constructible); + + using MDSpan = std::mdspan<int, Extents, Layout, Accessor>; + static_assert(std::is_nothrow_move_assignable_v<MDSpan> == Assignable); + static_assert(std::is_nothrow_move_constructible_v<MDSpan> == Constructible); +} + +constexpr void +test_nothrow_movable_all() +{ + using MDSpan = std::mdspan<double, std::dextents<int, 3>>; + static_assert(std::is_nothrow_move_assignable_v<MDSpan>); + static_assert(std::is_nothrow_move_constructible_v<MDSpan>); + + test_nothrow_movable<true, true>(); + test_nothrow_movable<true, false>(); + test_nothrow_movable<false, true>(); + test_nothrow_movable<false, false>(); +} + +int +main() +{ + test_typedefs_all(); + + test_rank_all(); + test_extent_all(); + static_assert(test_extent_all()); + + test_class_properties_all(); + static_assert(test_class_properties_all()); + + test_empty_all(); + static_assert(test_empty_all()); + + test_default_ctor(); + static_assert(test_default_ctor()); + + test_from_other(); + static_assert(test_from_other()); + + test_from_carray(); + static_assert(test_from_carray()); + + 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()); + + test_from_mapping(); + static_assert(test_from_mapping()); + + test_from_accessor(); + static_assert(test_from_accessor()); + + test_from_int_like(); + test_from_opaque_accessor(); + test_from_base_class_accessor(); + test_from_mapping_like(); + static_assert(test_from_mapping_like()); + + test_access(); + static_assert(test_access()); + + test_swap(); + static_assert(test_swap()); + test_swap_adl(); + + test_nothrow_movable_all(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc new file mode 100644 index 0000000..dceae56 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/out_of_bounds_neg.cc @@ -0,0 +1,24 @@ +// { dg-do compile { target c++23 } } +#include<mdspan> + +#include "layout_like.h" + +template<typename Layout> +constexpr bool +test_invalid_multi_index() +{ + + double data = 1.1; + auto m = typename Layout::mapping<std::extents<int, 1, 2, 3>>{}; + auto md = std::mdspan(&data, m); + + [[maybe_unused]] double x = md[0, 2, 2]; // { dg-error "expansion of" } + return true; +}; +static_assert(test_invalid_multi_index<LayoutLike>()); // { dg-error "expansion of" } +static_assert(test_invalid_multi_index<std::layout_left>()); // { dg-error "expansion of" } +static_assert(test_invalid_multi_index<std::layout_right>()); // { dg-error "expansion of" } +static_assert(test_invalid_multi_index<std::layout_stride>()); // { dg-error "expansion of" } + +// { dg-prune-output "non-constant condition" } +// { dg-prune-output "__glibcxx_assert" } diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/version.cc b/libstdc++-v3/testsuite/23_containers/mdspan/version.cc new file mode 100644 index 0000000..106ee40 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/version.cc @@ -0,0 +1,9 @@ +// { dg-do compile { target c++23 } } +#include <mdspan> + +#ifndef __cpp_lib_mdspan +#error "Feature test macro __cpp_lib_mdspan is missing for <mdspan>" +#if __cpp_lib_mdspan < 202207 +#error "Feature test macro __cpp_lib_mdspan has the wrong value" +#endif +#endif diff --git a/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc b/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc index c9e9112..890fdf8 100644 --- a/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/contiguous_range_neg.cc @@ -25,6 +25,7 @@ main() { std::deque<int> d{}; std::span<int, std::dynamic_extent> myspan(d); // { dg-error "no match" } + (void) myspan; } // { dg-prune-output "data" } 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/23_containers/unordered_map/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc new file mode 100644 index 0000000..e62f158 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/const_container.cc @@ -0,0 +1,19 @@ +// { dg-do compile { target c++11 } } + +#include <unordered_map> + +#include <testsuite_hooks.h> + +// PR c++/116369 +const std::unordered_map<int, int> um + { + { 0, 1 }, + { 2, 3 }, + { 4, 5 } + }; + +int main() +{ + VERIFY( um.size() == 3 ); + VERIFY( um.find(0) != um.end() ); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc new file mode 100644 index 0000000..3da1e33 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/const_container.cc @@ -0,0 +1,22 @@ +// { dg-do compile { target c++11 } } + +#include <unordered_map> + +#include <testsuite_hooks.h> + +// PR c++/116369 +const std::unordered_multimap<int, int> umm + { + { 0, 1 }, + { 0, 1 }, + { 2, 3 }, + { 2, 3 }, + { 4, 5 }, + { 4, 5 } + }; + +int main() +{ + VERIFY( umm.size() == 6 ); + VERIFY( umm.find(0) != umm.end() ); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc new file mode 100644 index 0000000..841d25a --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/const_container.cc @@ -0,0 +1,15 @@ +// { dg-do compile { target c++11 } } + +#include <unordered_set> + +#include <testsuite_hooks.h> + +// PR c++/116369 +const std::unordered_multiset<int> ums + { 0, 0, 1, 1, 2, 2 }; + +int main() +{ + VERIFY( ums.size() == 6 ); + VERIFY( ums.find(0) != ums.end() ); +} diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc new file mode 100644 index 0000000..ffdbbad --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/const_container.cc @@ -0,0 +1,14 @@ +// { dg-do compile { target c++11 } } + +#include <unordered_set> + +#include <testsuite_hooks.h> + +// PR c++/116369 +const std::unordered_set<int> us { 0, 1, 2 }; + +int main() +{ + VERIFY( us.size() == 3 ); + VERIFY( us.find(0) != us.end() ); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc b/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc index ba2ede0..792ed45 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/debug/mutex_association.cc @@ -25,7 +25,7 @@ class container : public __gnu_debug::_Safe_sequence<container> { public: __gnu_cxx::__mutex& - get_mutex() + get_mutex() const { return this->_M_get_mutex(); } }; 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/util/testsuite_containers.h b/libstdc++-v3/testsuite/util/testsuite_containers.h index 37491a4..ab0107f 100644 --- a/libstdc++-v3/testsuite/util/testsuite_containers.h +++ b/libstdc++-v3/testsuite/util/testsuite_containers.h @@ -210,6 +210,9 @@ namespace __gnu_test clit = container.cbegin(bn); assert( ++clit == container.cend(bn) ); + clit = container.begin(bn); + assert( ++clit == container.cend(bn) ); + assert( container.begin(bn) != container.cend(bn) ); } }; @@ -304,6 +307,9 @@ namespace __gnu_test assert( container.cbegin() != container.cend() ); assert( container.cbegin() != container.end() ); assert( container.begin() != container.cend() ); + + auto cit = container.begin(); + assert( cit == container.cbegin() ); } }; |