aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog427
-rw-r--r--libstdc++-v3/doc/doxygen/user.cfg.in6
-rw-r--r--libstdc++-v3/doc/html/manual/test.html11
-rw-r--r--libstdc++-v3/doc/xml/manual/test.xml12
-rw-r--r--libstdc++-v3/include/bits/chrono_io.h912
-rw-r--r--libstdc++-v3/include/bits/formatfwd.h26
-rw-r--r--libstdc++-v3/include/bits/ranges_algo.h64
-rw-r--r--libstdc++-v3/include/bits/stl_algo.h4
-rw-r--r--libstdc++-v3/include/bits/stl_tempbuf.h2
-rw-r--r--libstdc++-v3/include/bits/stl_uninitialized.h20
-rw-r--r--libstdc++-v3/include/bits/version.def8
-rw-r--r--libstdc++-v3/include/bits/version.h10
-rw-r--r--libstdc++-v3/include/std/format44
-rw-r--r--libstdc++-v3/include/std/mdspan726
-rw-r--r--libstdc++-v3/include/std/optional47
-rw-r--r--libstdc++-v3/include/std/type_traits3
-rw-r--r--libstdc++-v3/libsupc++/exception6
-rwxr-xr-xlibstdc++-v3/scripts/create_testsuite_files4
-rw-r--r--libstdc++-v3/src/c++23/std.cc.in5
-rw-r--r--libstdc++-v3/testsuite/17_intro/names.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/optional/range.cc163
-rw-r--r--libstdc++-v3/testsuite/20_util/optional/version.cc18
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/120397.cc19
-rw-r--r--libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/120397.cc19
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_default.cc2
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc48
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc436
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc131
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc568
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc526
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/bool/format.cc6
-rw-r--r--libstdc++-v3/testsuite/std/format/debug.cc74
-rw-r--r--libstdc++-v3/testsuite/std/format/formatter/120625.cc19
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/adaptors.cc22
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/formatter.cc13
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/map.cc8
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/sequence.cc8
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/string.cc12
-rw-r--r--libstdc++-v3/testsuite/std/format/tuple.cc25
-rw-r--r--libstdc++-v3/testsuite/std/time/format/empty_spec.cc112
-rw-r--r--libstdc++-v3/testsuite/std/time/format/pr117214.cc43
-rw-r--r--libstdc++-v3/testsuite/std/time/format/pr120114.cc20
-rw-r--r--libstdc++-v3/testsuite/std/time/format/pr120481.cc26
-rw-r--r--libstdc++-v3/testsuite/std/time/format/precision.cc14
-rw-r--r--libstdc++-v3/testsuite/std/time/format/whitespace.cc56
47 files changed, 4211 insertions, 522 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index e92a153..a021428 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,430 @@
+2025-06-16 Jason Merrill <jason@redhat.com>
+
+ * testsuite/20_util/is_complete_or_unbounded/memoization.cc
+ * testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc:
+ Expect -Wsfinae-incomplete.
+
+2025-06-13 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/120397
+ * include/bits/stl_uninitialized.h (_UninitDestroyGuard<I,void>):
+ Add new member function _S_destroy and call it from the
+ destructor (for C++17 only).
+ * testsuite/20_util/specialized_algorithms/uninitialized_default_construct/120397.cc:
+ New test.
+ * testsuite/20_util/specialized_algorithms/uninitialized_value_construct/120397.cc:
+ New test.
+
+2025-06-13 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ PR libstdc++/120648
+ * include/bits/chrono_io.h (__formatter_chrono::_M_format_to):
+ Handle %c, %r, %x and %X by passing them to _M_c_r_x_X.
+ (__formatter_chrono::_M_c_r_x_X): Reworked from _M_c.
+ (__formatter_chrono::_M_c): Renamed into above.
+ (__formatter_chrono::_M_r, __formatter_chrono::_M_x)
+ (__formatter_chrono::_M_X): Removed.
+ * testsuite/std/time/format/pr117214.cc: New tests for %r, %x,
+ %X with date, time and durations.
+
+2025-06-13 Patrick Palka <ppalka@redhat.com>
+
+ * include/bits/ranges_algo.h (__detail::__by_ref_or_value_fn): New.
+ (__detail::_Comp_proj): New.
+ (__detail::__make_comp_proj): Use it instead.
+ (__detail::_Pred_proj): New.
+ (__detail::__make_pred_proj): Use it instead.
+
+2025-06-13 Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+
+ PR c++/120644
+ * include/std/optional (format_kind): Do not use `auto`.
+
+2025-06-13 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * testsuite/23_containers/vector/bool/format.cc: Replaced _CharT
+ with CharT.
+ * testsuite/std/format/debug.cc: Likewise.
+ * testsuite/std/format/ranges/adaptors.cc: Likewise.
+ * testsuite/std/format/ranges/formatter.cc: Likewise.
+ * testsuite/std/format/ranges/map.cc: Likewise.
+ * testsuite/std/format/ranges/sequence.cc: Likewise.
+ * testsuite/std/format/ranges/string.cc: Likewise.
+ * testsuite/std/format/tuple.cc: Likewise.
+ * testsuite/std/time/format/empty_spec.cc: Likewise.
+ * testsuite/std/time/format/pr120114.cc: Likewise.
+ * testsuite/std/time/format/pr120481.cc: Likewise.
+ * testsuite/std/time/format/precision.cc: Likewise.
+
+2025-06-13 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * include/bits/chrono_io.h (__formatter_chrono::_M_format):
+ Remove handling of empty _M_chrono_specs.
+ (__formatter_chrono::_M_format_to_ostream): Changed to accept
+ only chrono::duration and made public.
+ (std::formatter<chrono::duration<_Rep, _Period>, _CharT>):
+ Configure __defSpec and handle empty chrono-spec locally.
+
+2025-06-13 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * include/bits/chrono_io.h (__format::__formatter_chrono_info)
+ [_GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI]: Define.
+ (std::formatter<chrono::sys_info, _CharT>)
+ (std::formatter<chrono::local_inf, _CharT>): Delegate to
+ __format::__formatter_chrono_info.
+ (std::operator<<(basic_ostream<_CharT, _Traits>& const sys_info&)):
+ Use format on sys_info with empty format spec.
+
+2025-06-13 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * testsuite/std/time/format/whitespace.cc: New test.
+
+2025-06-12 Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+
+ PR libstdc++/119496
+ * include/bits/stl_algo.h: Adjust calls to requested_size.
+ * include/bits/stl_tempbuf.h (requested_size): Rename with
+ an _M_ prefix.
+ * testsuite/17_intro/names.cc: Add a #define for
+ requested_size.
+
+2025-06-12 Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+
+ * include/bits/formatfwd.h (format_kind): Move the definition
+ (and some supporting code) from <format>.
+ * include/std/format (format_kind): Likewise.
+ * include/bits/version.def (optional_range_support): Add
+ the feature-testing macro.
+ * include/bits/version.h: Regenerate.
+ * include/std/optional (iterator, const_iterator, begin, end):
+ Add range support.
+ (enable_view): Specialize for std::optional.
+ (format_kind): Specialize for std::optional.
+ * testsuite/20_util/optional/range.cc: New test.
+ * testsuite/20_util/optional/version.cc: Test the new
+ feature-testing macro.
+
+2025-06-12 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * include/bits/chrono_io.h (_ChronoFormats::_S_ftz)
+ (_ChronoFormats::_S_ft, _ChronoFormats::_S_t): Define.
+ (__formatter_chrono::_M_format_to_ostream): Remove handling for
+ time_points.
+ (std::formatter<chrono::hh_mm_ss<_Dur>, _CharT>)
+ (std::formatter<chrono::sys_time<_Dur>, _CharT>)
+ (std::formatter<chrono::utc_time<_Dur>, _CharT>)
+ (std::formatter<chrono::tai_time<_Dur>, _CharT>)
+ (std::formatter<chrono::gps_time<_Dur>, _CharT>)
+ (std::formatter<chrono::file_time<_Dur>, _CharT>)
+ (std::formatter<chrono::local_time<_Dur>, _CharT>)
+ (std::formatter<chrono::__detail::__local_time_fmt<_Dur>, _CharT>)
+ (std::formatter<chrono::zoned_time<_Dur>, _CharT>):
+ Define __defSpec, and pass it as argument to _M_prase and
+ constructor of __formatter_chrono.
+
+2025-06-12 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * include/bits/chrono_io.h (__format::_ChronoFormats): Define.
+ (__formatter_chrono::__formatter_chrono())
+ (__formatter_chrono::__formatter_chrono(_ChronoSpec<_CharT>)): Define.
+ (__formatter_chrono::_M_parse): Add parameter with default spec,
+ and merge it with new values. Handle '%\0' as weekday index
+ specifier.
+ (__formatter_chrono::_M_a_A, __formatter_chrono::_M_b_B)
+ (__formatter_chrono::_M_C_y_Y, __formatter_chrono::_M_d_e)
+ (__formatter_chrono::_M_F): Support _M_debug flag.
+ (__formatter_chrono::_M_wi, __formatter_chrono::_S_weekday_index):
+ Define.
+ (std::formatter<chrono::day, _CharT>)
+ (std::formatter<chrono::month, _CharT>)
+ (std::formatter<chrono::year, _CharT>)
+ (std::formatter<chrono::weekday, _CharT>)
+ (std::formatter<chrono::weekday_indexed, _CharT>)
+ (std::formatter<chrono::weekday_last, _CharT>)
+ (std::formatter<chrono::month_day, _CharT>)
+ (std::formatter<chrono::month_day_last, _CharT>)
+ (std::formatter<chrono::month_weekday, _CharT>)
+ (std::formatter<chrono::month_weekday_last, _CharT>)
+ (std::formatter<chrono::year_month, _CharT>)
+ (std::formatter<chrono::year_month_day, _CharT>)
+ (std::formatter<chrono::year_month_day_last, _CharT>)
+ (std::formatter<chrono::year_month_weekday, _CharT>)
+ (std::formatter<chrono::year_month_weekday_last, _CharT>):
+ Define __defSpec, and pass it as argument to _M_parse and
+ constructor of __formatter_chrono.
+
+2025-06-12 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * include/std/mdspan (__mdspan::__mapping_alike): Rename template
+ parameter from M to _M_p.
+ (layout_right::mapping): Replace class with typename in template
+ head.
+ (layout_stride::mapping): Fix typo in comment.
+ * testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc:
+ Changed B to function.
+
+2025-06-12 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan (layout_left): Strengthen the exception
+ guarantees of layout_left::mapping(layout_stride::mapping).
+ * testsuite/23_containers/mdspan/layouts/ctors.cc:
+ Simplify tests to reflect the change.
+
+2025-06-12 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: Add
+ tests for layout_stride.
+ * testsuite/23_containers/mdspan/layouts/ctors.cc: Add test for
+ layout_stride and the interaction with other layouts.
+ * testsuite/23_containers/mdspan/layouts/empty.cc: Ditto.
+ * testsuite/23_containers/mdspan/layouts/mapping.cc: Ditto.
+ * testsuite/23_containers/mdspan/layouts/stride.cc: New test.
+
+2025-06-12 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan (layout_stride): New class.
+ * src/c++23/std.cc.in: Add layout_stride.
+
+2025-06-12 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: Add
+ tests for layout_right.
+ * testsuite/23_containers/mdspan/layouts/ctors.cc: Add tests for
+ layout_right and the interaction with layout_left.
+ * testsuite/23_containers/mdspan/layouts/empty.cc: ditto.
+ * testsuite/23_containers/mdspan/layouts/mapping.cc: ditto.
+
+2025-06-12 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan (layout_right): New class.
+ * src/c++23/std.cc.in: Add layout_right.
+
+2025-06-12 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc: New test.
+ * testsuite/23_containers/mdspan/layouts/ctors.cc: New test.
+ * testsuite/23_containers/mdspan/layouts/empty.cc: New test.
+ * testsuite/23_containers/mdspan/layouts/mapping.cc: New test.
+
+2025-06-12 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan (layout_left): New class.
+ * src/c++23/std.cc.in: Add layout_left.
+
+2025-06-12 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan(__mdspan::_ExtentsStorage): Change name
+ of private member _M_dynamic_extens to _M_dyn_exts.
+ (extents): Change name of private member from _M_dynamic_extents
+ to _M_exts.
+ Fix two instances of whitespace errors.
+ * testsuite/23_containers/mdspan/extents/ctor_default.cc: Fix
+ integer comparison with cmp_equal.
+
+2025-06-12 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/xml/manual/test.xml: Improve discussion of copyright
+ notices in new test cases.
+ * doc/html/manual/test.html: Regenerate.
+
+2025-06-12 Jonathan Wakely <jwakely@redhat.com>
+
+ * scripts/create_testsuite_files: Remove incorrect comment about
+ filtering out wchar_t tests.
+
+2025-06-12 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/120625
+ * include/std/format (__format::__disabled): Remove.
+ (__formatter_disabled): New type.
+ (formatter<char*, wchar_t>, formatter<const char*, wchar_t>)
+ (formatter<char[N], wchar_t>, formatter<string, wchar_t>)
+ (formatter<string_view, wchar_t>): Use __formatter_disabled as
+ base class instead of formatter<__disabled, wchar_t>.
+ * testsuite/std/format/formatter/120625.cc: New test.
+
+2025-06-11 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/doxygen/user.cfg.in (PREDEFINED): Remove -D prefixes from
+ some macros. Define _GLIBCXX_USE_BUILTIN_TRAIT and
+ _GLIBCXX_HAVE_ICONV macros.
+
+2025-06-11 Jonathan Wakely <jwakely@redhat.com>
+
+ * libsupc++/exception: Remove redundant parentheses and adjust
+ whitespace.
+
+2025-06-11 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/type_traits: Restore @cond and @endcond balance.
+
+2025-06-11 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ * testsuite/std/time/format/empty_spec.cc: New tests.
+ * testsuite/std/time/format/precision.cc: New test.
+
+2025-06-11 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_construct.h: Replace std::__addressof with
+ std::addressof in code that doesn't need to compile as C++98.
+ Replace std::__is_constant_evaluated with
+ std::is_constant_evaluated in code that doesn't need to compile
+ as C++17 or earlier.
+ * include/bits/stl_uninitialized.h: Likewise for __addressof.
+
+2025-06-11 Jonathan Wakely <jwakely@redhat.com>
+
+ * doc/xml/manual/test.xml: Remove note about unused 'test'
+ variables for old definition of VERIFY.
+ * doc/html/manual/test.html: Regenerate.
+ * testsuite/experimental/net/buffer/arithmetic.cc: Remove unused
+ variable.
+ * testsuite/experimental/net/buffer/const.cc: Likewise.
+ * testsuite/experimental/net/buffer/mutable.cc: Likewise.
+ * testsuite/experimental/net/buffer/size.cc: Likewise.
+ * testsuite/experimental/net/timer/waitable/cons.cc: Likewise.
+ * testsuite/experimental/net/timer/waitable/dest.cc: Likewise.
+ * testsuite/experimental/net/timer/waitable/ops.cc: Likewise.
+ * testsuite/ext/special_functions/airy_ai/check_value.cc:
+ Likewise.
+ * testsuite/ext/special_functions/airy_bi/check_value.cc:
+ Likewise.
+ * testsuite/ext/special_functions/conf_hyperg/check_value.cc:
+ Likewise.
+ * testsuite/ext/special_functions/hyperg/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/01_assoc_laguerre/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/02_assoc_legendre/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/02_assoc_legendre/pr86655.cc:
+ Likewise.
+ * testsuite/special_functions/03_beta/check_value.cc: Likewise.
+ * testsuite/special_functions/04_comp_ellint_1/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/05_comp_ellint_2/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/06_comp_ellint_3/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/07_cyl_bessel_i/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/08_cyl_bessel_j/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/09_cyl_bessel_k/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/10_cyl_neumann/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/11_ellint_1/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/12_ellint_2/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/13_ellint_3/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/14_expint/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/15_hermite/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/16_laguerre/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/17_legendre/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/18_riemann_zeta/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/19_sph_bessel/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/20_sph_legendre/check_value.cc:
+ Likewise.
+ * testsuite/special_functions/20_sph_legendre/pr86655.cc:
+ Likewise.
+ * testsuite/special_functions/21_sph_neumann/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/01_assoc_laguerre/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/02_assoc_legendre/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/02_assoc_legendre/pr86655.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/03_beta/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/04_comp_ellint_1/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/05_comp_ellint_2/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/06_comp_ellint_3/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/07_conf_hyperg/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/08_cyl_bessel_i/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/09_cyl_bessel_j/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/10_cyl_bessel_k/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/11_cyl_neumann/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/12_ellint_1/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/13_ellint_2/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/14_ellint_3/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/15_expint/check_value_neg.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/16_hermite/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/17_hyperg/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/18_laguerre/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/19_legendre/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/20_riemann_zeta/check_value_neg.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/21_sph_bessel/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/22_sph_legendre/check_value.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/22_sph_legendre/pr86655.cc:
+ Likewise.
+ * testsuite/tr1/5_numerical_facilities/special_functions/23_sph_neumann/check_value.cc:
+ Likewise.
+
+2025-06-11 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/sstream: Adjust whitespace.
+
+2025-06-11 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/120390
+ * include/bits/stl_construct.h (_Destroy_aux::__destroy_n): New
+ static member function.
+ (_Destroy_aux<true>::__destroy_n): Likewise.
+ (_Destroy_n_aux): Remove.
+ (_Destroy(ForwardIterator, ForwardIterator)): Remove
+ static_assert. Use is_trivially_destructible instead of
+ __has_trivial_destructor.
+ (_Destroy_n): Likewise. Use _Destroy_aux::__destroy_n instead of
+ _Destroy_n_aux::__destroy_n.
+ * testsuite/20_util/specialized_algorithms/memory_management_tools/destroy_neg.cc:
+ Adjust dg-error strings. Move destroy_n tests to ...
+ * testsuite/20_util/specialized_algorithms/memory_management_tools/destroy_n_neg.cc:
+ New test.
+ * testsuite/23_containers/vector/cons/destructible_debug_neg.cc:
+ Adjust dg-error strings.
+ * testsuite/23_containers/vector/cons/destructible_neg.cc:
+ Likewise.
+
+2025-06-11 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/27_io/basic_istringstream/cons/char/string_view.cc:
+ Only check get_allocator() for new string ABI.
+ * testsuite/27_io/basic_ostringstream/cons/char/string_view.cc:
+ Likewise.
+ * testsuite/27_io/basic_stringbuf/cons/char/string_view.cc:
+ Likewise.
+ * testsuite/27_io/basic_stringstream/cons/char/string_view.cc:
+ Likewise.
+
2025-06-10 Patrick Palka <ppalka@redhat.com>
* include/bits/max_size_type.h (__max_size_type::_M_val): Make
diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index e926c67..536e035 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -2350,8 +2350,8 @@ PREDEFINED = __cplusplus=202002L \
"_GLIBCXX_END_NAMESPACE_CONTAINER= " \
"_GLIBCXX_END_NAMESPACE_CXX11= " \
"_GLIBCXX_END_NAMESPACE_LDBL= " \
- "-D_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(X)= " \
- "-D_GLIBCXX_END_INLINE_ABI_NAMESPACE(X)= " \
+ "_GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(X)= " \
+ "_GLIBCXX_END_INLINE_ABI_NAMESPACE(X)= " \
"_GLIBCXX_TEMPLATE_ARGS=... " \
"_GLIBCXX_DEPRECATED= " \
"_GLIBCXX_DEPRECATED_SUGGEST(E)= " \
@@ -2414,6 +2414,8 @@ PREDEFINED = __cplusplus=202002L \
_GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE \
_GLIBCXX_HAVE_IS_CONSTANT_EVALUATED \
_GLIBCXX_HAVE_BUILTIN_LAUNDER \
+ "_GLIBCXX_USE_BUILTIN_TRAIT(X)=1" \
+ _GLIBCXX_HAVE_ICONV=1 \
"_GLIBCXX_DOXYGEN_ONLY(X)=X " \
__exception_ptr=__unspecified__ \
diff --git a/libstdc++-v3/doc/html/manual/test.html b/libstdc++-v3/doc/html/manual/test.html
index f6776f2..497ee1a 100644
--- a/libstdc++-v3/doc/html/manual/test.html
+++ b/libstdc++-v3/doc/html/manual/test.html
@@ -389,10 +389,15 @@ cat 27_io/objects/char/3_xin.in | a.out</pre></dd><dt><span class="term"><code c
We no longer require that, because most tests are uninteresting
and contain no "original authorship", and so would not be protected
by copyright anyway.
- If you do want to add the FSF copyright notice and GPL licence text,
+ Adding the FSF copyright notice to new tests is incorrect unless you
+ (or your employer) have a copyright assignment on file with the FSF,
+ or if the test contains code copied from another test under FSF copyright.
+ In particular, new tests that contain original code are not copyright FSF
+ if contributed under the <a class="link" href="https://gcc.gnu.org/dco.html" target="_top">DCO</a> terms.
+ If new tests do add the FSF copyright notice and GPL licence text,
then the first copyright year should correspond to the date
- the file was checked in to version control. If a test is copied from
- an existing file it should retain the copyright years from the
+ the file was checked in to version control. If the test code is copied
+ from an existing file it should retain the copyright years from the
original file.
</p><p>
The DejaGnu instructions say to always return <code class="literal">0</code>
diff --git a/libstdc++-v3/doc/xml/manual/test.xml b/libstdc++-v3/doc/xml/manual/test.xml
index f0139df..df49f56 100644
--- a/libstdc++-v3/doc/xml/manual/test.xml
+++ b/libstdc++-v3/doc/xml/manual/test.xml
@@ -650,10 +650,16 @@ cat 27_io/objects/char/3_xin.in | a.out</programlisting>
We no longer require that, because most tests are uninteresting
and contain no "original authorship", and so would not be protected
by copyright anyway.
- If you do want to add the FSF copyright notice and GPL licence text,
+ Adding the FSF copyright notice to new tests is incorrect unless you
+ (or your employer) have a copyright assignment on file with the FSF,
+ or if the test contains code copied from another test under FSF copyright.
+ In particular, new tests that contain original code are not copyright FSF
+ if contributed under the <link xmlns:xlink="http://www.w3.org/1999/xlink"
+ xlink:href="https://gcc.gnu.org/dco.html">DCO</link> terms.
+ If new tests do add the FSF copyright notice and GPL licence text,
then the first copyright year should correspond to the date
- the file was checked in to version control. If a test is copied from
- an existing file it should retain the copyright years from the
+ the file was checked in to version control. If the test code is copied
+ from an existing file it should retain the copyright years from the
original file.
</para>
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index c5c5e4b..abbf4efc 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -238,6 +238,108 @@ namespace __format
operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept
{ return __x = __x | __y; }
+ template<typename _CharT>
+ struct _ChronoFormats
+ {
+ using _String_view = basic_string_view<_CharT>;
+
+ static consteval
+ _String_view
+ _S_ftz() noexcept
+ { return _GLIBCXX_WIDEN("%F %T %Z"); }
+
+ static consteval
+ _String_view
+ _S_ft() noexcept
+ { return _S_ftz().substr(0, 5); }
+
+ static consteval
+ _String_view
+ _S_f() noexcept
+ { return _S_ftz().substr(0, 2); }
+
+ static consteval
+ _String_view
+ _S_t() noexcept
+ { return _S_ftz().substr(3, 2); }
+
+ static consteval
+ _String_view
+ _S_ymd() noexcept
+ { return _GLIBCXX_WIDEN("%Y/%b/%d"); }
+
+ static consteval
+ _String_view
+ _S_ym() noexcept
+ { return _S_ymd().substr(0, 5); }
+
+ static consteval
+ _String_view
+ _S_md() noexcept
+ { return _S_ymd().substr(3); }
+
+ static consteval
+ _String_view
+ _S_y() noexcept
+ { return _S_ymd().substr(0, 2); }
+
+ static consteval
+ _String_view
+ _S_m() noexcept
+ { return _S_ymd().substr(3, 2); }
+
+ static consteval
+ _String_view
+ _S_d() noexcept
+ { return _S_ymd().substr(6, 2); }
+
+ static consteval
+ _String_view
+ _S_ymwi() noexcept
+ // %\0 is extension for handling weekday index
+ { return _String_view(_GLIBCXX_WIDEN("%Y/%b/%a[%\0]"), 12); }
+
+ static consteval
+ _String_view
+ _S_mwi() noexcept
+ { return _S_ymwi().substr(3); }
+
+ static consteval
+ _String_view
+ _S_wi() noexcept
+ { return _S_ymwi().substr(6); }
+
+ static consteval
+ _String_view
+ _S_w() noexcept
+ { return _S_ymwi().substr(6, 2); }
+
+ static consteval
+ _String_view
+ _S_ymwl() noexcept
+ { return _GLIBCXX_WIDEN("%Y/%b/%a[last]"); }
+
+ static consteval
+ _String_view
+ _S_mwl() noexcept
+ { return _S_ymwl().substr(3); }
+
+ static consteval
+ _String_view
+ _S_wl() noexcept
+ { return _S_ymwl().substr(6); }
+
+ static consteval
+ _String_view
+ _S_yml() noexcept
+ { return _GLIBCXX_WIDEN("%Y/%b/last"); }
+
+ static consteval
+ _String_view
+ _S_ml() noexcept
+ { return _S_yml().substr(3); }
+ };
+
// TODO rename this to chrono::__formatter? or chrono::__detail::__formatter?
template<typename _CharT>
struct __formatter_chrono
@@ -245,14 +347,22 @@ namespace __format
using __string_view = basic_string_view<_CharT>;
using __string = basic_string<_CharT>;
+ __formatter_chrono() = default;
+
+ constexpr explicit
+ __formatter_chrono(_ChronoSpec<_CharT> __spec) noexcept
+ : _M_spec(__spec)
+ { }
+
template<typename _ParseContext>
constexpr typename _ParseContext::iterator
- _M_parse(_ParseContext& __pc, _ChronoParts __parts)
+ _M_parse(_ParseContext& __pc, _ChronoParts __parts,
+ const _ChronoSpec<_CharT>& __def = {})
{
auto __first = __pc.begin();
auto __last = __pc.end();
- _ChronoSpec<_CharT> __spec{};
+ _ChronoSpec<_CharT> __spec = __def;
auto __finalize = [this, &__spec] {
_M_spec = __spec;
@@ -285,6 +395,7 @@ namespace __format
return __first;
}
+ __spec._M_localized = false;
__first = __spec._M_parse_locale(__first, __last);
if (__finished())
return __first;
@@ -306,6 +417,9 @@ namespace __format
// Parse chrono-specs in [first,last), checking each conversion-spec
// against __parts (so fail for %Y if no year in parts).
// Save range in __spec._M_chrono_specs.
+ __spec._M_debug = false;
+ __spec._M_locale_specific = true;
+ __spec._M_chrono_specs = __string_view();
const auto __chrono_specs = __first++; // Skip leading '%'
if (*__chrono_specs != '%')
@@ -492,14 +606,12 @@ namespace __format
// that we instantiate fewer different specializations. Similar to
// _Sink_iter for std::format. Replace each _S_year, _S_day etc. with
// member functions of that type.
+ // pre: !_M_spec._M_chrono_specs.empty()
template<typename _Tp, typename _FormatContext>
typename _FormatContext::iterator
_M_format(const _Tp& __t, _FormatContext& __fc,
bool __is_neg = false) const
{
- if (_M_spec._M_chrono_specs.empty())
- return _M_format_to_ostream(__t, __fc, __is_neg);
-
#if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3565. Handling of encodings in localized formatting
@@ -562,6 +674,10 @@ namespace __format
_CharT __c = *__first++;
switch (__c)
{
+ // %\0 is extension for handling weekday index
+ case '\0':
+ __out = _M_wi(__t, std::move(__out), __fc);
+ break;
case 'a':
case 'A':
__out = _M_a_A(__t, std::move(__out), __fc, __c == 'A');
@@ -572,7 +688,10 @@ namespace __format
__out = _M_b_B(__t, std::move(__out), __fc, __c == 'B');
break;
case 'c':
- __out = _M_c(__t, std::move(__out), __fc, __mod == 'E');
+ case 'r':
+ case 'x':
+ case 'X':
+ __out = _M_c_r_x_X(__t, std::move(__out), __fc, __c, __mod);
break;
case 'C':
case 'y':
@@ -623,9 +742,6 @@ namespace __format
__throw_format_error("chrono format error: argument is "
"not a duration");
break;
- case 'r':
- __out = _M_r(__t, __print_sign(), __fc);
- break;
case 'R':
case 'T':
__out = _M_R_T(__t, __print_sign(), __fc, __c == 'T');
@@ -643,12 +759,6 @@ namespace __format
__out = _M_U_V_W(__t, std::move(__out), __fc, __c,
__mod == 'O');
break;
- case 'x':
- __out = _M_x(__t, std::move(__out), __fc, __mod == 'E');
- break;
- case 'X':
- __out = _M_X(__t, __print_sign(), __fc, __mod == 'E');
- break;
case 'z':
__out = _M_z(__t, std::move(__out), __fc, (bool)__mod);
break;
@@ -694,6 +804,24 @@ namespace __format
return std::move(__out);
}
+ // Format duration for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6).
+ template<typename _Rep, typename _Period, typename _FormatContext>
+ typename _FormatContext::iterator
+ _M_format_to_ostream(const chrono::duration<_Rep, _Period>& __d,
+ bool __is_neg, _FormatContext& __fc) const
+ {
+ basic_ostringstream<_CharT> __os;
+ __os.imbue(_M_locale(__fc));
+
+ if (__is_neg) [[unlikely]]
+ __os << _S_plus_minus[1];
+ __os << __d;
+
+ auto __str = std::move(__os).str();
+ return __format::__write_padded_as_spec(__str, __str.size(),
+ __fc, _M_spec);
+ }
+
_ChronoSpec<_CharT> _M_spec;
private:
@@ -708,82 +836,6 @@ namespace __format
return __fc.locale();
}
- // Format for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6).
- // TODO: consider moving body of every operator<< into this function
- // and use std::format("{}", t) to implement those operators. That
- // would avoid std::format("{}", t) calling operator<< which calls
- // std::format again.
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_format_to_ostream(const _Tp& __t, _FormatContext& __fc,
- bool __is_neg) const
- {
- using ::std::chrono::__detail::__utc_leap_second;
- using ::std::chrono::__detail::__local_time_fmt;
-
- basic_ostringstream<_CharT> __os;
- __os.imbue(_M_locale(__fc));
-
- if constexpr (__is_specialization_of<_Tp, __local_time_fmt>)
- {
- // Format as "{:L%F %T}"
- auto __days = chrono::floor<chrono::days>(__t._M_time);
- __os << chrono::year_month_day(__days) << ' '
- << chrono::hh_mm_ss(__t._M_time - __days);
-
- // For __local_time_fmt the __is_neg flags says whether to
- // append " %Z" to the result.
- if (__is_neg)
- {
- if (!__t._M_abbrev) [[unlikely]]
- __format::__no_timezone_available();
- else if constexpr (is_same_v<_CharT, char>)
- __os << ' ' << *__t._M_abbrev;
- else
- {
- __os << L' ';
- for (char __c : *__t._M_abbrev)
- __os << __c;
- }
- }
- }
- else
- {
- if constexpr (__is_specialization_of<_Tp, __utc_leap_second>)
- __os << __t._M_date << ' ' << __t._M_time;
- else if constexpr (chrono::__is_time_point_v<_Tp>)
- {
- // Need to be careful here because not all specializations
- // of chrono::sys_time can be written to an ostream.
- // For the specializations of time_point that can be
- // formatted with an empty chrono-specs, either it's a
- // sys_time with period greater or equal to days:
- if constexpr (is_convertible_v<_Tp, chrono::sys_days>)
- __os << _S_date(__t);
- // Or a local_time with period greater or equal to days:
- else if constexpr (is_convertible_v<_Tp, chrono::local_days>)
- __os << _S_date(__t);
- else // Or it's formatted as "{:L%F %T}":
- {
- auto __days = chrono::floor<chrono::days>(__t);
- __os << chrono::year_month_day(__days) << ' '
- << chrono::hh_mm_ss(__t - __days);
- }
- }
- else
- {
- if constexpr (chrono::__is_duration_v<_Tp>)
- if (__is_neg) [[unlikely]]
- __os << _S_plus_minus[1];
- __os << __t;
- }
- }
-
- auto __str = std::move(__os).str();
- return __format::__write_padded_as_spec(__str, __str.size(),
- __fc, _M_spec);
- }
-
static constexpr const _CharT* _S_chars
= _GLIBCXX_WIDEN("0123456789:/ +-{}");
static constexpr _CharT _S_colon = _S_chars[10];
@@ -818,6 +870,22 @@ namespace __format
template<typename _Tp, typename _FormatContext>
typename _FormatContext::iterator
+ _M_wi(const _Tp& __t, typename _FormatContext::iterator __out,
+ _FormatContext& __ctx) const
+ {
+ // %\0 Extension to format weekday index, used only by empty format spec
+ unsigned __wi = _S_weekday_index(__t);
+
+ _CharT __buf[3];
+ __out = __format::__write(std::move(__out), _S_str_d1(__buf, __wi));
+ if (_M_spec._M_debug && (__wi < 1 || __wi > 5))
+ __out = __format::__write(std::move(__out),
+ __string_view(_GLIBCXX_WIDEN(" is not a valid index")));
+ return std::move(__out);
+ }
+
+ template<typename _Tp, typename _FormatContext>
+ typename _FormatContext::iterator
_M_a_A(const _Tp& __t, typename _FormatContext::iterator __out,
_FormatContext& __ctx, bool __full) const
{
@@ -825,7 +893,16 @@ namespace __format
// %A Locale's full weekday name.
chrono::weekday __wd = _S_weekday(__t);
if (!__wd.ok())
- __throw_format_error("format error: invalid weekday");
+ {
+ if (!_M_spec._M_debug)
+ __throw_format_error("format error: invalid weekday");
+
+ _CharT __buf[3];
+ __out = __format::__write(std::move(__out),
+ _S_str_d1(__buf, __wd.c_encoding()));
+ return __format::__write(std::move(__out),
+ __string_view(_GLIBCXX_WIDEN(" is not a valid weekday")));
+ }
locale __loc = _M_locale(__ctx);
const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
@@ -847,7 +924,17 @@ namespace __format
// %B Locale's full month name.
chrono::month __m = _S_month(__t);
if (!__m.ok())
- __throw_format_error("format error: invalid month");
+ {
+ if (!_M_spec._M_debug)
+ __throw_format_error("format error: invalid month");
+
+ _CharT __buf[3];
+ __out = __format::__write(std::move(__out),
+ _S_str_d1(__buf, (unsigned)__m));
+ return __format::__write(std::move(__out),
+ __string_view(_GLIBCXX_WIDEN(" is not a valid month")));
+ }
+
locale __loc = _M_locale(__ctx);
const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
const _CharT* __months[12];
@@ -861,11 +948,16 @@ namespace __format
template<typename _Tp, typename _FormatContext>
typename _FormatContext::iterator
- _M_c(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod = false) const
+ _M_c_r_x_X(const _Tp& __t, typename _FormatContext::iterator __out,
+ _FormatContext& __ctx, _CharT __conv, _CharT __mod) const
{
// %c Locale's date and time representation.
// %Ec Locale's alternate date and time representation.
+ // %r Locale's 12-hour clock time.
+ // %x Locale's date rep
+ // %Ex Locale's alternative date representation.
+ // %X Locale's time rep
+ // %EX Locale's alternative time representation.
using namespace chrono;
using ::std::chrono::__detail::__utc_leap_second;
@@ -899,23 +991,30 @@ namespace __format
__tm.tm_zone = const_cast<char*>("UTC");
#endif
- auto __d = _S_days(__t); // Either sys_days or local_days.
- using _TDays = decltype(__d);
- const year_month_day __ymd(__d);
- const auto __y = __ymd.year();
- const auto __hms = _S_hms(__t);
+ if (__conv == 'c' || __conv == 'x')
+ {
+ auto __d = _S_days(__t); // Either sys_days or local_days.
+ using _TDays = decltype(__d);
+ const year_month_day __ymd(__d);
+ const auto __y = __ymd.year();
+
+ __tm.tm_year = (int)__y - 1900;
+ __tm.tm_yday = (__d - _TDays(__y/January/1)).count();
+ __tm.tm_mon = (unsigned)__ymd.month() - 1;
+ __tm.tm_mday = (unsigned)__ymd.day();
+ __tm.tm_wday = weekday(__d).c_encoding();
+ }
- __tm.tm_year = (int)__y - 1900;
- __tm.tm_yday = (__d - _TDays(__y/January/1)).count();
- __tm.tm_mon = (unsigned)__ymd.month() - 1;
- __tm.tm_mday = (unsigned)__ymd.day();
- __tm.tm_wday = weekday(__d).c_encoding();
- __tm.tm_hour = __hms.hours().count();
- __tm.tm_min = __hms.minutes().count();
- __tm.tm_sec = __hms.seconds().count();
-
- return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 'c',
- __mod ? 'E' : '\0');
+ if (__conv != 'x')
+ {
+ const auto __hms = _S_hms(__t);
+ __tm.tm_hour = __hms.hours().count();
+ __tm.tm_min = __hms.minutes().count();
+ __tm.tm_sec = __hms.seconds().count();
+ }
+
+ return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm,
+ __conv, __mod);
}
template<typename _Tp, typename _FormatContext>
@@ -974,7 +1073,11 @@ namespace __format
}
__out = __format::__write(std::move(__out), __sv);
}
- return std::move(__out);
+
+ if (_M_spec._M_debug && __conv == 'Y' && !__y.ok()) [[unlikely]]
+ __out = __format::__write(std::move(__out),
+ __string_view(_GLIBCXX_WIDEN(" is not a valid year")));
+ return __out;
}
template<typename _Tp, typename _FormatContext>
@@ -1039,7 +1142,12 @@ namespace __format
__buf[0] = _S_space;
__sv = {__buf, 2};
}
- return __format::__write(std::move(__out), __sv);
+
+ __out = __format::__write(std::move(__out), __sv);
+ if (_M_spec._M_debug && !__d.ok()) [[unlikely]]
+ __out = __format::__write(std::move(__out),
+ __string_view(_GLIBCXX_WIDEN(" is not a valid day")));
+ return std::move(__out);
}
template<typename _Tp, typename _FormatContext>
@@ -1076,6 +1184,10 @@ namespace __format
_S_fill_two_digits(__buf + 9, __di);
__out = __format::__write(std::move(__out), __sv);
}
+
+ if (_M_spec._M_debug && !__ymd.ok())
+ __out = __format::__write(std::move(__out),
+ __string_view(_GLIBCXX_WIDEN(" is not a valid date")));
return std::move(__out);
}
@@ -1243,25 +1355,6 @@ namespace __format
template<typename _Tp, typename _FormatContext>
typename _FormatContext::iterator
- _M_r(const _Tp& __tt, typename _FormatContext::iterator __out,
- _FormatContext& __ctx) const
- {
- // %r locale's 12-hour clock time.
- auto __t = _S_floor_seconds(__tt);
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __ampm_fmt;
- __tp._M_am_pm_format(&__ampm_fmt);
- basic_string<_CharT> __fmt(_S_empty_spec);
- __fmt.insert(1u, 1u, _S_colon);
- __fmt.insert(2u, __ampm_fmt);
- using _FmtStr = _Runtime_format_string<_CharT>;
- return _M_write(std::move(__out), __loc,
- std::format(__loc, _FmtStr(__fmt), __t));
- }
-
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
_M_R_T(const _Tp& __t, typename _FormatContext::iterator __out,
_FormatContext& __ctx, bool __secs) const
{
@@ -1441,53 +1534,6 @@ namespace __format
template<typename _Tp, typename _FormatContext>
typename _FormatContext::iterator
- _M_x(const _Tp& __t, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod = false) const
- {
- // %x Locale's date rep
- // %Ex Locale's alternative date representation.
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __date_reps[2];
- __tp._M_date_formats(__date_reps);
- const _CharT* __rep = __date_reps[__mod];
- if (!*__rep)
- return _M_D(__t, std::move(__out), __ctx);
-
- basic_string<_CharT> __fmt(_S_empty_spec);
- __fmt.insert(1u, 1u, _S_colon);
- __fmt.insert(2u, __rep);
- using _FmtStr = _Runtime_format_string<_CharT>;
- return _M_write(std::move(__out), __loc,
- std::format(__loc, _FmtStr(__fmt), __t));
- }
-
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
- _M_X(const _Tp& __tt, typename _FormatContext::iterator __out,
- _FormatContext& __ctx, bool __mod = false) const
- {
- // %X Locale's time rep
- // %EX Locale's alternative time representation.
- auto __t = _S_floor_seconds(__tt);
- locale __loc = _M_locale(__ctx);
- const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
- const _CharT* __time_reps[2];
- __tp._M_time_formats(__time_reps);
- const _CharT* __rep = __time_reps[__mod];
- if (!*__rep)
- return _M_R_T(__t, std::move(__out), __ctx, true);
-
- basic_string<_CharT> __fmt(_S_empty_spec);
- __fmt.insert(1u, 1u, _S_colon);
- __fmt.insert(2u, __rep);
- using _FmtStr = _Runtime_format_string<_CharT>;
- return _M_write(std::move(__out), __loc,
- std::format(__loc, _FmtStr(__fmt), __t));
- }
-
- template<typename _Tp, typename _FormatContext>
- typename _FormatContext::iterator
_M_z(const _Tp& __t, typename _FormatContext::iterator __out,
_FormatContext&, bool __mod = false) const
{
@@ -1757,6 +1803,20 @@ namespace __format
return weekday(_S_days(__t));
}
+ template<typename _Tp>
+ static unsigned
+ _S_weekday_index(const _Tp& __t)
+ {
+ using namespace ::std::chrono;
+
+ if constexpr (is_same_v<_Tp, weekday_indexed>)
+ return __t.index();
+ else if constexpr (requires { __t.weekday_indexed(); })
+ return __t.weekday_indexed().index();
+ else
+ return ((unsigned)_S_day(__t) + 6) / 7;
+ }
+
// Remove subsecond precision from a time_point.
template<typename _Tp>
static auto
@@ -1801,6 +1861,84 @@ namespace __format
}
};
+#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+ template<typename _CharT>
+ struct __formatter_chrono_info
+ {
+ constexpr typename basic_format_parse_context<_CharT>::iterator
+ parse(basic_format_parse_context<_CharT>& __pc)
+ { return _M_f._M_parse(__pc, _ChronoParts(), {}); }
+
+ template<typename _Info, typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const _Info& __i,
+ basic_format_context<_Out, _CharT>& __fc) const
+ {
+ // n.b. only acceptable chrono-spec for info is one containing
+ // only whitespaces and %%, that do not depend on formatted object.
+ if (!_M_f._M_spec._M_chrono_specs.empty()) [[unlikely]]
+ return _M_f._M_format(chrono::day(1), __fc);
+
+ const size_t __padwidth = _M_f._M_spec._M_get_width(__fc);
+ if (__padwidth == 0)
+ return _M_format_to(__fc.out(), __i);
+
+ _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth);
+ _M_format_to(__sink.out(), __i);
+ return __sink._M_finish(_M_f._M_spec._M_align, _M_f._M_spec._M_fill);
+ }
+
+ private:
+ template<typename _Out>
+ _Out
+ _M_format_to(_Out __out, const chrono::sys_info& __si) const
+ {
+ using _FmtStr = _Runtime_format_string<_CharT>;
+ // n.b. only decimal separator is locale dependent for specifiers
+ // used below, as sys_info uses seconds and minutes duration, the
+ // output is locale-independent.
+ constexpr auto* __fs
+ = _GLIBCXX_WIDEN("[{0:%F %T},{1:%F %T},{2:%T},{3:%Q%q},{0:%Z}]");
+ const chrono::local_seconds __lb(__si.begin.time_since_epoch());
+ return std::format_to(std::move(__out), _FmtStr(__fs),
+ chrono::local_time_format(__lb, &__si.abbrev),
+ __si.end, __si.offset, __si.save);
+ }
+
+ template<typename _Out>
+ _Out
+ _M_format_to(_Out __out, const chrono::local_info& __li) const
+ {
+ *__out = _Separators<_CharT>::_S_squares()[0];
+ ++__out;
+ if (__li.result == chrono::local_info::unique)
+ __out = _M_format_to(std::move(__out), __li.first);
+ else
+ {
+ basic_string_view<_CharT> __sv;
+ if (__li.result == chrono::local_info::nonexistent)
+ __sv =_GLIBCXX_WIDEN("nonexistent");
+ else
+ __sv = _GLIBCXX_WIDEN("ambiguous");
+ __out = __format::__write(std::move(__out), __sv);
+
+ __sv = _GLIBCXX_WIDEN(" local time between ");
+ __out = __format::__write(std::move(__out), __sv);
+ __out = _M_format_to(std::move(__out), __li.first);
+
+ __sv = _GLIBCXX_WIDEN(" and ");
+ __out = __format::__write(std::move(__out), __sv);
+ __out = _M_format_to(std::move(__out), __li.second);
+ }
+ *__out = _Separators<_CharT>::_S_squares()[1];
+ ++__out;
+ return std::move(__out);
+ }
+
+ __formatter_chrono<_CharT> _M_f;
+ };
+#endif
+
} // namespace __format
/// @endcond
@@ -1812,7 +1950,7 @@ namespace __format
parse(basic_format_parse_context<_CharT>& __pc)
{
using namespace __format;
- auto __it = _M_f._M_parse(__pc, _Duration|_TimeOfDay);
+ auto __it = _M_f._M_parse(__pc, _Duration|_TimeOfDay, __defSpec);
if constexpr (!is_floating_point_v<_Rep>)
if (_M_f._M_spec._M_prec_kind != __format::_WP_none)
__throw_format_error("format error: invalid precision for duration");
@@ -1834,16 +1972,37 @@ namespace __format
using _URep = make_unsigned_t<_Rep>;
auto __ucnt = -static_cast<_URep>(__d.count());
auto __ud = chrono::duration<_URep, _Period>(__ucnt);
- return _M_f._M_format(__ud, __fc, true);
+ return _M_format(__ud, true, __fc);
}
else
- return _M_f._M_format(-__d, __fc, true);
+ return _M_format(-__d, true, __fc);
}
- return _M_f._M_format(__d, __fc, false);
+ return _M_format(__d, false, __fc);
}
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_localized = !is_integral_v<_Rep>;
+ if constexpr (is_integral_v<_Rep>)
+ __res._M_chrono_specs = _GLIBCXX_WIDEN("%Q%q");
+ return __res;
+ }();
+
+ template<typename _Rep2, typename _Out>
+ typename basic_format_context<_Out, _CharT>::iterator
+ _M_format(const chrono::duration<_Rep2, _Period>& __d,
+ bool __is_neg,
+ basic_format_context<_Out, _CharT>& __fc) const
+ {
+ if constexpr (!is_integral_v<_Rep>)
+ if (_M_f._M_spec._M_chrono_specs.empty())
+ return _M_f._M_format_to_ostream(__d, __is_neg, __fc);
+ return _M_f._M_format(__d, __fc, __is_neg);
+ }
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1851,7 +2010,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Day); }
+ { return _M_f._M_parse(__pc, __format::_Day, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1860,7 +2019,15 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_d();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1868,7 +2035,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month); }
+ { return _M_f._M_parse(__pc, __format::_Month, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1877,7 +2044,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_m();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1885,7 +2062,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Year); }
+ { return _M_f._M_parse(__pc, __format::_Year, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1894,7 +2071,15 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_y();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1902,7 +2087,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Weekday); }
+ { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1911,7 +2096,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_w();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1919,7 +2114,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Weekday); }
+ { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1928,7 +2123,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_wi();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1936,7 +2141,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Weekday); }
+ { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1945,7 +2150,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_wl();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1953,7 +2168,10 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
+ {
+ return _M_f._M_parse(__pc, __format::_Month|__format::_Day,
+ __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1962,7 +2180,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_md();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1970,7 +2198,10 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
+ {
+ return _M_f._M_parse(__pc, __format::_Month|__format::_Day,
+ __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1979,7 +2210,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ml();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -1987,7 +2228,10 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
+ {
+ return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday,
+ __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -1996,7 +2240,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_mwi();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -2004,7 +2258,10 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
+ {
+ return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday,
+ __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -2013,7 +2270,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_mwl();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -2021,7 +2288,10 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Year|__format::_Month); }
+ {
+ return _M_f._M_parse(__pc, __format::_Year|__format::_Month,
+ __defSpec);
+ }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -2030,7 +2300,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ym();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -2038,7 +2318,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Date); }
+ { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -2047,7 +2327,15 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_f();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -2055,7 +2343,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Date); }
+ { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -2064,7 +2352,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_yml();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -2072,7 +2370,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Date); }
+ { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -2081,7 +2379,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ymwi();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<__format::__char _CharT>
@@ -2089,7 +2397,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_Date); }
+ { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -2098,7 +2406,17 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_debug = true;
+ __res._M_localized = true;
+ __res._M_locale_specific = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ymwl();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<typename _Rep, typename _Period, __format::__char _CharT>
@@ -2106,7 +2424,7 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_TimeOfDay); }
+ { return _M_f._M_parse(__pc, __format::_TimeOfDay, __defSpec); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
@@ -2115,7 +2433,15 @@ namespace __format
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_localized = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_t();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
@@ -2124,16 +2450,16 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ChronoParts{}); }
+ { return _M_f.parse(__pc); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::sys_info& __i,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__i, __fc); }
+ { return _M_f.format(__i, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ __format::__formatter_chrono_info<_CharT> _M_f;
};
template<__format::__char _CharT>
@@ -2141,16 +2467,16 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ChronoParts{}); }
+ { return _M_f.parse(__pc); }
template<typename _Out>
typename basic_format_context<_Out, _CharT>::iterator
format(const chrono::local_info& __i,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__i, __fc); }
+ { return _M_f.format(__i, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ __format::__formatter_chrono_info<_CharT> _M_f;
};
#endif
@@ -2160,7 +2486,7 @@ namespace __format
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
{
- auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime);
+ auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime, __defSpec);
if constexpr (!__stream_insertable)
if (_M_f._M_spec._M_chrono_specs.empty())
__format::__invalid_chrono_spec(); // chrono-specs can't be empty
@@ -2178,7 +2504,22 @@ namespace __format
= requires (basic_ostream<_CharT>& __os,
chrono::sys_time<_Duration> __t) { __os << __t; };
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ if constexpr (!__stream_insertable)
+ return __res;
+ else if constexpr (is_convertible_v<_Duration, chrono::days>)
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_f();
+ else
+ {
+ __res._M_localized = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ft();
+ }
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<typename _Duration, __format::__char _CharT>
@@ -2187,11 +2528,11 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime, __defSpec); }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::utc_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::utc_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{
// Adjust by removing leap seconds to get equivalent sys_time.
@@ -2212,7 +2553,15 @@ namespace __format
private:
friend formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT>;
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_localized = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ft();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<typename _Duration, __format::__char _CharT>
@@ -2221,11 +2570,11 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime, __defSpec); }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::tai_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::tai_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{
// Convert to __local_time_fmt with abbrev "TAI" and offset 0s.
@@ -2243,7 +2592,15 @@ namespace __format
}
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_localized = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ft();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<typename _Duration, __format::__char _CharT>
@@ -2252,11 +2609,11 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime, __defSpec); }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::gps_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::gps_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{
// Convert to __local_time_fmt with abbrev "GPS" and offset 0s.
@@ -2274,7 +2631,15 @@ namespace __format
}
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_localized = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ft();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<typename _Duration, __format::__char _CharT>
@@ -2282,11 +2647,11 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime, __defSpec); }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::file_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::file_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{
using namespace chrono;
@@ -2294,24 +2659,45 @@ namespace __format
}
private:
- __format::__formatter_chrono<_CharT> _M_f;
- };
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_localized = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ft();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
+ };
template<typename _Duration, __format::__char _CharT>
struct formatter<chrono::local_time<_Duration>, _CharT>
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_DateTime); }
+ { return _M_f._M_parse(__pc, __format::_DateTime, __defSpec); }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::local_time<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::local_time<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{ return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ if constexpr (is_convertible_v<_Duration, chrono::days>)
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_f();
+ else
+ {
+ __res._M_localized = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ft();
+ }
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
template<typename _Duration, __format::__char _CharT>
@@ -2319,16 +2705,24 @@ namespace __format
{
constexpr typename basic_format_parse_context<_CharT>::iterator
parse(basic_format_parse_context<_CharT>& __pc)
- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); }
+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime, __defSpec); }
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::__detail::__local_time_fmt<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::__detail::__local_time_fmt<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
- { return _M_f._M_format(__t, __fc, /* use %Z for {} */ true); }
+ { return _M_f._M_format(__t, __fc); }
private:
- __format::__formatter_chrono<_CharT> _M_f;
+ static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
+ {
+ __format::_ChronoSpec<_CharT> __res{};
+ __res._M_localized = true;
+ __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_ftz();
+ return __res;
+ }();
+
+ __format::__formatter_chrono<_CharT> _M_f{__defSpec};
};
#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
@@ -2337,8 +2731,8 @@ namespace __format
: formatter<chrono::__detail::__local_time_fmt_for<_Duration>, _CharT>
{
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp,
basic_format_context<_Out, _CharT>& __fc) const
{
using _Ltf = chrono::__detail::__local_time_fmt_for<_Duration>;
@@ -2358,8 +2752,8 @@ namespace __format
: formatter<chrono::utc_time<_Duration>, _CharT>
{
template<typename _Out>
- typename basic_format_context<_Out, _CharT>::iterator
- format(const chrono::__detail::__utc_leap_second<_Duration>& __t,
+ typename basic_format_context<_Out, _CharT>::iterator
+ format(const chrono::__detail::__utc_leap_second<_Duration>& __t,
basic_format_context<_Out, _CharT>& __fc) const
{ return this->_M_f._M_format(__t, __fc); }
};
@@ -2944,15 +3338,7 @@ namespace __detail
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __i)
{
- // n.b. only decimal separator is locale dependent for specifiers
- // used below, as sys_info uses seconds and minutes duration, the
- // output is locale-independent.
- constexpr auto* __fs
- = _GLIBCXX_WIDEN("[{0:%F %T},{1:%F %T},{2:%T},{3:%Q%q},{0:%Z}]");
- local_seconds __lb(__i.begin.time_since_epoch());
- __os << std::format(__fs, local_time_format(__lb, &__i.abbrev),
- __i.end, __i.offset, __i.save);
- return __os;
+ return __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{}"), __i);
}
/// Writes a local_info object to an ostream in an unspecified format.
diff --git a/libstdc++-v3/include/bits/formatfwd.h b/libstdc++-v3/include/bits/formatfwd.h
index 777e629..314b55d 100644
--- a/libstdc++-v3/include/bits/formatfwd.h
+++ b/libstdc++-v3/include/bits/formatfwd.h
@@ -162,6 +162,32 @@ namespace __format
using __maybe_const
= __conditional_t<formattable<const _Tp, _CharT>, const _Tp, _Tp>;
}
+
+ // [format.range], formatting of ranges
+ // [format.range.fmtkind], variable template format_kind
+ enum class range_format {
+ disabled,
+ map,
+ set,
+ sequence,
+ string,
+ debug_string
+ };
+
+ /** @brief A constant determining how a range should be formatted.
+ *
+ * The primary template of `std::format_kind` cannot be instantiated.
+ * There is a partial specialization for input ranges and you can
+ * specialize the variable template for your own cv-unqualified types
+ * that satisfy the `ranges::input_range` concept.
+ *
+ * @since C++23
+ */
+ template<typename _Rg>
+ constexpr auto format_kind = []{
+ static_assert(false, "cannot use primary template of 'std::format_kind'");
+ return type_identity<_Rg>{};
+ }();
#endif // format_ranges
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
index a62c3cd..5aca6e8 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -47,28 +47,60 @@ namespace ranges
{
namespace __detail
{
+ template<typename _Fp>
+ using __by_ref_or_value_fn
+ = __conditional_t<is_scalar_v<_Fp> || is_empty_v<_Fp>, _Fp, _Fp&>;
+
template<typename _Comp, typename _Proj>
- constexpr auto
+ struct _Comp_proj
+ {
+ [[no_unique_address]] __by_ref_or_value_fn<_Comp> _M_comp;
+ [[no_unique_address]] __by_ref_or_value_fn<_Proj> _M_proj;
+
+ constexpr
+ _Comp_proj(_Comp& __comp, _Proj& __proj)
+ : _M_comp(__comp), _M_proj(__proj)
+ { }
+
+ template<typename _Tp, typename _Up>
+ constexpr bool
+ operator()(_Tp&& __x, _Up&& __y)
+ {
+ return std::__invoke(_M_comp,
+ std::__invoke(_M_proj, std::forward<_Tp>(__x)),
+ std::__invoke(_M_proj, std::forward<_Up>(__y)));
+ }
+ };
+
+ template<typename _Comp, typename _Proj>
+ constexpr _Comp_proj<_Comp, _Proj>
__make_comp_proj(_Comp& __comp, _Proj& __proj)
+ { return {__comp, __proj}; }
+
+ template<typename _Pred, typename _Proj>
+ struct _Pred_proj
{
- return [&] (auto&& __lhs, auto&& __rhs) -> bool {
- using _TL = decltype(__lhs);
- using _TR = decltype(__rhs);
- return std::__invoke(__comp,
- std::__invoke(__proj, std::forward<_TL>(__lhs)),
- std::__invoke(__proj, std::forward<_TR>(__rhs)));
- };
- }
+ [[no_unique_address]] __by_ref_or_value_fn<_Pred> _M_pred;
+ [[no_unique_address]] __by_ref_or_value_fn<_Proj> _M_proj;
+
+ constexpr
+ _Pred_proj(_Pred& __pred, _Proj& __proj)
+ : _M_pred(__pred), _M_proj(__proj)
+ { }
+
+ template<typename _Tp>
+ constexpr bool
+ operator()(_Tp&& __x)
+ {
+ return std::__invoke(_M_pred,
+ std::__invoke(_M_proj, std::forward<_Tp>(__x)));
+ }
+ };
template<typename _Pred, typename _Proj>
- constexpr auto
+ constexpr _Pred_proj<_Pred, _Proj>
__make_pred_proj(_Pred& __pred, _Proj& __proj)
- {
- return [&] <typename _Tp> (_Tp&& __arg) -> bool {
- return std::__invoke(__pred,
- std::__invoke(__proj, std::forward<_Tp>(__arg)));
- };
- }
+ { return {__pred, __proj}; }
} // namespace __detail
struct __all_of_fn
diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h
index 98c2249..3f4674d 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -2511,7 +2511,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
// [first,middle) and [middle,last).
_TmpBuf __buf(__first, std::min(__len1, __len2));
- if (__builtin_expect(__buf.size() == __buf.requested_size(), true))
+ if (__builtin_expect(__buf.size() == __buf._M_requested_size(), true))
std::__merge_adaptive
(__first, __middle, __last, __len1, __len2, __buf.begin(), __comp);
else if (__builtin_expect(__buf.begin() == 0, false))
@@ -5024,7 +5024,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
// so the buffer only needs to fit half the range at once.
_TmpBuf __buf(__first, (__last - __first + 1) / 2);
- if (__builtin_expect(__buf.requested_size() == __buf.size(), true))
+ if (__builtin_expect(__buf._M_requested_size() == __buf.size(), true))
std::__stable_sort_adaptive(__first,
__first + _DistanceType(__buf.size()),
__last, __buf.begin(), __comp);
diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h b/libstdc++-v3/include/bits/stl_tempbuf.h
index 7a7619e..8cc7b11 100644
--- a/libstdc++-v3/include/bits/stl_tempbuf.h
+++ b/libstdc++-v3/include/bits/stl_tempbuf.h
@@ -227,7 +227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// Returns the size requested by the constructor; may be >size().
size_type
- requested_size() const
+ _M_requested_size() const
{ return _M_original_len; }
/// As per Table mumble.
diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h
index bde787c..f4b26cc 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -118,7 +118,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
~_UninitDestroyGuard()
{
if (__builtin_expect(_M_cur != 0, 0))
+#if __cplusplus == 201703L
+ // std::uninitialized_{value,default}{,_n} can construct array types,
+ // but std::_Destroy cannot handle them until C++20 (PR 120397).
+ _S_destroy(_M_first, *_M_cur);
+#else
std::_Destroy(_M_first, *_M_cur);
+#endif
}
_GLIBCXX20_CONSTEXPR
@@ -129,6 +135,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
private:
_UninitDestroyGuard(const _UninitDestroyGuard&);
+
+#if __cplusplus == 201703L
+ template<typename _Iter>
+ static void
+ _S_destroy(_Iter __first, _Iter __last)
+ {
+ using _ValT = typename iterator_traits<_Iter>::value_type;
+ if constexpr (is_array<_ValT>::value)
+ for (; __first != __last; ++__first)
+ _S_destroy(*__first, *__first + extent<_ValT>::value);
+ else
+ std::_Destroy(__first, __last);
+ }
+#endif
};
// This is the default implementation of std::uninitialized_copy.
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 7cf62e9..880586e 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -852,6 +852,14 @@ ftms = {
};
ftms = {
+ name = optional_range_support;
+ values = {
+ v = 202406;
+ cxxmin = 26;
+ };
+};
+
+ftms = {
name = destroying_delete;
values = {
v = 201806;
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 9f4cf9a..4300adb 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -955,6 +955,16 @@
#endif /* !defined(__cpp_lib_optional) && defined(__glibcxx_want_optional) */
#undef __glibcxx_want_optional
+#if !defined(__cpp_lib_optional_range_support)
+# if (__cplusplus > 202302L)
+# define __glibcxx_optional_range_support 202406L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional_range_support)
+# define __cpp_lib_optional_range_support 202406L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_optional_range_support) && defined(__glibcxx_want_optional_range_support) */
+#undef __glibcxx_want_optional_range_support
+
#if !defined(__cpp_lib_destroying_delete)
# if (__cplusplus >= 202002L) && (__cpp_impl_destroying_delete)
# define __glibcxx_destroying_delete 201806L
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index ec76ab0..46bd5d5 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -3114,24 +3114,28 @@ namespace __format
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 3944. Formatters converting sequences of char to sequences of wchar_t
- namespace __format { struct __disabled; }
+ struct __formatter_disabled
+ {
+ __formatter_disabled() = delete; // Cannot format char sequence to wchar_t
+ __formatter_disabled(const __formatter_disabled&) = delete;
+ __formatter_disabled& operator=(const __formatter_disabled&) = delete;
+ };
- // std::formatter<__disabled, C> uses the primary template, which is disabled.
template<>
struct formatter<char*, wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
template<>
struct formatter<const char*, wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
template<size_t _Nm>
struct formatter<char[_Nm], wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
template<class _Traits, class _Allocator>
struct formatter<basic_string<char, _Traits, _Allocator>, wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
template<class _Traits>
struct formatter<basic_string_view<char, _Traits>, wchar_t>
- : private formatter<__format::__disabled, wchar_t> { };
+ : private __formatter_disabled { };
#endif
/// An iterator after the last character written, and the number of
@@ -5479,32 +5483,6 @@ namespace __format
#endif
#if __glibcxx_format_ranges // C++ >= 23 && HOSTED
- // [format.range], formatting of ranges
- // [format.range.fmtkind], variable template format_kind
- enum class range_format {
- disabled,
- map,
- set,
- sequence,
- string,
- debug_string
- };
-
- /** @brief A constant determining how a range should be formatted.
- *
- * The primary template of `std::format_kind` cannot be instantiated.
- * There is a partial specialization for input ranges and you can
- * specialize the variable template for your own cv-unqualified types
- * that satisfy the `ranges::input_range` concept.
- *
- * @since C++23
- */
- template<typename _Rg>
- constexpr auto format_kind = []{
- static_assert(false, "cannot use primary template of 'std::format_kind'");
- return type_identity<_Rg>{};
- }();
-
/// @cond undocumented
template<typename _Tp>
consteval range_format
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index bcf2fa6..6dc2441 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -69,12 +69,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
//
// If __r is the index of a dynamic extent, then
// _S_dynamic_index[__r] is the index of that extent in
- // _M_dynamic_extents.
+ // _M_dyn_exts.
static constexpr auto _S_dynamic_index = [] consteval
{
array<size_t, _S_rank+1> __ret;
size_t __dyn = 0;
- for(size_t __i = 0; __i < _S_rank; ++__i)
+ for (size_t __i = 0; __i < _S_rank; ++__i)
{
__ret[__i] = __dyn;
__dyn += _S_is_dyn(_Extents[__i]);
@@ -105,7 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
auto __se = _Extents[__r];
if (__se == dynamic_extent)
- return _M_dynamic_extents[_S_dynamic_index[__r]];
+ return _M_dyn_exts[_S_dynamic_index[__r]];
else
return __se;
}
@@ -114,12 +114,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr void
_M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept
{
- for(size_t __i = 0; __i < _S_rank_dynamic; ++__i)
+ for (size_t __i = 0; __i < _S_rank_dynamic; ++__i)
{
size_t __di = __i;
if constexpr (_OtherRank != _S_rank_dynamic)
__di = _S_dynamic_index_inv[__i];
- _M_dynamic_extents[__i] = _S_int_cast(__get_extent(__di));
+ _M_dyn_exts[__i] = _S_int_cast(__get_extent(__di));
}
}
@@ -144,9 +144,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __exts[__i]; });
}
+ static constexpr span<const size_t>
+ _S_static_extents(size_t __begin, size_t __end) noexcept
+ {
+ return {_Extents.data() + __begin, _Extents.data() + __end};
+ }
+
+ constexpr span<const _IndexType>
+ _M_dynamic_extents(size_t __begin, size_t __end) const noexcept
+ requires (_Extents.size() > 0)
+ {
+ return {_M_dyn_exts + _S_dynamic_index[__begin],
+ _M_dyn_exts + _S_dynamic_index[__end]};
+ }
+
private:
using _S_storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
- [[no_unique_address]] _S_storage _M_dynamic_extents{};
+ [[no_unique_address]] _S_storage _M_dyn_exts{};
};
template<typename _OIndexType, typename _SIndexType>
@@ -160,6 +174,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|| _Extent <= numeric_limits<_IndexType>::max();
}
+ namespace __mdspan
+ {
+ template<typename _Extents>
+ constexpr span<const size_t>
+ __static_extents(size_t __begin = 0, size_t __end = _Extents::rank())
+ noexcept
+ { return _Extents::_S_storage::_S_static_extents(__begin, __end); }
+
+ template<typename _Extents>
+ constexpr span<const typename _Extents::index_type>
+ __dynamic_extents(const _Extents& __exts, size_t __begin = 0,
+ size_t __end = _Extents::rank()) noexcept
+ {
+ return __exts._M_exts._M_dynamic_extents(__begin, __end);
+ }
+ }
+
template<typename _IndexType, size_t... _Extents>
class extents
{
@@ -197,7 +228,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if constexpr (rank() == 0)
__builtin_trap();
else
- return _M_dynamic_extents._M_extent(__r);
+ return _M_exts._M_extent(__r);
}
constexpr
@@ -233,14 +264,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
requires (_S_is_compatible_extents<_OExtents...>())
constexpr explicit(_S_ctor_explicit<_OIndexType, _OExtents...>())
extents(const extents<_OIndexType, _OExtents...>& __other) noexcept
- : _M_dynamic_extents(__other._M_dynamic_extents)
+ : _M_exts(__other._M_exts)
{ }
template<__mdspan::__valid_index_type<index_type>... _OIndexTypes>
requires (sizeof...(_OIndexTypes) == rank()
|| sizeof...(_OIndexTypes) == rank_dynamic())
constexpr explicit extents(_OIndexTypes... __exts) noexcept
- : _M_dynamic_extents(span<const _IndexType, sizeof...(_OIndexTypes)>(
+ : _M_exts(span<const _IndexType, sizeof...(_OIndexTypes)>(
initializer_list{_S_storage::_S_int_cast(__exts)...}))
{ }
@@ -248,15 +279,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
requires (_Nm == rank() || _Nm == rank_dynamic())
constexpr explicit(_Nm != rank_dynamic())
extents(span<_OIndexType, _Nm> __exts) noexcept
- : _M_dynamic_extents(span<const _OIndexType, _Nm>(__exts))
+ : _M_exts(span<const _OIndexType, _Nm>(__exts))
{ }
-
template<__mdspan::__valid_index_type<index_type> _OIndexType, size_t _Nm>
requires (_Nm == rank() || _Nm == rank_dynamic())
constexpr explicit(_Nm != rank_dynamic())
extents(const array<_OIndexType, _Nm>& __exts) noexcept
- : _M_dynamic_extents(span<const _OIndexType, _Nm>(__exts))
+ : _M_exts(span<const _OIndexType, _Nm>(__exts))
{ }
template<typename _OIndexType, size_t... _OExtents>
@@ -276,9 +306,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
private:
+ friend span<const size_t>
+ __mdspan::__static_extents<extents>(size_t, size_t);
+
+ friend span<const index_type>
+ __mdspan::__dynamic_extents<extents>(const extents&, size_t, size_t);
+
using _S_storage = __mdspan::_ExtentsStorage<
_IndexType, array<size_t, sizeof...(_Extents)>{_Extents...}>;
- [[no_unique_address]] _S_storage _M_dynamic_extents;
+ [[no_unique_address]] _S_storage _M_exts;
template<typename _OIndexType, size_t... _OExtents>
friend class extents;
@@ -286,6 +322,69 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace __mdspan
{
+ template<typename _Tp, size_t _Nm>
+ constexpr bool
+ __contains_zero(span<_Tp, _Nm> __exts) noexcept
+ {
+ for (size_t __i = 0; __i < __exts.size(); ++__i)
+ if (__exts[__i] == 0)
+ return true;
+ return false;
+ }
+
+ template<typename _Extents>
+ constexpr bool
+ __empty(const _Extents& __exts) noexcept
+ {
+ if constexpr (__contains_zero(__static_extents<_Extents>()))
+ return true;
+ else if constexpr (_Extents::rank_dynamic() > 0)
+ return __contains_zero(__dynamic_extents(__exts));
+ else
+ return false;
+ }
+
+ constexpr size_t
+ __static_extents_prod(const auto& __sta_exts) noexcept
+ {
+ size_t __ret = 1;
+ for (auto __factor : __sta_exts)
+ if (__factor != dynamic_extent)
+ __ret *= __factor;
+ return __ret;
+ }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __exts_prod(const _Extents& __exts, size_t __begin, size_t __end) noexcept
+ {
+ using _IndexType = typename _Extents::index_type;
+
+ size_t __ret = 1;
+ if constexpr (_Extents::rank_dynamic() != _Extents::rank())
+ {
+ auto __sta_exts = __static_extents<_Extents>(__begin, __end);
+ __ret = __static_extents_prod(__sta_exts);
+ if (__ret == 0)
+ return 0;
+ }
+
+ if constexpr (_Extents::rank_dynamic() > 0)
+ for (auto __factor : __dynamic_extents(__exts, __begin, __end))
+ __ret *= size_t(__factor);
+ return _IndexType(__ret);
+ }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __fwd_prod(const _Extents& __exts, size_t __r) noexcept
+ { return __exts_prod(__exts, 0, __r); }
+
+ template<typename _Extents>
+ constexpr typename _Extents::index_type
+ __rev_prod(const _Extents& __exts, size_t __r) noexcept
+ { return __exts_prod(__exts, __r + 1, __exts.rank()); }
+
template<typename _IndexType, size_t... _Counts>
auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
-> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
@@ -304,6 +403,607 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit extents(_Integrals...) ->
extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>;
+ struct layout_left
+ {
+ template<typename _Extents>
+ class mapping;
+ };
+
+ struct layout_right
+ {
+ template<typename _Extents>
+ class mapping;
+ };
+
+ struct layout_stride
+ {
+ template<typename _Extents>
+ class mapping;
+ };
+
+ namespace __mdspan
+ {
+ template<typename _Tp>
+ constexpr bool __is_extents = false;
+
+ template<typename _IndexType, size_t... _Extents>
+ constexpr bool __is_extents<extents<_IndexType, _Extents...>> = true;
+
+ template<typename _Extents, typename... _Indices>
+ constexpr typename _Extents::index_type
+ __linear_index_left(const _Extents& __exts, _Indices... __indices)
+ noexcept
+ {
+ using _IndexType = typename _Extents::index_type;
+ _IndexType __res = 0;
+ if constexpr (sizeof...(__indices) > 0)
+ {
+ _IndexType __mult = 1;
+ auto __update = [&, __pos = 0u](_IndexType __idx) mutable
+ {
+ __res += __idx * __mult;
+ __mult *= __exts.extent(__pos);
+ ++__pos;
+ };
+ (__update(__indices), ...);
+ }
+ return __res;
+ }
+
+ template<typename _Extents,
+ typename _IndexType = typename _Extents::index_type>
+ consteval _IndexType
+ __static_quotient(_IndexType __nom = numeric_limits<_IndexType>::max())
+ {
+ auto __sta_exts = __static_extents<_Extents>();
+ for (auto __factor : __sta_exts)
+ {
+ if (__factor != dynamic_extent)
+ __nom /= _IndexType(__factor);
+ if (__nom == 0)
+ break;
+ }
+ return __nom;
+ }
+
+ template<typename _Extents>
+ constexpr bool
+ __is_representable_extents(const _Extents& __exts) noexcept
+ {
+ using _IndexType = _Extents::index_type;
+
+ if constexpr (__contains_zero(__static_extents<_Extents>()))
+ return true;
+ else
+ {
+ constexpr auto __sta_quo = __static_quotient<_Extents>();
+ if constexpr (_Extents::rank_dynamic() == 0)
+ return __sta_quo != 0;
+ else
+ {
+ auto __dyn_exts = __dynamic_extents(__exts);
+ if (__contains_zero(__dyn_exts))
+ return true;
+
+ if constexpr (__sta_quo == 0)
+ return false;
+ else
+ {
+ auto __dyn_quo = _IndexType(__sta_quo);
+ for (auto __factor : __dyn_exts)
+ {
+ __dyn_quo /= __factor;
+ if (__dyn_quo == 0)
+ return false;
+ }
+ return true;
+ }
+ }
+ }
+ }
+
+ template<typename _Extents, typename _IndexType>
+ concept __representable_size = _Extents::rank_dynamic() != 0
+ || __contains_zero(__static_extents<_Extents>())
+ || (__static_quotient<_Extents, _IndexType>() != 0);
+
+ template<typename _Layout, typename _Mapping>
+ concept __mapping_of =
+ is_same_v<typename _Layout::mapping<typename _Mapping::extents_type>,
+ _Mapping>;
+
+ template<typename _Mapping>
+ concept __standardized_mapping = __mapping_of<layout_left, _Mapping>
+ || __mapping_of<layout_right, _Mapping>
+ || __mapping_of<layout_stride, _Mapping>;
+
+ // A tag type to create internal ctors.
+ class __internal_ctor
+ { };
+ }
+
+ template<typename _Extents>
+ class layout_left::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 = layout_left;
+
+ static_assert(__mdspan::__representable_size<extents_type, index_type>,
+ "The size of extents_type must be representable as index_type");
+
+ constexpr
+ mapping() noexcept = default;
+
+ constexpr
+ mapping(const mapping&) noexcept = default;
+
+ constexpr
+ mapping(const extents_type& __extents) noexcept
+ : _M_extents(__extents)
+ { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
+
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { }
+
+ template<typename _OExtents>
+ requires (extents_type::rank() <= 1)
+ && is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const layout_right::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { }
+
+ // noexcept for consistency with other layouts.
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(extents_type::rank() > 0)
+ mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { __glibcxx_assert(*this == __other); }
+
+ constexpr mapping&
+ operator=(const mapping&) noexcept = default;
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_extents; }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); }
+
+ template<__mdspan::__valid_index_type<index_type>... _Indices>
+ requires (sizeof...(_Indices) == extents_type::rank())
+ constexpr index_type
+ operator()(_Indices... __indices) const noexcept
+ {
+ return __mdspan::__linear_index_left(_M_extents,
+ static_cast<index_type>(__indices)...);
+ }
+
+ static constexpr bool
+ is_always_unique() noexcept { return true; }
+
+ static constexpr bool
+ is_always_exhaustive() noexcept { return true; }
+
+ static constexpr bool
+ is_always_strided() noexcept { return true; }
+
+ static constexpr bool
+ is_unique() noexcept { return true; }
+
+ static constexpr bool
+ is_exhaustive() noexcept { return true; }
+
+ static constexpr bool
+ is_strided() noexcept { return true; }
+
+ constexpr index_type
+ stride(rank_type __i) const noexcept
+ requires (extents_type::rank() > 0)
+ {
+ __glibcxx_assert(__i < extents_type::rank());
+ return __mdspan::__fwd_prod(_M_extents, __i);
+ }
+
+ template<typename _OExtents>
+ requires (extents_type::rank() == _OExtents::rank())
+ friend constexpr bool
+ operator==(const mapping& __self, const mapping<_OExtents>& __other)
+ noexcept
+ { return __self.extents() == __other.extents(); }
+
+ private:
+ template<typename _OExtents>
+ constexpr explicit
+ mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
+ : _M_extents(__oexts)
+ {
+ static_assert(__mdspan::__representable_size<_OExtents, index_type>,
+ "The size of OtherExtents must be representable as index_type");
+ __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
+ }
+
+ [[no_unique_address]] extents_type _M_extents{};
+ };
+
+ namespace __mdspan
+ {
+ template<typename _Extents, typename... _Indices>
+ constexpr typename _Extents::index_type
+ __linear_index_right(const _Extents& __exts, _Indices... __indices)
+ noexcept
+ {
+ using _IndexType = typename _Extents::index_type;
+ array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...};
+ _IndexType __res = 0;
+ if constexpr (sizeof...(__indices) > 0)
+ {
+ _IndexType __mult = 1;
+ auto __update = [&, __pos = __exts.rank()](_IndexType) mutable
+ {
+ --__pos;
+ __res += __ind_arr[__pos] * __mult;
+ __mult *= __exts.extent(__pos);
+ };
+ (__update(__indices), ...);
+ }
+ return __res;
+ }
+ }
+
+ template<typename _Extents>
+ class layout_right::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 = layout_right;
+
+ static_assert(__mdspan::__representable_size<extents_type, index_type>,
+ "The size of extents_type must be representable as index_type");
+
+ constexpr
+ mapping() noexcept = default;
+
+ constexpr
+ mapping(const mapping&) noexcept = default;
+
+ constexpr
+ mapping(const extents_type& __extents) noexcept
+ : _M_extents(__extents)
+ { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); }
+
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { }
+
+ template<typename _OExtents>
+ requires (extents_type::rank() <= 1)
+ && is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(!is_convertible_v<_OExtents, extents_type>)
+ mapping(const layout_left::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { }
+
+ template<typename _OExtents>
+ requires is_constructible_v<extents_type, _OExtents>
+ constexpr explicit(extents_type::rank() > 0)
+ mapping(const layout_stride::mapping<_OExtents>& __other) noexcept
+ : mapping(__other.extents(), __mdspan::__internal_ctor{})
+ { __glibcxx_assert(*this == __other); }
+
+ constexpr mapping&
+ operator=(const mapping&) noexcept = default;
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_extents; }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); }
+
+ template<__mdspan::__valid_index_type<index_type>... _Indices>
+ requires (sizeof...(_Indices) == extents_type::rank())
+ constexpr index_type
+ operator()(_Indices... __indices) const noexcept
+ {
+ return __mdspan::__linear_index_right(
+ _M_extents, static_cast<index_type>(__indices)...);
+ }
+
+ static constexpr bool
+ is_always_unique() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_always_exhaustive() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_always_strided() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_unique() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_exhaustive() noexcept
+ { return true; }
+
+ static constexpr bool
+ is_strided() noexcept
+ { return true; }
+
+ constexpr index_type
+ stride(rank_type __i) const noexcept
+ requires (extents_type::rank() > 0)
+ {
+ __glibcxx_assert(__i < extents_type::rank());
+ return __mdspan::__rev_prod(_M_extents, __i);
+ }
+
+ template<typename _OExtents>
+ requires (extents_type::rank() == _OExtents::rank())
+ friend constexpr bool
+ operator==(const mapping& __self, const mapping<_OExtents>& __other)
+ noexcept
+ { return __self.extents() == __other.extents(); }
+
+ private:
+ template<typename _OExtents>
+ constexpr explicit
+ mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept
+ : _M_extents(__oexts)
+ {
+ static_assert(__mdspan::__representable_size<_OExtents, index_type>,
+ "The size of OtherExtents must be representable as index_type");
+ __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents));
+ }
+
+ [[no_unique_address]] extents_type _M_extents{};
+ };
+
+ namespace __mdspan
+ {
+ template<typename _Mp>
+ concept __mapping_alike = requires
+ {
+ requires __is_extents<typename _Mp::extents_type>;
+ { _Mp::is_always_strided() } -> same_as<bool>;
+ { _Mp::is_always_exhaustive() } -> same_as<bool>;
+ { _Mp::is_always_unique() } -> same_as<bool>;
+ bool_constant<_Mp::is_always_strided()>::value;
+ bool_constant<_Mp::is_always_exhaustive()>::value;
+ bool_constant<_Mp::is_always_unique()>::value;
+ };
+
+ template<typename _Mapping>
+ constexpr typename _Mapping::index_type
+ __offset(const _Mapping& __m) noexcept
+ {
+ using _IndexType = typename _Mapping::index_type;
+ constexpr auto __rank = _Mapping::extents_type::rank();
+
+ if constexpr (__standardized_mapping<_Mapping>)
+ return 0;
+ else if (__empty(__m.extents()))
+ return 0;
+ else
+ {
+ auto __impl = [&__m]<size_t... _Counts>(index_sequence<_Counts...>)
+ { return __m(((void) _Counts, _IndexType(0))...); };
+ return __impl(make_index_sequence<__rank>());
+ }
+ }
+
+ template<typename _Mapping, typename... _Indices>
+ constexpr typename _Mapping::index_type
+ __linear_index_strides(const _Mapping& __m, _Indices... __indices)
+ noexcept
+ {
+ using _IndexType = typename _Mapping::index_type;
+ _IndexType __res = 0;
+ if constexpr (sizeof...(__indices) > 0)
+ {
+ auto __update = [&, __pos = 0u](_IndexType __idx) mutable
+ {
+ __res += __idx * __m.stride(__pos++);
+ };
+ (__update(__indices), ...);
+ }
+ return __res;
+ }
+ }
+
+ template<typename _Extents>
+ class layout_stride::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 = layout_stride;
+
+ static_assert(__mdspan::__representable_size<extents_type, index_type>,
+ "The size of extents_type must be representable as index_type");
+
+ constexpr
+ mapping() noexcept
+ {
+ // The precondition is either statically asserted, or automatically
+ // satisfied because dynamic extents are zero-initialized.
+ size_t __stride = 1;
+ for (size_t __i = extents_type::rank(); __i > 0; --__i)
+ {
+ _M_strides[__i - 1] = index_type(__stride);
+ __stride *= size_t(_M_extents.extent(__i - 1));
+ }
+ }
+
+ constexpr
+ mapping(const mapping&) noexcept = default;
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType>
+ constexpr
+ mapping(const extents_type& __exts,
+ span<_OIndexType, extents_type::rank()> __strides) noexcept
+ : _M_extents(__exts)
+ {
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ _M_strides[__i] = index_type(as_const(__strides[__i]));
+ }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType>
+ constexpr
+ mapping(const extents_type& __exts,
+ const array<_OIndexType, extents_type::rank()>& __strides)
+ noexcept
+ : mapping(__exts,
+ span<const _OIndexType, extents_type::rank()>(__strides))
+ { }
+
+ template<__mdspan::__mapping_alike _StridedMapping>
+ requires (is_constructible_v<extents_type,
+ typename _StridedMapping::extents_type>
+ && _StridedMapping::is_always_unique()
+ && _StridedMapping::is_always_strided())
+ constexpr explicit(!(
+ is_convertible_v<typename _StridedMapping::extents_type, extents_type>
+ && __mdspan::__standardized_mapping<_StridedMapping>))
+ mapping(const _StridedMapping& __other) noexcept
+ : _M_extents(__other.extents())
+ {
+ using _OIndexType = _StridedMapping::index_type;
+ using _OExtents = _StridedMapping::extents_type;
+
+ __glibcxx_assert(__mdspan::__offset(__other) == 0);
+ static_assert(__mdspan::__representable_size<_OExtents, index_type>,
+ "The size of StridedMapping::extents_type must be representable as"
+ " index_type");
+ if constexpr (cmp_greater(numeric_limits<_OIndexType>::max(),
+ numeric_limits<index_type>::max()))
+ __glibcxx_assert(!cmp_less(numeric_limits<index_type>::max(),
+ __other.required_span_size())
+ && "other.required_span_size() must be representable"
+ " as index_type");
+ if constexpr (extents_type::rank() > 0)
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ _M_strides[__i] = index_type(__other.stride(__i));
+ }
+
+ constexpr mapping&
+ operator=(const mapping&) noexcept = default;
+
+ constexpr const extents_type&
+ extents() const noexcept { return _M_extents; }
+
+ constexpr array<index_type, extents_type::rank()>
+ strides() const noexcept
+ {
+ array<index_type, extents_type::rank()> __ret;
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ __ret[__i] = _M_strides[__i];
+ return __ret;
+ }
+
+ constexpr index_type
+ required_span_size() const noexcept
+ {
+ if (__mdspan::__empty(_M_extents))
+ return 0;
+
+ index_type __ret = 1;
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ __ret += (_M_extents.extent(__i) - 1) * _M_strides[__i];
+ return __ret;
+ }
+
+ template<__mdspan::__valid_index_type<index_type>... _Indices>
+ requires (sizeof...(_Indices) == extents_type::rank())
+ constexpr index_type
+ operator()(_Indices... __indices) const noexcept
+ {
+ return __mdspan::__linear_index_strides(*this,
+ static_cast<index_type>(__indices)...);
+ }
+
+ static constexpr bool
+ is_always_unique() noexcept { return true; }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4266. layout_stride::mapping should treat empty mappings as exhaustive
+ static constexpr bool
+ is_always_exhaustive() noexcept
+ {
+ return (_Extents::rank() == 0) || __mdspan::__contains_zero(
+ __mdspan::__static_extents<extents_type>());
+ }
+
+ static constexpr bool
+ is_always_strided() noexcept { return true; }
+
+ static constexpr bool
+ is_unique() noexcept { return true; }
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 4266. layout_stride::mapping should treat empty mappings as exhaustive
+ constexpr bool
+ is_exhaustive() const noexcept
+ {
+ if constexpr (!is_always_exhaustive())
+ {
+ constexpr auto __rank = extents_type::rank();
+ auto __size = __mdspan::__fwd_prod(_M_extents, __rank);
+ if(__size > 0)
+ return __size == required_span_size();
+ }
+ return true;
+ }
+
+ static constexpr bool
+ is_strided() noexcept { return true; }
+
+ constexpr index_type
+ stride(rank_type __r) const noexcept { return _M_strides[__r]; }
+
+ template<__mdspan::__mapping_alike _OMapping>
+ requires ((extents_type::rank() == _OMapping::extents_type::rank())
+ && _OMapping::is_always_strided())
+ friend constexpr bool
+ operator==(const mapping& __self, const _OMapping& __other) noexcept
+ {
+ if (__self.extents() != __other.extents())
+ return false;
+ if constexpr (extents_type::rank() > 0)
+ for (size_t __i = 0; __i < extents_type::rank(); ++__i)
+ if (!cmp_equal(__self.stride(__i), __other.stride(__i)))
+ return false;
+ return __mdspan::__offset(__other) == 0;
+ }
+
+ private:
+ using _S_strides_t = typename __array_traits<index_type,
+ extents_type::rank()>::_Type;
+ [[no_unique_address]] extents_type _M_extents;
+ [[no_unique_address]] _S_strides_t _M_strides;
+ };
+
_GLIBCXX_END_NAMESPACE_VERSION
}
#endif
diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional
index a616dc0..cc7af5b 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -36,6 +36,7 @@
#define __glibcxx_want_freestanding_optional
#define __glibcxx_want_optional
+#define __glibcxx_want_optional_range_support
#define __glibcxx_want_constrained_equality
#include <bits/version.h>
@@ -57,6 +58,11 @@
#if __cplusplus > 202002L
# include <concepts>
#endif
+#ifdef __cpp_lib_optional_range_support // C++ >= 26
+# include <bits/formatfwd.h>
+# include <bits/ranges_base.h>
+# include <bits/stl_iterator.h>
+#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -858,6 +864,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
using value_type = _Tp;
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional>;
+ using const_iterator = __gnu_cxx::__normal_iterator<const _Tp*, optional>;
+#endif
constexpr optional() noexcept { }
@@ -1158,6 +1168,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ // Iterator support.
+ constexpr iterator begin() noexcept
+ {
+ return iterator(
+ this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
+ );
+ }
+
+ constexpr const_iterator begin() const noexcept
+ {
+ return const_iterator(
+ this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr
+ );
+ }
+
+ constexpr iterator end() noexcept
+ {
+ return begin() + has_value();
+ }
+
+ constexpr const_iterator end() const noexcept
+ {
+ return begin() + has_value();
+ }
+#endif // __cpp_lib_optional_range_support
+
// Observers.
constexpr const _Tp*
operator->() const noexcept
@@ -1772,6 +1809,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template <typename _Tp> optional(_Tp) -> optional<_Tp>;
#endif
+#ifdef __cpp_lib_optional_range_support // >= C++26
+ template<typename _Tp>
+ inline constexpr bool
+ ranges::enable_view<optional<_Tp>> = true;
+
+ template<typename _Tp>
+ inline constexpr range_format
+ format_kind<optional<_Tp>> = range_format::disabled;
+#endif // __cpp_lib_optional_range_support
+
#undef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL
_GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index c8907fe..abff9f8 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -1036,6 +1036,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __is_array_unknown_bounds<_Tp[]>
: public true_type
{ };
+ /// @endcond
// Destructible and constructible type properties.
@@ -1046,6 +1047,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __bool_constant<__is_destructible(_Tp)>
{ };
#else
+ /// @cond undocumented
+
// In N3290 is_destructible does not say anything about function
// types and abstract types, see LWG 2049. This implementation
// describes function types as non-destructible and all complete
diff --git a/libstdc++-v3/libsupc++/exception b/libstdc++-v3/libsupc++/exception
index 246c9b1..8c3bb33 100644
--- a/libstdc++-v3/libsupc++/exception
+++ b/libstdc++-v3/libsupc++/exception
@@ -164,9 +164,9 @@ _GLIBCXX_END_NAMESPACE_VERSION
} // extern "C++"
-#if (__cplusplus >= 201103L)
-#include <bits/exception_ptr.h>
-#include <bits/nested_exception.h>
+#if __cplusplus >= 201103L
+# include <bits/exception_ptr.h>
+# include <bits/nested_exception.h>
#endif
#endif
diff --git a/libstdc++-v3/scripts/create_testsuite_files b/libstdc++-v3/scripts/create_testsuite_files
index 174c24e..ae259c6 100755
--- a/libstdc++-v3/scripts/create_testsuite_files
+++ b/libstdc++-v3/scripts/create_testsuite_files
@@ -3,9 +3,7 @@
# Constructs lists of source files (full pathnames) to test. Two
# files are constructed: testsuite_files, which is used to test with
# the default dg-runtest command, and testsuite_files_interactive,
-# which is used to test cases that require input to be entered. In
-# addition, both lists are pruned of wchar_t tests if the toolchain
-# under test does not support wchar_t functionality.
+# which is used to test cases that require input to be entered.
#
# We mimic the mkcheck script in that the first time this is run, all
# existing files are listed in "testsuite_files" in the output
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index 4cd3e52..109f590 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -1840,7 +1840,10 @@ export namespace std
export namespace std
{
using std::extents;
- // FIXME layout_*, default_accessor and mdspan
+ using std::layout_left;
+ using std::layout_right;
+ using std::layout_stride;
+ // FIXME layout_left_padded, layout_right_padded, default_accessor and mdspan
}
#endif
diff --git a/libstdc++-v3/testsuite/17_intro/names.cc b/libstdc++-v3/testsuite/17_intro/names.cc
index f32205d..e94da9d 100644
--- a/libstdc++-v3/testsuite/17_intro/names.cc
+++ b/libstdc++-v3/testsuite/17_intro/names.cc
@@ -404,4 +404,8 @@
# endif
#endif
+// PR libstdc++/119496
+// _Temporary_buffer used to have a member with this name
+#define requested_size 1
+
#include <bits/stdc++.h>
diff --git a/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization.cc b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization.cc
index 256b84d..59af024 100644
--- a/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization.cc
+++ b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization.cc
@@ -23,7 +23,7 @@ struct X;
static_assert(
!std::__is_complete_or_unbounded(std::__type_identity<X>{}), "error");
-struct X{};
+struct X{}; // { dg-warning Wsfinae-incomplete }
static_assert(
std::__is_complete_or_unbounded(std::__type_identity<X>{}),
"Result memoized. This leads to worse diagnostics");
diff --git a/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc
index 8e207b5..264efa7 100644
--- a/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc
@@ -25,5 +25,5 @@
struct X;
constexpr bool res_incomplete = std::is_move_constructible<X>::value; // { dg-error "required from here" }
-struct X{};
+struct X{}; // { dg-warning Wsfinae-incomplete }
constexpr bool res_complete = std::is_default_constructible<X>::value; // { dg-bogus "required from here" }
diff --git a/libstdc++-v3/testsuite/20_util/optional/range.cc b/libstdc++-v3/testsuite/20_util/optional/range.cc
new file mode 100644
index 0000000..e77dc21
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/range.cc
@@ -0,0 +1,163 @@
+// { dg-do compile { target c++26 } }
+
+#include <concepts>
+#include <format>
+#include <iterator>
+#include <optional>
+#include <ranges>
+#include <string_view>
+#include <vector>
+
+#include <testsuite_hooks.h>
+
+template<typename O>
+constexpr
+void
+test_range_concepts()
+{
+ static_assert(std::ranges::contiguous_range<O>);
+ static_assert(std::ranges::sized_range<O>);
+ static_assert(std::ranges::common_range<O>);
+ static_assert(!std::ranges::borrowed_range<O>);
+
+ // an optional<const T> is not assignable, and therefore does not satisfy ranges::view
+ using T = typename O::value_type;
+ constexpr bool is_const_opt = std::is_const_v<T>;
+ static_assert(std::ranges::view<O> == !is_const_opt);
+ static_assert(std::ranges::viewable_range<O> == !is_const_opt);
+}
+
+template<typename O>
+constexpr
+void
+test_iterator_concepts()
+{
+ using T = typename O::value_type;
+ using iterator = typename O::iterator;
+ static_assert(std::contiguous_iterator<iterator>);
+ static_assert(std::is_same_v<typename std::iterator_traits<iterator>::value_type, std::remove_cv_t<T>>);
+ static_assert(std::is_same_v<std::iter_value_t<iterator>, std::remove_cv_t<T>>);
+ static_assert(std::is_same_v<typename std::iterator_traits<iterator>::reference, T&>);
+ static_assert(std::is_same_v<std::iter_reference_t<iterator>, T&>);
+
+ using const_iterator = typename O::const_iterator;
+ static_assert(std::contiguous_iterator<const_iterator>);
+ static_assert(std::is_same_v<typename std::iterator_traits<const_iterator>::value_type, std::remove_cv_t<T>>);
+ static_assert(std::is_same_v<std::iter_value_t<const_iterator>, std::remove_cv_t<T>>);
+ static_assert(std::is_same_v<typename std::iterator_traits<const_iterator>::reference, const T&>);
+ static_assert(std::is_same_v<std::iter_reference_t<const_iterator>, const T&>);
+}
+
+template<typename O>
+constexpr
+void
+test_empty()
+{
+ O empty;
+ VERIFY(!empty);
+ VERIFY(empty.begin() == empty.end());
+ VERIFY(std::as_const(empty).begin() == std::as_const(empty).end());
+ VERIFY(std::ranges::empty(empty));
+ VERIFY(std::ranges::empty(std::as_const(empty)));
+ VERIFY(std::ranges::empty(empty | std::views::as_const));
+ VERIFY(std::ranges::size(empty) == 0);
+ VERIFY(std::ranges::size(std::as_const(empty)) == 0);
+
+ size_t count = 0;
+ for (const auto& x : empty)
+ ++count;
+ VERIFY(count == 0);
+}
+
+template<typename O, typename T>
+constexpr
+void
+test_non_empty(const T& value)
+{
+ O non_empty = std::make_optional(value);
+ VERIFY(non_empty);
+ VERIFY(*non_empty == value);
+ VERIFY(non_empty.begin() != non_empty.end());
+ VERIFY(non_empty.begin() < non_empty.end());
+ VERIFY(std::as_const(non_empty).begin() != std::as_const(non_empty).end());
+ VERIFY(std::as_const(non_empty).begin() < std::as_const(non_empty).end());
+ VERIFY(!std::ranges::empty(non_empty));
+ VERIFY(!std::ranges::empty(std::as_const(non_empty)));
+ VERIFY(!std::ranges::empty(non_empty | std::views::as_const));
+ VERIFY(std::ranges::size(non_empty) == 1);
+ VERIFY(std::ranges::size(std::as_const(non_empty)) == 1);
+
+ size_t count = 0;
+ for (const auto& x : non_empty)
+ ++count;
+ VERIFY(count == 1);
+
+ if constexpr (!std::is_const_v<typename O::value_type>) {
+ for (auto& x : non_empty)
+ x = T{};
+ VERIFY(non_empty);
+ VERIFY(*non_empty == T{});
+ }
+}
+
+template<typename T>
+constexpr
+void
+test(const T& value)
+{
+ using O = std::optional<T>;
+ test_range_concepts<O>();
+ test_iterator_concepts<O>();
+ test_empty<O>();
+ test_non_empty<O>(value);
+ static_assert(!std::formattable<O, char>);
+ static_assert(!std::formattable<O, wchar_t>);
+ static_assert(std::format_kind<O> == std::range_format::disabled);
+}
+
+constexpr
+void
+range_chain_example() // from P3168
+{
+ std::vector<int> v{2, 3, 4, 5, 6, 7, 8, 9, 1};
+ auto test = [](int i) -> std::optional<int> {
+ switch(i) {
+ case 1:
+ case 3:
+ case 7:
+ case 9:
+ return i * 2;
+ default:
+ return {};
+ }
+ };
+
+ auto result = v
+ | std::views::transform(test)
+ | std::views::filter([](auto x) { return bool(x); })
+ | std::views::transform([](auto x){ return *x; })
+ | std::ranges::to<std::vector>();
+
+ bool ok = result == std::vector<int>{6, 14, 18, 2};
+ VERIFY(ok);
+}
+
+constexpr
+bool
+all_tests()
+{
+ test(42);
+ int i = 42;
+ test(&i);
+ test(std::string_view("test"));
+ test(std::vector<int>{1, 2, 3, 4});
+ test(std::optional<int>(42));
+ test<const int>(42);
+
+ range_chain_example();
+
+ return true;
+}
+
+static_assert(all_tests());
+
diff --git a/libstdc++-v3/testsuite/20_util/optional/version.cc b/libstdc++-v3/testsuite/20_util/optional/version.cc
index 657a399..ba44aa5 100644
--- a/libstdc++-v3/testsuite/20_util/optional/version.cc
+++ b/libstdc++-v3/testsuite/20_util/optional/version.cc
@@ -21,8 +21,17 @@
#endif
#endif
+#if __cplusplus > 202302L
+# ifndef __cpp_lib_optional_range_support
+# error "Feature test macro for optional range support is missing in <version>"
+# elif __cpp_lib_optional_range_support != 202406L
+# error "Feature test macro for optional range support has wrong value for C++26 in <version>"
+# endif
+#endif
+
#undef __cpp_lib_optional
#undef __cpp_lib_freestanding_optional
+#undef __cpp_lib_optional_range_support
#include <optional>
#if __cplusplus >= 202302L
@@ -32,3 +41,12 @@
# error "Feature test macro for freestanding std::optional has wrong value in <optional>"
#endif
#endif
+
+#if __cplusplus > 202302L
+# ifndef __cpp_lib_optional_range_support
+# error "Feature test macro for optional range support is missing in <optional>"
+# endif
+# if __cpp_lib_optional_range_support != 202406L
+# error "Feature test macro for optional range support has wrong value for C++26 in <optional>"
+# endif
+#endif
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/120397.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/120397.cc
new file mode 100644
index 0000000..7aa05d7
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_default_construct/120397.cc
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++17 } }
+
+#include <memory>
+
+// PR libstdc++/120397
+// std::uninitialized_value_construct cannot create arrays of non-trivially
+// destructible types
+
+struct X { X() { } ~X() { } };
+
+void def(X (*x)[1])
+{
+ std::uninitialized_default_construct(x, x+1);
+}
+
+void def_n(X (*x)[1])
+{
+ std::uninitialized_default_construct_n(x, 1);
+}
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/120397.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/120397.cc
new file mode 100644
index 0000000..f4d9fce
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_value_construct/120397.cc
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++17 } }
+
+#include <memory>
+
+// PR libstdc++/120397
+// std::uninitialized_value_construct cannot create arrays of non-trivially
+// destructible types
+
+struct X { X() { } ~X() { } };
+
+void val(X (*x)[1])
+{
+ std::uninitialized_value_construct(x, x+1);
+}
+
+void val_n(X (*x)[1])
+{
+ std::uninitialized_value_construct_n(x, 1);
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_default.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_default.cc
index eec300f..f45d3e5 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_default.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_default.cc
@@ -15,7 +15,7 @@ template<typename Extents>
if(exts.static_extent(i) == std::dynamic_extent)
VERIFY(exts.extent(i) == 0);
else
- VERIFY(exts.extent(i) == Extents::static_extent(i));
+ VERIFY(std::cmp_equal(exts.extent(i), Extents::static_extent(i)));
}
constexpr bool
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
new file mode 100644
index 0000000..7091153
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/class_mandate_neg.cc
@@ -0,0 +1,48 @@
+// { dg-do compile { target c++23 } }
+#include<mdspan>
+
+#include <cstdint>
+
+constexpr size_t dyn = std::dynamic_extent;
+static constexpr size_t n = std::numeric_limits<uint8_t>::max() / 2;
+
+template<typename Layout>
+ struct A
+ {
+ typename Layout::mapping<std::extents<uint8_t, n, 2>> m0;
+ typename Layout::mapping<std::extents<uint8_t, n, 2, dyn>> m1;
+ typename Layout::mapping<std::extents<uint8_t, n, 2, 0>> m2;
+
+ using extents_type = std::extents<uint8_t, n, 4>;
+ typename Layout::mapping<extents_type> m3; // { dg-error "required from" }
+ };
+
+template<size_t Count, typename Layout, typename OLayout>
+ bool
+ B()
+ {
+ using Extents = std::extents<uint8_t, dyn, dyn, Count>;
+ using OExtents = std::extents<uint16_t, n, 4, Count>;
+
+ using Mapping = typename Layout::mapping<Extents>;
+ using OMapping = typename OLayout::mapping<OExtents>;
+
+ Mapping m{OMapping{}};
+ return true;
+ };
+
+A<std::layout_left> a_left; // { dg-error "required from" }
+A<std::layout_right> a_right; // { dg-error "required from" }
+A<std::layout_stride> a_stride; // { dg-error "required from" }
+
+auto b1 = B<1, std::layout_left, std::layout_left>(); // { dg-error "required from" }
+auto b2 = B<2, std::layout_left, std::layout_stride>(); // { dg-error "required from" }
+
+auto b3 = B<3, std::layout_right, std::layout_right>(); // { dg-error "required from" }
+auto b4 = B<4, std::layout_right, std::layout_stride>(); // { dg-error "required from" }
+
+auto b5 = B<5, std::layout_stride, std::layout_right>(); // { dg-error "required from" }
+auto b6 = B<6, std::layout_stride, std::layout_left>(); // { dg-error "required from" }
+auto b7 = B<7, std::layout_stride, std::layout_stride>(); // { dg-error "required from" }
+
+// { dg-prune-output "must be representable as index_type" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
new file mode 100644
index 0000000..23c0a55
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/ctors.cc
@@ -0,0 +1,436 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <cstdint>
+#include <testsuite_hooks.h>
+
+constexpr size_t dyn = std::dynamic_extent;
+
+template<typename Mapping, typename IndexType, size_t... Extents>
+ constexpr void
+ verify(std::extents<IndexType, Extents...> oexts)
+ {
+ auto m = Mapping(oexts);
+ VERIFY(m.extents() == oexts);
+ }
+
+template<typename Mapping, typename OMapping>
+ requires (requires { typename OMapping::layout_type; })
+ constexpr void
+ verify(OMapping other)
+ {
+ constexpr auto rank = Mapping::extents_type::rank();
+ auto m = Mapping(other);
+ VERIFY(m.extents() == other.extents());
+ if constexpr (rank > 0)
+ for(size_t i = 0; i < rank; ++i)
+ VERIFY(std::cmp_equal(m.stride(i), other.stride(i)));
+ }
+
+
+template<typename To, typename From>
+ constexpr void
+ verify_convertible(From from)
+ {
+ static_assert(std::is_convertible_v<From, To>);
+ verify<To>(from);
+ }
+
+template<typename To, typename From>
+ constexpr void
+ verify_nothrow_convertible(From from)
+ {
+ static_assert(std::is_nothrow_constructible_v<To, From>);
+ verify_convertible<To>(from);
+ }
+
+template<typename To, typename From>
+ constexpr void
+ verify_constructible(From from)
+ {
+ static_assert(!std::is_convertible_v<From, To>);
+ static_assert(std::is_constructible_v<To, From>);
+ verify<To>(from);
+ }
+
+template<typename To, typename From>
+ constexpr void
+ verify_nothrow_constructible(From from)
+ {
+ static_assert(std::is_nothrow_constructible_v<To, From>);
+ verify_constructible<To>(from);
+ }
+
+template<typename Mapping, typename OExtents>
+ constexpr void
+ assert_not_constructible()
+ {
+ static_assert(!std::is_constructible_v<Mapping, OExtents>);
+ }
+
+// ctor: mapping()
+namespace default_ctor
+{
+ template<typename Layout, typename Extents>
+ constexpr void
+ test_default_ctor()
+ {
+ using Mapping = typename Layout::mapping<Extents>;
+
+ Mapping m;
+ for(size_t i = 0; i < Extents::rank(); ++i)
+ if (Extents::static_extent(i) == std::dynamic_extent)
+ VERIFY(m.extents().extent(i) == 0);
+ else
+ VERIFY(m.extents().static_extent(i) == Extents::static_extent(i));
+ }
+
+ template<typename Layout>
+ constexpr bool
+ test_default_ctor_all()
+ {
+ test_default_ctor<Layout, std::extents<int, dyn>>();
+ test_default_ctor<Layout, std::extents<int, 1, 2>>();
+ test_default_ctor<Layout, std::extents<int, dyn, 2>>();
+ test_default_ctor<Layout, std::extents<int, dyn, dyn>>();
+ test_default_ctor<Layout, std::extents<int, dyn, 2, dyn>>();
+ test_default_ctor<Layout, std::extents<int, dyn, dyn, dyn>>();
+ return true;
+ }
+
+ template<typename Layout>
+ constexpr void
+ test_all()
+ {
+ test_default_ctor_all<Layout>();
+ static_assert(test_default_ctor_all<Layout>());
+ }
+}
+
+// ctor: mapping(const extents&)
+namespace from_extents
+{
+ template<typename Layout, typename Extents, typename OExtents>
+ constexpr void
+ verify_nothrow_convertible(OExtents oexts)
+ {
+ using Mapping = typename Layout::mapping<Extents>;
+ ::verify_nothrow_convertible<Mapping>(oexts);
+ }
+
+ template<typename Layout, typename Extents, typename OExtents>
+ constexpr void
+ verify_nothrow_constructible(OExtents oexts)
+ {
+ using Mapping = typename Layout::mapping<Extents>;
+ ::verify_nothrow_constructible<Mapping>(oexts);
+ }
+
+ template<typename Layout, typename Extents, typename OExtents>
+ constexpr void
+ assert_not_constructible()
+ {
+ using Mapping = typename Layout::mapping<Extents>;
+ ::assert_not_constructible<Mapping, OExtents>();
+ }
+
+ template<typename Layout>
+ constexpr bool
+ test_ctor()
+ {
+ verify_nothrow_convertible<Layout, std::extents<int>>(
+ std::extents<int>{});
+
+ verify_nothrow_convertible<Layout, std::extents<int, 2>>(
+ std::extents<int, 2>{});
+
+ verify_nothrow_convertible<Layout, std::extents<int, dyn, 3>>(
+ std::extents<int, dyn, 3>{2});
+
+ verify_nothrow_constructible<Layout, std::extents<unsigned int>>(
+ std::extents<int>{});
+
+ verify_nothrow_constructible<Layout, std::extents<int, dyn>>(
+ std::extents<int, 2>{});
+
+ verify_nothrow_constructible<Layout, std::extents<int, dyn, 3>>(
+ std::extents<int, 2, 3>{});
+
+ assert_not_constructible<Layout, std::extents<int>,
+ std::extents<unsigned int>>();
+ assert_not_constructible<Layout, std::extents<int, 2>,
+ std::extents<int, dyn>>();
+ assert_not_constructible<Layout, std::extents<int, 2, 3>,
+ std::extents<int, dyn, 3>>();
+ return true;
+ }
+
+ template<typename Layout, typename Extents>
+ constexpr void
+ assert_deducible(Extents exts)
+ {
+ typename Layout::mapping m(exts);
+ static_assert(std::same_as<decltype(m),
+ typename Layout::mapping<Extents>>);
+ }
+
+ template<typename Layout>
+ constexpr void
+ test_deducible()
+ {
+ assert_deducible<Layout>(std::extents<int>());
+ assert_deducible<Layout>(std::extents<int, 1>());
+ assert_deducible<Layout>(std::extents<int, 1, 2, dyn>(3));
+ }
+
+ template<typename Layout>
+ constexpr void
+ test_all()
+ {
+ test_ctor<Layout>();
+ static_assert(test_ctor<Layout>());
+ test_deducible<Layout>();
+ }
+}
+
+// ctor: mapping(mapping<OExtents>)
+namespace from_same_layout
+{
+ template<typename Layout, typename Extents, typename OExtents>
+ constexpr void
+ verify_nothrow_convertible(OExtents exts)
+ {
+ using Mapping = typename Layout::mapping<Extents>;
+ using OMapping = typename Layout::mapping<OExtents>;
+
+ ::verify_nothrow_convertible<Mapping>(OMapping(exts));
+ }
+
+ template<typename Layout, typename Extents, typename OExtents>
+ constexpr void
+ verify_nothrow_constructible(OExtents exts)
+ {
+ using Mapping = typename Layout::mapping<Extents>;
+ using OMapping = typename Layout::mapping<OExtents>;
+
+ ::verify_nothrow_constructible<Mapping>(OMapping(exts));
+ }
+
+ template<typename Layout>
+ constexpr bool
+ test_ctor()
+ {
+ verify_nothrow_convertible<Layout, std::extents<unsigned int>>(
+ std::extents<int>{});
+
+ verify_nothrow_constructible<Layout, std::extents<int>>(
+ std::extents<unsigned int>{});
+
+ assert_not_constructible<
+ typename Layout::mapping<std::extents<int>>,
+ typename Layout::mapping<std::extents<int, 1>>>();
+
+ assert_not_constructible<
+ typename Layout::mapping<std::extents<int, 1>>,
+ typename Layout::mapping<std::extents<int>>>();
+
+ verify_nothrow_constructible<Layout, std::extents<int, 1>>(
+ std::extents<int, dyn>{1});
+
+ verify_nothrow_convertible<Layout, std::extents<int, dyn>>(
+ std::extents<int, 1>{});
+
+ assert_not_constructible<
+ typename Layout::mapping<std::extents<int, 1, 2>>,
+ typename Layout::mapping<std::extents<int, 1>>>();
+
+ verify_nothrow_constructible<Layout, std::extents<int, 1, 2>>(
+ std::extents<int, dyn, 2>{1});
+
+ verify_nothrow_convertible<Layout, std::extents<int, dyn, 2>>(
+ std::extents<int, 1, 2>{});
+ return true;
+ }
+
+ template<typename Layout>
+ constexpr void
+ test_all()
+ {
+ test_ctor<Layout>();
+ static_assert(test_ctor<Layout>());
+ }
+}
+
+// ctor: mapping(layout_{right,left}::mapping<OExtents>)
+namespace from_left_or_right
+{
+ template<typename SLayout, typename OLayout, typename SExtents,
+ typename OExtents>
+ constexpr void
+ verify_ctor(OExtents oexts)
+ {
+ using SMapping = typename SLayout::mapping<SExtents>;
+ using OMapping = typename OLayout::mapping<OExtents>;
+
+ constexpr bool expected = std::is_convertible_v<OExtents, SExtents>;
+ if constexpr (expected)
+ verify_nothrow_convertible<SMapping>(OMapping(oexts));
+ else
+ verify_nothrow_constructible<SMapping>(OMapping(oexts));
+ }
+
+ template<typename SLayout, typename OLayout>
+ constexpr bool
+ test_ctor()
+ {
+ assert_not_constructible<
+ typename SLayout::mapping<std::extents<int>>,
+ typename OLayout::mapping<std::extents<int, 1>>>();
+
+ verify_ctor<OLayout, SLayout, std::extents<int>>(
+ std::extents<unsigned int>{});
+
+ verify_ctor<OLayout, SLayout, std::extents<unsigned int>>(
+ std::extents<int>{});
+
+ assert_not_constructible<
+ typename SLayout::mapping<std::extents<int, 1>>,
+ typename OLayout::mapping<std::extents<int>>>();
+
+ verify_ctor<OLayout, SLayout, std::extents<int, 1>>(
+ std::extents<int, 1>{});
+
+ verify_ctor<OLayout, SLayout, std::extents<int, 1>>(
+ std::extents<unsigned int, 1>{});
+
+ verify_ctor<OLayout, SLayout, std::extents<unsigned int, 1>>(
+ std::extents<int, 1>{});
+
+ assert_not_constructible<
+ typename SLayout::mapping<std::extents<int, 1, 2>>,
+ typename OLayout::mapping<std::extents<int, 1, 2>>>();
+ return true;
+ }
+
+ template<typename SLayout, typename OLayout>
+ constexpr void
+ test_all()
+ {
+ test_ctor<SLayout, OLayout>();
+ static_assert(test_ctor<SLayout, OLayout>());
+ }
+}
+
+// ctor: mapping(layout_stride::mapping<OExtents>)
+namespace from_stride
+{
+ template<typename Mapping>
+ constexpr auto
+ strides(Mapping m)
+ {
+ constexpr auto rank = Mapping::extents_type::rank();
+ std::array<typename Mapping::index_type, rank> s;
+
+ if constexpr (rank > 0)
+ for(size_t i = 0; i < rank; ++i)
+ s[i] = m.stride(i);
+ return s;
+ }
+
+ template<typename Layout, typename Extents, typename OExtents>
+ constexpr void
+ verify_nothrow_convertible(OExtents oexts)
+ {
+ using Mapping = typename Layout::mapping<Extents>;
+ using OMapping = std::layout_stride::mapping<OExtents>;
+
+ constexpr auto other = OMapping(oexts, strides(Mapping(Extents(oexts))));
+ ::verify_nothrow_convertible<Mapping>(other);
+ }
+
+ template<typename Layout, typename Extents, typename OExtents>
+ constexpr void
+ verify_nothrow_constructible(OExtents oexts)
+ {
+ using Mapping = typename Layout::mapping<Extents>;
+ using OMapping = std::layout_stride::mapping<OExtents>;
+
+ constexpr auto other = OMapping(oexts, strides(Mapping(Extents(oexts))));
+ ::verify_nothrow_constructible<Mapping>(other);
+ }
+
+ template<typename Layout>
+ constexpr bool
+ test_ctor()
+ {
+ assert_not_constructible<
+ typename Layout::mapping<std::extents<int>>,
+ std::layout_stride::mapping<std::extents<int, 1>>>();
+
+ assert_not_constructible<
+ typename Layout::mapping<std::extents<int, 1>>,
+ std::layout_stride::mapping<std::extents<int>>>();
+
+ assert_not_constructible<
+ typename Layout::mapping<std::extents<int, 2>>,
+ std::layout_stride::mapping<std::extents<int, 1>>>();
+
+ verify_nothrow_convertible<Layout, std::extents<int>>(
+ std::extents<int>{});
+
+ verify_nothrow_convertible<Layout, std::extents<unsigned int>>(
+ std::extents<int>{});
+
+ // Rank == 0 doesn't check IndexType for convertibility.
+ verify_nothrow_convertible<Layout, std::extents<int>>(
+ std::extents<unsigned int>{});
+
+ verify_nothrow_constructible<Layout, std::extents<int, 3>>(
+ std::extents<int, 3>{});
+
+ verify_nothrow_constructible<Layout, std::extents<unsigned int, 3>>(
+ std::extents<int, 3>{});
+
+ verify_nothrow_constructible<Layout, std::extents<int, 3>>(
+ std::extents<unsigned int, 3>{});
+
+ verify_nothrow_constructible<Layout, std::extents<int, 3, 5>>(
+ std::extents<int, 3, 5>{});
+
+ verify_nothrow_constructible<Layout, std::extents<unsigned int, 3, 5>>(
+ std::extents<int, 3, 5>{});
+
+ verify_nothrow_constructible<Layout, std::extents<int, 3, 5>>(
+ std::extents<unsigned int, 3, 5>{});
+ return true;
+ }
+
+ template<typename Layout>
+ constexpr void
+ test_all()
+ {
+ test_ctor<Layout>();
+ static_assert(test_ctor<Layout>());
+ }
+}
+
+template<typename Layout>
+ constexpr void
+ test_all()
+ {
+ default_ctor::test_all<Layout>();
+ from_extents::test_all<Layout>();
+ from_same_layout::test_all<Layout>();
+ from_stride::test_all<Layout>();
+ }
+
+int
+main()
+{
+ test_all<std::layout_left>();
+ test_all<std::layout_right>();
+
+ from_left_or_right::test_all<std::layout_left, std::layout_right>();
+ from_left_or_right::test_all<std::layout_right, std::layout_left>();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc
new file mode 100644
index 0000000..655b9b6
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/empty.cc
@@ -0,0 +1,131 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <cstdint>
+#include <algorithm>
+#include <testsuite_hooks.h>
+
+constexpr size_t dyn = std::dynamic_extent;
+
+template<typename Mapping>
+ constexpr void
+ invoke_stride(Mapping m)
+ {
+ // Only checking for UB, e.g. signed overflow.
+ for(size_t i = 0; i < Mapping::extents_type::rank(); ++i)
+ m.stride(i);
+ }
+
+template<typename Mapping>
+ constexpr void
+ verify_required_span_size(Mapping m)
+ { VERIFY(m.required_span_size() == 0); }
+
+template<typename Mapping>
+ constexpr void
+ verify_all(Mapping m)
+ {
+ verify_required_span_size(m);
+ invoke_stride(m);
+ }
+
+template<typename Layout, typename Int>
+constexpr void
+test_static_overflow()
+{
+ constexpr Int n1 = std::numeric_limits<Int>::max();
+ constexpr size_t n2 = std::dynamic_extent - 1;
+ constexpr size_t n = std::cmp_less(n1, n2) ? size_t(n1) : n2;
+
+ verify_all(typename Layout::mapping<std::extents<Int, n, n, 0, n, n>>{});
+ verify_all(typename Layout::mapping<std::extents<Int, 0, n, n, n>>{});
+ verify_all(typename Layout::mapping<std::extents<Int, dyn, n, n, n>>{});
+ verify_all(typename Layout::mapping<std::extents<Int, n, n, n, 0>>{});
+ verify_all(typename Layout::mapping<std::extents<Int, n, n, n, dyn>>{});
+}
+
+template<typename Int, size_t N>
+constexpr std::array<Int, N>
+make_strides()
+{
+ std::array<Int, N> strides;
+ std::ranges::fill(strides, Int(1));
+ return strides;
+}
+
+template<typename Layout, typename Extents>
+constexpr typename Layout::mapping<Extents>
+make_mapping(Extents exts)
+{
+ using IndexType = typename Extents::index_type;
+ constexpr auto rank = Extents::rank();
+ constexpr auto strides = make_strides<IndexType, rank>();
+
+ if constexpr (std::same_as<Layout, std::layout_stride>)
+ return typename Layout::mapping(exts, strides);
+ else
+ return typename Layout::mapping(exts);
+}
+
+template<typename Layout, typename Int>
+constexpr void
+test_dynamic_overflow()
+{
+ constexpr Int n1 = std::numeric_limits<Int>::max();
+ constexpr size_t n2 = std::dynamic_extent - 1;
+ constexpr Int n = std::cmp_less(n1, n2) ? n1 : Int(n2);
+
+ verify_all(make_mapping<Layout>(
+ std::extents<Int, dyn, dyn, 0, dyn, dyn>{n, n, n, n}));
+
+ verify_all(make_mapping<Layout>(
+ std::extents<Int, dyn, dyn, dyn, dyn, dyn>{n, n, 0, n, n}));
+
+ verify_all(make_mapping<Layout>(
+ std::extents<Int, dyn, dyn, dyn, 0>{n, n, n}));
+
+ verify_all(make_mapping<Layout>(
+ std::extents<Int, dyn, dyn, dyn, dyn>{n, n, n, 0}));
+
+ verify_all(make_mapping<Layout>(
+ std::extents<Int, 0, dyn, dyn, dyn>{n, n, n}));
+
+ verify_all(make_mapping<Layout>(
+ std::extents<Int, dyn, dyn, dyn, dyn>{0, n, n, n}));
+}
+
+template<typename Layout, typename Int>
+constexpr void
+test_overflow()
+{
+ test_static_overflow<Layout, Int>();
+ test_dynamic_overflow<Layout, Int>();
+}
+
+template<typename Layout>
+constexpr bool
+test_all()
+{
+ test_overflow<Layout, signed char>();
+ test_overflow<Layout, short int>();
+ test_overflow<Layout, int>();
+ test_overflow<Layout, long int>();
+ test_overflow<Layout, long long int>();
+
+ test_overflow<Layout, unsigned char>();
+ test_overflow<Layout, unsigned short int>();
+ test_overflow<Layout, unsigned int>();
+ test_overflow<Layout, unsigned long int>();
+ test_overflow<Layout, unsigned long long int>();
+ test_overflow<Layout, size_t>();
+ return true;
+}
+
+int
+main()
+{
+ static_assert(test_all<std::layout_left>());
+ static_assert(test_all<std::layout_right>());
+ static_assert(test_all<std::layout_stride>());
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
new file mode 100644
index 0000000..963c804
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/mapping.cc
@@ -0,0 +1,568 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <cstdint>
+#include <testsuite_hooks.h>
+
+constexpr size_t dyn = std::dynamic_extent;
+
+template<typename Layout, typename Extents>
+ constexpr bool
+ test_mapping_properties()
+ {
+ using M = typename Layout::mapping<Extents>;
+ static_assert(std::__mdspan::__is_extents<typename M::extents_type>);
+ static_assert(std::__mdspan::__mapping_alike<M>);
+ static_assert(std::copyable<M>);
+ static_assert(std::is_nothrow_move_constructible_v<M>);
+ static_assert(std::is_nothrow_move_assignable_v<M>);
+ static_assert(std::is_nothrow_swappable_v<M>);
+ static_assert(std::is_same_v<typename M::extents_type, Extents>);
+ static_assert(std::is_same_v<typename M::index_type,
+ typename M::extents_type::index_type>);
+ static_assert(std::is_same_v<typename M::size_type,
+ typename M::extents_type::size_type>);
+ static_assert(std::is_same_v<typename M::rank_type,
+ typename M::extents_type::rank_type>);
+ static_assert(std::is_same_v<typename M::layout_type, Layout>);
+
+ static_assert(std::is_trivially_copyable_v<M>);
+ static_assert(std::regular<M>);
+
+ static_assert(M::is_always_unique() && M::is_unique());
+ static_assert(M::is_always_strided() && M::is_strided());
+ if constexpr (!std::is_same_v<Layout, std::layout_stride>)
+ static_assert(M::is_always_exhaustive() && M::is_exhaustive());
+ return true;
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_mapping_properties_all()
+ {
+ test_mapping_properties<Layout, std::extents<int>>();
+ test_mapping_properties<Layout, std::extents<int, 1>>();
+ test_mapping_properties<Layout, std::extents<int, dyn>>();
+ test_mapping_properties<Layout, std::extents<int, dyn, dyn>>();
+ return true;
+ }
+
+// Check operator()(Indices...)
+template<typename Mapping, size_t N>
+ constexpr typename Mapping::index_type
+ linear_index(const Mapping& mapping,
+ const std::array<typename Mapping::index_type, N>& indices)
+ {
+ typename Mapping::index_type ret = 0;
+ for(size_t r = 0; r < indices.size(); ++r)
+ ret += indices[r] * mapping.stride(r);
+ return ret;
+ }
+
+template<typename Mapping, typename... Indices>
+ constexpr void
+ test_linear_index(const Mapping& m, Indices... i)
+ {
+ using index_type = typename Mapping::index_type;
+ index_type expected = linear_index(m, std::array{index_type(i)...});
+ VERIFY(m(i...) == expected);
+ VERIFY(m(uint8_t(i)...) == expected);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_linear_index_0d()
+ {
+ constexpr typename Layout::mapping<std::extents<int>> m;
+ VERIFY(m() == 0);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_linear_index_1d()
+ {
+ typename Layout::mapping<std::extents<int, 5>> m;
+ test_linear_index(m, 0);
+ test_linear_index(m, 1);
+ test_linear_index(m, 4);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_linear_index_2d()
+ {
+ typename Layout::mapping<std::extents<int, 3, 256>> m;
+ test_linear_index(m, 0, 0);
+ test_linear_index(m, 1, 0);
+ test_linear_index(m, 0, 1);
+ test_linear_index(m, 1, 1);
+ test_linear_index(m, 2, 4);
+ }
+
+template<typename Layout>
+ struct MappingFactory
+ {
+ template<typename Extents>
+ static constexpr typename Layout::mapping<Extents>
+ create(Extents exts)
+ { return exts; }
+ };
+
+template<>
+ struct MappingFactory<std::layout_stride>
+ {
+ template<typename Extents>
+ static constexpr std::layout_stride::mapping<Extents>
+ create(Extents exts)
+ {
+ if constexpr (Extents::rank() == 0)
+ {
+ auto strides = std::array<size_t, 0>{};
+ return std::layout_stride::mapping(exts, strides);
+ }
+ else if constexpr (Extents::rank() == 1)
+ {
+ auto strides = std::array<size_t, 1>{2};
+ return std::layout_stride::mapping(exts, strides);
+ }
+ else if constexpr (Extents::rank() == 2)
+ {
+ size_t m = exts.extent(1);
+ auto strides = std::array<size_t, 2>{3*m, 2};
+ return std::layout_stride::mapping(exts, strides);
+ }
+ else if constexpr (Extents::rank() == 3)
+ {
+ size_t n = exts.extent(0);
+ size_t m = exts.extent(1);
+ auto strides = std::array<size_t, 3>{3*m, 2, 11*m*n};
+ return std::layout_stride::mapping(exts, strides);
+ }
+ }
+ };
+
+template<typename Layout>
+ constexpr void
+ test_linear_index_3d()
+ {
+ auto m = MappingFactory<Layout>::create(std::extents(3, 5, 7));
+ test_linear_index(m, 0, 0, 0);
+ test_linear_index(m, 1, 0, 0);
+ test_linear_index(m, 0, 1, 0);
+ test_linear_index(m, 0, 0, 1);
+ test_linear_index(m, 1, 1, 0);
+ test_linear_index(m, 2, 4, 6);
+ }
+
+struct IntLikeA
+{
+ operator int()
+ { return 0; }
+};
+
+struct IntLikeB
+{
+ operator int() noexcept
+ { return 0; }
+};
+
+struct NotIntLike
+{ };
+
+template<typename Layout>
+ constexpr void
+ test_has_linear_index_0d()
+ {
+ using Mapping = typename Layout::mapping<std::extents<int>>;
+ static_assert(std::invocable<Mapping>);
+ static_assert(!std::invocable<Mapping, int>);
+ static_assert(!std::invocable<Mapping, IntLikeA>);
+ static_assert(!std::invocable<Mapping, IntLikeB>);
+ static_assert(!std::invocable<Mapping, NotIntLike>);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_has_linear_index_1d()
+ {
+ using Mapping = typename Layout::mapping<std::extents<int, 3>>;
+ static_assert(std::invocable<Mapping, int>);
+ static_assert(!std::invocable<Mapping>);
+ static_assert(!std::invocable<Mapping, IntLikeA>);
+ static_assert(std::invocable<Mapping, IntLikeB>);
+ static_assert(!std::invocable<Mapping, NotIntLike>);
+ static_assert(std::invocable<Mapping, double>);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_has_linear_index_2d()
+ {
+ using Mapping = typename Layout::mapping<std::extents<int, 3, 5>>;
+ static_assert(std::invocable<Mapping, int, int>);
+ static_assert(!std::invocable<Mapping, int>);
+ static_assert(!std::invocable<Mapping, IntLikeA, int>);
+ static_assert(std::invocable<Mapping, IntLikeB, int>);
+ static_assert(!std::invocable<Mapping, NotIntLike, int>);
+ static_assert(std::invocable<Mapping, double, double>);
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_linear_index_all()
+ {
+ test_linear_index_0d<Layout>();
+ test_linear_index_1d<Layout>();
+ test_linear_index_2d<Layout>();
+ test_linear_index_3d<Layout>();
+ test_has_linear_index_0d<Layout>();
+ test_has_linear_index_1d<Layout>();
+ test_has_linear_index_2d<Layout>();
+ return true;
+ }
+
+template<typename Mapping>
+ constexpr typename Mapping::index_type
+ linear_index_end(Mapping m)
+ {
+ using index_type = typename Mapping::index_type;
+ constexpr size_t rank = Mapping::extents_type::rank();
+
+ auto impl = [m]<index_type... Counts>(
+ std::integer_sequence<index_type, Counts...>) -> index_type
+ {
+ auto exts = m.extents();
+ if(((exts.extent(Counts) == 0) || ...))
+ return 0;
+ return m((exts.extent(Counts) - 1)...) + 1;
+ };
+
+ return impl(std::make_integer_sequence<index_type, rank>());
+ }
+
+// Check required_span_size
+template<typename Mapping>
+ constexpr void
+ test_required_span_size(Mapping m)
+ { VERIFY(m.required_span_size() == linear_index_end(m)); }
+
+template<typename Layout>
+ constexpr void
+ test_required_span_size_0d()
+ {
+ typename Layout::mapping<std::extents<int>> m;
+ test_required_span_size(m);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_required_span_size_1d()
+ {
+ auto m = MappingFactory<Layout>::create(std::extents(3));
+ test_required_span_size(m);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_required_span_size_2d()
+ {
+ auto m = MappingFactory<Layout>::create(std::extents(3, 5));
+ test_required_span_size(m);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_required_span_size_3d()
+ {
+ auto m = MappingFactory<Layout>::create(std::extents(3, 5, 7));
+ test_required_span_size(m);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_required_span_size_zero_1d()
+ {
+ auto m = MappingFactory<Layout>::create(std::extents(3, 0));
+ test_required_span_size(m);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_required_span_size_zero_3d()
+ {
+ auto m = MappingFactory<Layout>::create(std::extents(3, 0, 7));
+ test_required_span_size(m);
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_required_span_size_all()
+ {
+ test_required_span_size_0d<Layout>();
+ test_required_span_size_1d<Layout>();
+ test_required_span_size_2d<Layout>();
+ test_required_span_size_3d<Layout>();
+ test_required_span_size_zero_1d<Layout>();
+ test_required_span_size_zero_3d<Layout>();
+ return true;
+ }
+
+// Check stride
+template<typename Layout>
+ constexpr void
+ test_stride_1d()
+ {
+ std::layout_left::mapping<std::extents<int, 3>> m;
+ VERIFY(m.stride(0) == 1);
+ }
+
+template<>
+ constexpr void
+ test_stride_1d<std::layout_stride>()
+ {
+ std::array<int, 1> strides{13};
+ std::layout_stride::mapping m(std::extents<int, 3>{}, strides);
+ VERIFY(m.stride(0) == strides[0]);
+ VERIFY(m.strides() == strides);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_stride_2d();
+
+template<>
+ constexpr void
+ test_stride_2d<std::layout_left>()
+ {
+ std::layout_left::mapping<std::extents<int, 3, 5>> m;
+ VERIFY(m.stride(0) == 1);
+ VERIFY(m.stride(1) == 3);
+ }
+
+template<>
+ constexpr void
+ test_stride_2d<std::layout_right>()
+ {
+ std::layout_right::mapping<std::extents<int, 3, 5>> m;
+ VERIFY(m.stride(0) == 5);
+ VERIFY(m.stride(1) == 1);
+ }
+
+template<>
+ constexpr void
+ test_stride_2d<std::layout_stride>()
+ {
+ std::array<int, 2> strides{13, 2};
+ std::layout_stride::mapping m(std::extents<int, 3, 5>{}, strides);
+ VERIFY(m.stride(0) == strides[0]);
+ VERIFY(m.stride(1) == strides[1]);
+ VERIFY(m.strides() == strides);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_stride_3d();
+
+template<>
+ constexpr void
+ test_stride_3d<std::layout_left>()
+ {
+ std::layout_left::mapping m(std::dextents<int, 3>(3, 5, 7));
+ VERIFY(m.stride(0) == 1);
+ VERIFY(m.stride(1) == 3);
+ VERIFY(m.stride(2) == 3*5);
+ }
+
+template<>
+ constexpr void
+ test_stride_3d<std::layout_right>()
+ {
+ std::layout_right::mapping m(std::dextents<int, 3>(3, 5, 7));
+ VERIFY(m.stride(0) == 5*7);
+ VERIFY(m.stride(1) == 7);
+ VERIFY(m.stride(2) == 1);
+ }
+
+template<>
+ constexpr void
+ test_stride_3d<std::layout_stride>()
+ {
+ std::dextents<int, 3> exts(3, 5, 7);
+ std::array<int, 3> strides{11, 2, 41};
+ std::layout_stride::mapping<std::dextents<int, 3>> m(exts, strides);
+ VERIFY(m.stride(0) == strides[0]);
+ VERIFY(m.stride(1) == strides[1]);
+ VERIFY(m.stride(2) == strides[2]);
+ VERIFY(m.strides() == strides);
+ }
+
+template<typename Layout>
+ constexpr bool
+ test_stride_all()
+ {
+ test_stride_1d<Layout>();
+ test_stride_2d<Layout>();
+ test_stride_3d<Layout>();
+ return true;
+ }
+
+template<typename Mapping>
+ concept has_stride = requires (Mapping m)
+ {
+ { m.stride(0) } -> std::same_as<typename Mapping::index_type>;
+ };
+
+template<typename Layout>
+ constexpr void
+ test_has_stride_0d()
+ {
+ using Mapping = typename Layout::mapping<std::extents<int>>;
+ constexpr bool expected = std::is_same_v<Layout, std::layout_stride>;
+ static_assert(has_stride<Mapping> == expected);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_has_stride_1d()
+ { static_assert(has_stride<typename Layout::mapping<std::extents<int, 1>>>); }
+
+template<typename Layout>
+ constexpr void
+ test_has_stride_2d()
+ {
+ using Extents = std::extents<int, 1, 2>;
+ static_assert(has_stride<typename Layout::mapping<Extents>>);
+ }
+
+// Check operator==
+template<typename Layout>
+ constexpr void
+ test_eq()
+ {
+ typename Layout::mapping<std::extents<int, 1, 2>> m1;
+ typename Layout::mapping<std::extents<int, 2, 2>> m2;
+ typename Layout::mapping<std::dextents<int, 2>> m3(m1);
+
+ VERIFY(m1 == m1);
+ VERIFY(m1 != m2);
+ VERIFY(m1 == m3);
+ VERIFY(m2 != m3);
+ }
+
+template<typename Layout>
+ constexpr void
+ test_eq_zero()
+ {
+ typename Layout::mapping<std::extents<int, 0, 2>> m1;
+ typename Layout::mapping<std::extents<int, 0, 2>> m2;
+ typename Layout::mapping<std::extents<int, 2, 0>> m3;
+
+ VERIFY(m1 == m2);
+ VERIFY(m1 != m3);
+ }
+
+template<typename M1, typename M2>
+ concept has_op_eq = requires (M1 m1, M2 m2)
+ {
+ { m1 == m2 } -> std::same_as<bool>;
+ { m2 == m1 } -> std::same_as<bool>;
+ { m1 != m2 } -> std::same_as<bool>;
+ { m2 != m1 } -> std::same_as<bool>;
+ };
+
+template<typename SLayout, typename OLayout, bool Expected>
+ constexpr void
+ test_has_op_eq()
+ {
+ static_assert(has_op_eq<
+ typename SLayout::mapping<std::extents<int>>,
+ typename OLayout::mapping<std::extents<int>>> == Expected);
+
+ static_assert(!has_op_eq<
+ typename SLayout::mapping<std::extents<int>>,
+ typename OLayout::mapping<std::extents<int, 1>>>);
+
+ static_assert(has_op_eq<
+ typename SLayout::mapping<std::extents<int, 1>>,
+ typename OLayout::mapping<std::extents<int, 1>>> == Expected);
+
+ static_assert(has_op_eq<
+ typename SLayout::mapping<std::extents<int, 1>>,
+ typename OLayout::mapping<std::extents<int, 2>>> == Expected);
+
+ static_assert(!has_op_eq<
+ typename SLayout::mapping<std::extents<int, 1>>,
+ typename OLayout::mapping<std::extents<int, 1, 2>>>);
+
+ static_assert(has_op_eq<
+ typename SLayout::mapping<std::extents<int, 1, 2>>,
+ typename OLayout::mapping<std::extents<int, 1, 2>>> == Expected);
+
+ static_assert(has_op_eq<
+ typename SLayout::mapping<std::extents<int, 1, 2>>,
+ typename OLayout::mapping<std::extents<int, 2, 2>>> == Expected);
+
+ static_assert(!has_op_eq<
+ typename SLayout::mapping<std::extents<int, 1, 2>>,
+ typename OLayout::mapping<std::extents<int, 1, 2, 3>>>);
+ }
+
+constexpr void
+test_has_op_eq_peculiar()
+{
+ static_assert(has_op_eq<
+ std::layout_right::mapping<std::extents<int>>,
+ std::layout_left::mapping<std::extents<unsigned int>>>);
+
+ static_assert(has_op_eq<
+ std::layout_right::mapping<std::extents<int, 1>>,
+ std::layout_left::mapping<std::extents<int, dyn>>>);
+
+ static_assert(!has_op_eq<
+ std::layout_right::mapping<std::extents<int, 1, 2>>,
+ std::layout_left::mapping<std::extents<int, dyn, 2>>>);
+}
+
+template<typename Layout>
+ constexpr bool
+ test_mapping_all()
+ {
+ test_linear_index_all<Layout>();
+ test_required_span_size_all<Layout>();
+ test_stride_all<Layout>();
+
+ test_eq<Layout>();
+ test_eq_zero<Layout>();
+ return true;
+ }
+
+template<typename Layout>
+ constexpr void
+ test_all()
+ {
+ static_assert(std::is_trivially_default_constructible_v<Layout>);
+ static_assert(std::is_trivially_copyable_v<Layout>);
+ static_assert(test_mapping_properties_all<Layout>());
+
+ test_mapping_all<Layout>();
+ static_assert(test_mapping_all<Layout>());
+
+ test_has_stride_0d<Layout>();
+ test_has_stride_1d<Layout>();
+ test_has_stride_2d<Layout>();
+ test_has_op_eq<Layout, Layout, true>();
+ }
+
+int
+main()
+{
+ test_all<std::layout_left>();
+ test_all<std::layout_right>();
+ test_all<std::layout_stride>();
+
+ test_has_op_eq<std::layout_right, std::layout_left, false>();
+ test_has_op_eq<std::layout_right, std::layout_stride, true>();
+ test_has_op_eq<std::layout_left, std::layout_stride, true>();
+ test_has_op_eq_peculiar();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
new file mode 100644
index 0000000..c8af5c6
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/stride.cc
@@ -0,0 +1,526 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+
+constexpr size_t dyn = std::dynamic_extent;
+
+template<typename MappingStride>
+ constexpr void
+ test_ctor_default_stride()
+ {
+ using Extents = typename MappingStride::extents_type;
+ MappingStride actual;
+ typename std::layout_right::mapping<Extents> expected;
+
+ constexpr auto rank = MappingStride::extents_type::rank();
+ if constexpr (rank > 0)
+ for(size_t i = 0; i < rank; ++i)
+ VERIFY(actual.stride(i) == expected.stride(i));
+ }
+
+constexpr bool
+test_ctor_default_stride_all()
+{
+ test_ctor_default_stride<
+ std::layout_stride::mapping<std::extents<int, 3>>>();
+
+ test_ctor_default_stride<
+ std::layout_stride::mapping<std::extents<int, 3, 5, 7>>>();
+
+ test_ctor_default_stride<
+ std::layout_stride::mapping<std::dextents<int, 3>>>();
+
+ test_ctor_default_stride<
+ std::layout_stride::mapping<std::extents<int, 0, 5, 7>>>();
+
+ test_ctor_default_stride<
+ std::layout_stride::mapping<std::extents<int, 3, dyn, dyn>>>();
+
+ test_ctor_default_stride<
+ std::layout_stride::mapping<std::extents<int, dyn, dyn, 3>>>();
+ return true;
+}
+
+struct IntLikeA
+{
+ operator int()
+ { return 0; }
+};
+
+struct IntLikeB
+{
+ operator int() noexcept
+ { return 0; }
+};
+
+struct NotIntLike
+{ };
+
+template<typename E, typename E_arg, typename T, size_t N, bool Expected>
+constexpr void
+test_stride_constructible()
+{
+ static_assert(std::is_nothrow_constructible_v<
+ std::layout_stride::mapping<E>, E_arg, std::span<T, N>> == Expected);
+ static_assert(std::is_nothrow_constructible_v<
+ std::layout_stride::mapping<E>, E_arg, std::array<T, N>> == Expected);
+ static_assert(!std::is_constructible_v<std::layout_stride::mapping<E>,
+ E_arg>);
+}
+
+constexpr void
+test_stride_constructible_all()
+{
+ using E0 = std::extents<int>;
+ using E1 = std::extents<int, 2>;
+ using E2 = std::extents<int, dyn>;
+
+ test_stride_constructible<E0, E0, int, 0, true>();
+ test_stride_constructible<E0, E0, IntLikeA, 0, false>();
+ test_stride_constructible<E0, E0, IntLikeB, 0, true>();
+ test_stride_constructible<E0, E0, NotIntLike, 0, false>();
+ test_stride_constructible<E1, E1, int, 1, true>();
+ test_stride_constructible<E2, E1, int, 1, true>();
+ test_stride_constructible<E1, E1, int, 2, false>();
+ test_stride_constructible<E1, E0, int, 1, false>();
+}
+
+template<typename Extents, typename Shape>
+ constexpr void
+ test_ctor_shape_strides(Extents exts, Shape strides)
+ {
+ using M = std::layout_stride::mapping<Extents>;
+ M m(exts, strides);
+
+ if constexpr (Extents::rank() > 0)
+ for(size_t i = 0; i < exts.rank(); ++i)
+ {
+ VERIFY(m.stride(i) == strides[i]);
+ VERIFY(m.extents().extent(i) == exts.extent(i));
+ }
+ }
+
+constexpr bool
+test_ctor_shape_stride_all()
+{
+ test_ctor_shape_strides(std::extents<int>{}, std::array<int, 0>{});
+ test_ctor_shape_strides(std::extents<int, 2>{}, std::array<int, 1>{3});
+ test_ctor_shape_strides(std::extents<int, 2, 4, 6>{},
+ std::array<int, 3>{20, 5, 45});
+ return true;
+}
+
+template<typename Extents, std::array<bool, 2> Strided,
+ std::array<bool, 2> Unique, std::array<bool, 2> Exhautive,
+ typename Extents::index_type Offset = 0>
+ struct MappingLike
+ {
+ using extents_type = Extents;
+ using index_type = typename Extents::index_type;
+
+ constexpr
+ MappingLike(extents_type extents,
+ std::array<index_type, Extents::rank()> strides)
+ : _extents(extents), _strides(strides)
+ { }
+
+ static constexpr bool
+ is_always_strided() requires (Strided[0])
+ { return Strided[1]; }
+
+ static constexpr bool
+ is_always_unique() requires (Unique[0])
+ { return Unique[1]; }
+
+ static constexpr bool
+ is_always_exhaustive() requires (Exhautive[0])
+ { return Exhautive[1]; }
+
+ constexpr Extents
+ extents() const { return _extents; }
+
+ constexpr index_type
+ stride(size_t i) const { return _strides[i]; }
+
+ template<typename... Indices>
+ constexpr index_type
+ operator()(Indices... indices) const
+ {
+ if (empty())
+ VERIFY(false);
+
+ std::array<index_type, Extents::rank()> ind_arr{indices...};
+ index_type ret = Offset;
+ for(size_t i = 0; i < Extents::rank(); ++i)
+ ret += ind_arr[i]*_strides[i];
+ return ret;
+ }
+
+ private:
+ constexpr bool
+ empty() const
+ {
+ for (size_t i = 0; i < extents_type::rank(); ++i)
+ if (_extents.extent(i) == 0)
+ return true;
+ return false;
+ }
+
+ Extents _extents;
+ std::array<index_type, Extents::rank()> _strides;
+ };
+
+
+template<size_t Rank>
+struct ExtentLike
+{
+ using index_type = int;
+
+ static constexpr size_t
+ rank() { return Rank; }
+};
+
+
+template<typename E1>
+constexpr void
+test_mapping_like_constructible()
+{
+ using M = std::layout_stride::mapping<E1>;
+ using E2 = std::dextents<typename E1::index_type, E1::rank()>;
+ using E3 = std::dextents<typename E1::index_type, E1::rank() + 1>;
+ using E4 = ExtentLike<E1::rank()>;
+
+ constexpr auto TT = std::array{true, true};
+ constexpr auto FT = std::array{false, true};
+ constexpr auto TF = std::array{true, false};
+
+ static_assert(std::is_constructible_v<M, MappingLike<E1, TT, TT, TT>>);
+ static_assert(std::is_constructible_v<M, MappingLike<E2, TT, TT, TT>>);
+ static_assert(!std::is_constructible_v<M, MappingLike<E3, TT, TT, TT>>);
+ static_assert(!std::is_constructible_v<M, MappingLike<E1, FT, TT, TT>>);
+ static_assert(!std::is_constructible_v<M, MappingLike<E1, TF, TT, TT>>);
+ static_assert(!std::is_constructible_v<M, MappingLike<E1, TT, FT, TT>>);
+ static_assert(!std::is_constructible_v<M, MappingLike<E1, TT, TF, TT>>);
+ static_assert(!std::is_constructible_v<M, MappingLike<E1, TT, TT, FT>>);
+ static_assert(std::is_constructible_v<M, MappingLike<E1, TT, TT, TF>>);
+ static_assert(!std::is_constructible_v<M, MappingLike<E4, TT, TT, TF>>);
+ static_assert(!std::is_constructible_v<M, MappingLike<E4, TT, TT, TT>>);
+}
+
+constexpr void
+test_mapping_like_constructible_all()
+{
+ test_mapping_like_constructible<std::extents<int>>();
+ test_mapping_like_constructible<std::extents<int, 2>>();
+ test_mapping_like_constructible<std::extents<int, 2, 3>>();
+}
+
+template<typename E1, typename E2>
+constexpr void
+test_mapping_like_convertible()
+{
+ using M1 = std::layout_stride::mapping<E1>;
+ using M2 = std::layout_stride::mapping<E2>;
+ constexpr auto TT = std::array{true, true};
+
+ static_assert(!std::is_convertible_v<MappingLike<E1, TT, TT, TT>, M1>);
+ static_assert(!std::is_convertible_v<MappingLike<E2, TT, TT, TT>, M1>);
+ static_assert(!std::is_convertible_v<MappingLike<E1, TT, TT, TT>, M2>);
+
+ static_assert(std::is_convertible_v<std::layout_stride::mapping<E2>, M1>);
+ static_assert(std::is_convertible_v<std::layout_left::mapping<E2>, M1>);
+ static_assert(std::is_convertible_v<std::layout_right::mapping<E2>, M1>);
+
+ static_assert(!std::is_convertible_v<std::layout_stride::mapping<E1>, M2>);
+ static_assert(!std::is_convertible_v<std::layout_left::mapping<E1>, M2>);
+ static_assert(!std::is_convertible_v<std::layout_right::mapping<E1>, M2>);
+}
+
+constexpr void
+test_mapping_like_convertible_all()
+{
+ test_mapping_like_convertible<std::extents<unsigned int>,
+ std::extents<int>>();
+ test_mapping_like_convertible<std::extents<unsigned int, 2>,
+ std::extents<int, 2>>();
+ test_mapping_like_convertible<std::extents<int, dyn, 3>,
+ std::extents<int, 2, 3>>();
+}
+
+template<typename Extents>
+constexpr void
+test_ctor_stride_like(Extents exts, std::array<int, Extents::rank()> strides)
+{
+ auto other_right = std::layout_right::mapping(exts);
+ auto other_left = std::layout_left::mapping(exts);
+ auto other_stride = std::layout_stride::mapping(exts, strides);
+
+ VERIFY(std::layout_stride::mapping<Extents>(other_right) == other_right);
+ VERIFY(std::layout_stride::mapping<Extents>(other_left) == other_left);
+ VERIFY(std::layout_stride::mapping<Extents>(other_stride) == other_stride);
+}
+
+constexpr void
+test_ctor_stride_like_all()
+{
+ using E1 = std::extents<int>;
+ auto s1 = std::array<int, 0>{};
+ test_ctor_stride_like(E1{}, s1);
+
+ using E2 = std::extents<int, 3>;
+ auto s2 = std::array<int, 1>{2};
+ test_ctor_stride_like(E2{}, s2);
+
+ using E3 = std::extents<int, 3, 5, 7>;
+ auto s3 = std::array<int, 3>{5, 1, 15};
+ test_ctor_stride_like(E3{}, s3);
+}
+
+constexpr bool
+test_ctor_strides_all()
+{
+ test_ctor_default_stride_all();
+ test_ctor_shape_stride_all();
+ test_ctor_stride_like_all();
+ return true;
+}
+
+// Check is_exhaustive.
+template<typename Extents, typename Strides>
+ constexpr void
+ test_is_exhaustive(Extents extents, Strides strides, bool expected)
+ {
+ std::layout_stride::mapping<Extents> m(extents, strides);
+ VERIFY(m.is_exhaustive() == expected);
+
+ bool always_exhaustive = extents.rank() == 0 || m.required_span_size() == 0;
+ VERIFY(m.is_always_exhaustive() == always_exhaustive);
+ }
+
+constexpr void
+test_is_exhaustive_zero_1d()
+{
+ std::extents<int, 0> extents;
+ test_is_exhaustive(extents, std::array{1}, true);
+ test_is_exhaustive(extents, std::array{2}, true);
+}
+
+constexpr void
+test_is_exhaustive_zero_3d()
+{
+ std::extents<int, 3, 0, 7> extents;
+
+ test_is_exhaustive(extents, std::array{1, 1, 1}, true);
+ test_is_exhaustive(extents, std::array{1, 2*21, 2*3}, true);
+ test_is_exhaustive(extents, std::array{7, 2*21, 1}, true);
+ test_is_exhaustive(extents, std::array{1, 21, 3}, true);
+ test_is_exhaustive(extents, std::array{7, 21, 1}, true);
+}
+
+constexpr void
+test_is_exhaustive_0d()
+{
+ std::extents<int> extents;
+ test_is_exhaustive(extents, std::array<int, 0>{}, true);
+}
+
+constexpr void
+test_is_exhaustive_1d()
+{
+ std::extents<int, 3> extents;
+ test_is_exhaustive(extents, std::array{1}, true);
+ test_is_exhaustive(extents, std::array{3}, false);
+}
+
+
+constexpr void
+test_is_exhaustive_3d()
+{
+ std::extents<int, 3, dyn, 7> extents(5);
+
+ test_is_exhaustive(extents, std::array{1, 3, 3*5}, true);
+ test_is_exhaustive(extents, std::array{5*7, 1, 5}, true);
+ test_is_exhaustive(extents, std::array{7, 3*7, 1}, true);
+
+ test_is_exhaustive(extents, std::array{1, 3, 2*3*5}, false);
+ test_is_exhaustive(extents, std::array{2*5*7, 1, 2*5}, false);
+ test_is_exhaustive(extents, std::array{2*7, 2*3*7, 2}, false);
+}
+
+constexpr void
+test_is_exhaustive_ones()
+{
+ std::extents<int, 1, 1, 3, 1> extents;
+ test_is_exhaustive(extents, std::array{1, 1, 1, 1}, true);
+ test_is_exhaustive(extents, std::array{1, 1, 1, 3}, true);
+ test_is_exhaustive(extents, std::array{3, 3, 1, 3}, true);
+ test_is_exhaustive(extents, std::array{3, 1, 1, 3}, true);
+}
+
+constexpr bool
+test_is_exhaustive_all()
+{
+ test_is_exhaustive_zero_1d();
+ test_is_exhaustive_zero_3d();
+ test_is_exhaustive_ones();
+ test_is_exhaustive_0d();
+ test_is_exhaustive_1d();
+ test_is_exhaustive_3d();
+ return true;
+}
+
+template<typename Extents, int Offset>
+ using OffsetMapping = MappingLike<Extents, {true, true}, {true, true},
+ {true, false}, Offset>;
+
+template<typename Extents>
+ constexpr void
+ test_eq(Extents exts,
+ std::array<typename Extents::index_type, Extents::rank()> left_strides,
+ std::array<typename Extents::index_type, Extents::rank()> right_strides,
+ std::array<typename Extents::index_type, Extents::rank()> padded_strides)
+ {
+ using DExtents = std::dextents<int, Extents::rank()>;
+
+ std::layout_left::mapping<Extents> ml;
+ std::layout_right::mapping<DExtents> mr(exts);
+
+ std::layout_stride::mapping<Extents> msd;
+ std::layout_stride::mapping<Extents> msl(exts, left_strides);
+ std::layout_stride::mapping<Extents> msr(exts, right_strides);
+ std::layout_stride::mapping<Extents> msp(exts, padded_strides);
+
+ OffsetMapping<Extents, 0> mor{exts, right_strides};
+ OffsetMapping<Extents, 0> mol{exts, left_strides};
+ OffsetMapping<Extents, 0> mop{exts, padded_strides};
+ OffsetMapping<Extents, 1> moo{exts, right_strides};
+
+ VERIFY(msd == mr);
+ VERIFY(msd == mor);
+ VERIFY(msd != msp);
+ VERIFY(msd != mop);
+
+ VERIFY(msl == ml);
+ VERIFY(msl == mol);
+ VERIFY(msd != msp);
+ VERIFY(msl != mop);
+
+ VERIFY(msp == mop);
+ VERIFY(msp != ml);
+ VERIFY(msp != mr);
+
+ VERIFY(msd != moo);
+ }
+
+constexpr void
+test_eq_0d()
+{
+ using Extents = std::extents<int>;
+ Extents exts;
+ std::layout_left::mapping<Extents> ml;
+ std::layout_right::mapping<Extents> mr;
+ std::layout_stride::mapping<Extents> ms;
+ OffsetMapping<Extents, 0> mor{exts, {}};
+ OffsetMapping<Extents, 1> moo{exts, {}};
+
+ VERIFY(ms == ml);
+ VERIFY(ms == mr);
+ VERIFY(ms == mor);
+ VERIFY(ms != moo);
+}
+
+constexpr void
+test_eq_1d()
+{
+ using Extents = std::extents<int, 2>;
+ auto exhaustive_strides = std::array{1};
+ auto padded_strides = std::array{2};
+
+ test_eq(Extents{}, exhaustive_strides, exhaustive_strides, padded_strides);
+}
+
+constexpr void
+test_eq_2d()
+{
+ using Extents = std::extents<int, 1, 2>;
+ auto left_strides = std::array{1, 1};
+ auto right_strides = std::array{2, 1};
+ auto padded_strides = std::array{2, 8};
+
+ test_eq(Extents{}, left_strides, right_strides, padded_strides);
+}
+
+constexpr void
+test_eq_zero()
+{
+ using Extents = std::extents<int, 0, 2>;
+ using Mapping = std::layout_stride::mapping<Extents>;
+
+ Extents exts;
+ std::array<int, 2> sl{1, 5};
+ std::array<int, 2> sr{5, 1};
+
+ Mapping m1(exts, sl);
+ Mapping m2(exts, sl);
+ Mapping m3(exts, sr);
+ OffsetMapping<Extents, 0> m4(exts, sl);
+
+ VERIFY(m1 == m2);
+ VERIFY(m1 != m3);
+ VERIFY(m1 == m4);
+
+}
+
+constexpr bool
+test_eq_all()
+{
+ test_eq_0d();
+ test_eq_1d();
+ test_eq_2d();
+ test_eq_zero();
+ return true;
+}
+
+template<typename M1, typename M2>
+ concept has_op_eq = requires (M1 m1, M2 m2)
+ {
+ { m1 == m2 } -> std::same_as<bool>;
+ { m2 == m1 } -> std::same_as<bool>;
+ { m1 != m2 } -> std::same_as<bool>;
+ { m2 != m1 } -> std::same_as<bool>;
+ };
+
+constexpr void
+test_has_op_eq()
+{
+ using E1 = std::extents<int>;
+ using E2 = std::extents<int, 2>;
+ using E3 = std::extents<int, 1, 2>;
+ constexpr auto FT = std::array{false, true};
+
+ static_assert(!has_op_eq<
+ std::layout_stride::mapping<E1>, MappingLike<E1, FT, FT, FT>>);
+
+ static_assert(!has_op_eq<
+ std::layout_stride::mapping<E2>, MappingLike<E2, FT, FT, FT>>);
+
+ static_assert(!has_op_eq<
+ std::layout_stride::mapping<E3>, MappingLike<E3, FT, FT, FT>>);
+}
+
+int
+main()
+{
+ test_ctor_strides_all();
+ static_assert(test_ctor_strides_all());
+ test_mapping_like_convertible_all();
+ test_mapping_like_constructible_all();
+ test_stride_constructible_all();
+ test_is_exhaustive_all();
+ static_assert(test_is_exhaustive_all());
+ test_eq_all();
+ static_assert(test_eq_all());
+ test_has_op_eq();
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/format.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/format.cc
index eb24b66..cecc535 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/bool/format.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/format.cc
@@ -21,7 +21,7 @@ is_format_string_for(const char* str, Args&&... args)
}
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
void
test_format_string()
@@ -34,11 +34,11 @@ test_format_string()
VERIFY( !is_format_string_for("{:{}}", v[0], 1.0f) );
}
-template<typename _CharT>
+template<typename CharT>
void
test_output()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
size_t size = 0;
std::vector<bool> v{true, false};
diff --git a/libstdc++-v3/testsuite/std/format/debug.cc b/libstdc++-v3/testsuite/std/format/debug.cc
index 965b4df..43e930c 100644
--- a/libstdc++-v3/testsuite/std/format/debug.cc
+++ b/libstdc++-v3/testsuite/std/format/debug.cc
@@ -26,13 +26,13 @@ fdebug(std::wstring_view t)
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
-template<typename _CharT>
+template<typename CharT>
void
test_basic_escapes()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const auto tab = WIDEN("\t");
res = fdebug(tab);
@@ -71,11 +71,11 @@ test_basic_escapes()
VERIFY( res == WIDEN(R"('\'')") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_ascii_escapes()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const auto in = WIDEN("\x10 abcde\x7f\t0123");
res = fdebug(in);
@@ -88,11 +88,11 @@ test_ascii_escapes()
VERIFY( res == WIDEN(R"('a')") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_extended_ascii()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const auto in = WIDEN("Åëÿ");
res = fdebug(in);
@@ -100,7 +100,7 @@ test_extended_ascii()
static constexpr bool __test_characters
#if UNICODE_ENC
- = sizeof(_CharT) >= 2;
+ = sizeof(CharT) >= 2;
#else // ISO8859-1
= true;
#endif // UNICODE_ENC
@@ -116,12 +116,12 @@ test_extended_ascii()
}
}
-template<typename _CharT>
+template<typename CharT>
void
test_unicode_escapes()
{
#if UNICODE_ENC
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const auto in = WIDEN(
"\u008a" // Cc, Control, Line Tabulation Set,
@@ -143,7 +143,7 @@ test_unicode_escapes()
res = fdebug(in);
VERIFY( res == out );
- if constexpr (sizeof(_CharT) >= 2)
+ if constexpr (sizeof(CharT) >= 2)
{
res = fdebug(in[0]);
VERIFY( res == WIDEN(R"('\u{8a}')") );
@@ -157,7 +157,7 @@ test_unicode_escapes()
VERIFY( res == WIDEN(R"('\u{2029}')") );
}
- if constexpr (sizeof(_CharT) >= 4)
+ if constexpr (sizeof(CharT) >= 4)
{
res = fdebug(in[5]);
VERIFY( res == WIDEN("'\U0001f984'") );
@@ -165,25 +165,25 @@ test_unicode_escapes()
#endif // UNICODE_ENC
}
-template<typename _CharT>
+template<typename CharT>
void
test_grapheme_extend()
{
#if UNICODE_ENC
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const auto vin = WIDEN("o\u0302\u0323");
res = fdebug(vin);
VERIFY( res == WIDEN("\"o\u0302\u0323\"") );
- std::basic_string_view<_CharT> in = WIDEN("\t\u0302\u0323");
+ std::basic_string_view<CharT> in = WIDEN("\t\u0302\u0323");
res = fdebug(in);
VERIFY( res == WIDEN(R"("\t\u{302}\u{323}")") );
res = fdebug(in.substr(1));
VERIFY( res == WIDEN(R"("\u{302}\u{323}")") );
- if constexpr (sizeof(_CharT) >= 2)
+ if constexpr (sizeof(CharT) >= 2)
{
res = fdebug(in[1]);
VERIFY( res == WIDEN(R"('\u{302}')") );
@@ -191,13 +191,13 @@ test_grapheme_extend()
#endif // UNICODE_ENC
}
-template<typename _CharT>
+template<typename CharT>
void
test_replacement_char()
{
#if UNICODE_ENC
- std::basic_string<_CharT> repl = WIDEN("\uFFFD");
- std::basic_string<_CharT> res = fdebug(repl);
+ std::basic_string<CharT> repl = WIDEN("\uFFFD");
+ std::basic_string<CharT> res = fdebug(repl);
VERIFY( res == WIDEN("\"\uFFFD\"") );
repl = WIDEN("\uFFFD\uFFFD");
@@ -268,13 +268,13 @@ test_ill_formed_utf32()
#endif // UNICODE_ENC
}
-template<typename _CharT>
+template<typename CharT>
void
test_fill()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
- std::basic_string_view<_CharT> in = WIDEN("a\t\x10\u00ad");
+ std::basic_string_view<CharT> in = WIDEN("a\t\x10\u00ad");
res = std::format(WIDEN("{:10?}"), in.substr(0, 1));
VERIFY( res == WIDEN(R"("a" )") );
@@ -299,11 +299,11 @@ test_fill()
VERIFY( res == WIDEN(R"(="\u{ad}"=)") );
// width is 2
- std::basic_string_view<_CharT> in2 = WIDEN("\u1100");
+ std::basic_string_view<CharT> in2 = WIDEN("\u1100");
res = std::format(WIDEN("{:*^10?}"), in2);
VERIFY( res == WIDEN("***\"\u1100\"***") );
- if constexpr (sizeof(_CharT) >= 2)
+ if constexpr (sizeof(CharT) >= 2)
{
res = std::format(WIDEN("{:=^10?}"), in[3]);
VERIFY( res == WIDEN(R"(='\u{ad}'=)") );
@@ -314,14 +314,14 @@ test_fill()
#endif // UNICODE_ENC
}
-template<typename _CharT>
+template<typename CharT>
void
test_prec()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
// with ? escpaed presentation is copied to ouput, same as source
- std::basic_string_view<_CharT> in = WIDEN("a\t\x10\u00ad");
+ std::basic_string_view<CharT> in = WIDEN("a\t\x10\u00ad");
res = std::format(WIDEN("{:.2?}"), in.substr(0, 1));
VERIFY( res == WIDEN(R"("a)") );
@@ -335,7 +335,7 @@ test_prec()
res = std::format(WIDEN("{:.10?}"), in.substr(3));
VERIFY( res == WIDEN(R"("\u{ad}")") );
- std::basic_string_view<_CharT> in2 = WIDEN("\u1100");
+ std::basic_string_view<CharT> in2 = WIDEN("\u1100");
res = std::format(WIDEN("{:.3?}"), in2);
VERIFY( res == WIDEN("\"\u1100") );
#endif // UNICODE_ENC
@@ -759,38 +759,38 @@ private:
std::formatter<T, CharT> under;
};
-template<typename _CharT, typename StrT>
+template<typename CharT, typename StrT>
void
test_formatter_str()
{
- _CharT buf[]{ 'a', 'b', 'c', 0 };
+ CharT buf[]{ 'a', 'b', 'c', 0 };
DebugWrapper<StrT> in{ buf };
- std::basic_string<_CharT> res = std::format(WIDEN("{:?}"), in );
+ std::basic_string<CharT> res = std::format(WIDEN("{:?}"), in );
VERIFY( res == WIDEN(R"("abc")") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_formatter_arr()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
- DebugWrapper<_CharT[3]> in3{ 'a', 'b', 'c' };
+ DebugWrapper<CharT[3]> in3{ 'a', 'b', 'c' };
res = std::format(WIDEN("{:?}"), in3 );
VERIFY( res == WIDEN(R"("abc")") );
// We print all characters, including null-terminator
- DebugWrapper<_CharT[4]> in4{ 'a', 'b', 'c', 0 };
+ DebugWrapper<CharT[4]> in4{ 'a', 'b', 'c', 0 };
res = std::format(WIDEN("{:?}"), in4 );
VERIFY( res == WIDEN(R"("abc\u{0}")") );
}
-template<typename _CharT, typename SrcT>
+template<typename CharT, typename SrcT>
void
test_formatter_char()
{
DebugWrapper<SrcT> in{ 'a' };
- std::basic_string<_CharT> res = std::format(WIDEN("{:?}"), in);
+ std::basic_string<CharT> res = std::format(WIDEN("{:?}"), in);
VERIFY( res == WIDEN(R"('a')") );
}
diff --git a/libstdc++-v3/testsuite/std/format/formatter/120625.cc b/libstdc++-v3/testsuite/std/format/formatter/120625.cc
new file mode 100644
index 0000000..6b03af9
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/format/formatter/120625.cc
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++20 } }
+
+// Bug libstdc++/120625
+// std::formatter<__disabled> specializations cause errors in user code
+
+#include <format>
+
+enum X { };
+
+// A concept that cannot be used with incomplete types:
+template<typename T>
+concept is_X = !std::is_empty_v<T> && std::is_same_v<X, T>;
+
+// A valid program-defined specialization:
+template<typename T, typename C> requires is_X<T>
+struct std::formatter<T, C> : std::formatter<int, C> { };
+
+// Instantiate the program-defined formatter specialization:
+auto s = sizeof(std::formatter<X, char>);
diff --git a/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc b/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
index daa73aa..a4e2dfb 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/adaptors.cc
@@ -19,7 +19,7 @@ is_format_string_for(const char* str, Args&&... args)
}
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
template<template<typename Tp> class Adaptor>
void
@@ -66,13 +66,13 @@ template<typename T>
constexpr auto std::format_kind<NotFormattableCont<T>>
= std::range_format::disabled;
-template<typename _CharT,
+template<typename CharT,
template<typename Tp, typename Cont = std::vector<Tp>> class Adaptor>
void
test_output()
{
const std::vector<int> v{3, 2, 1};
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
Adaptor<int, std::vector<int>> q(std::from_range, v);
res = std::format(WIDEN("{}"), q);
@@ -88,9 +88,9 @@ test_output()
VERIFY( res == WIDEN("==[0x03, 0x02, 0x01]===") );
// Sequence output is always used
- Adaptor<_CharT, std::basic_string<_CharT>> qs(
+ Adaptor<CharT, std::basic_string<CharT>> qs(
std::from_range,
- std::basic_string_view<_CharT>(WIDEN("321")));
+ std::basic_string_view<CharT>(WIDEN("321")));
res = std::format(WIDEN("{}"), qs);
VERIFY( res == WIDEN("['3', '2', '1']") );
@@ -114,13 +114,13 @@ test_output()
res = std::format(WIDEN("{}"), mq);
VERIFY( res == WIDEN("[3, 2, 1]") );
- static_assert(!std::formattable<const Adaptor<MutFormat>, _CharT>);
+ static_assert(!std::formattable<const Adaptor<MutFormat>, CharT>);
- static_assert(!std::formattable<Adaptor<NoFormat>, _CharT>);
- static_assert(!std::formattable<const Adaptor<NoFormat>, _CharT>);
+ static_assert(!std::formattable<Adaptor<NoFormat>, CharT>);
+ static_assert(!std::formattable<const Adaptor<NoFormat>, CharT>);
// Formatter check if container is formattable, not container elements.
- static_assert(!std::formattable<Adaptor<int, NotFormattableCont<int>>, _CharT>);
+ static_assert(!std::formattable<Adaptor<int, NotFormattableCont<int>>, CharT>);
}
template<template<typename Tp, typename Cont = std::vector<Tp>> class Adaptor>
@@ -135,12 +135,12 @@ test_adaptor()
static_assert(!std::formattable<Adaptor<int>, char32_t>);
}
-template<typename _CharT>
+template<typename CharT>
void
test_compare()
{
const std::vector<int> v{3, 2, 1};
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
std::priority_queue<int, std::vector<int>, std::greater<>> q(
std::from_range, v);
diff --git a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
index 00ce9f6..d3e0897 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/formatter.cc
@@ -6,7 +6,7 @@
#include <vector>
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
template<typename T,
template<typename, typename> class Formatter = std::range_formatter>
@@ -22,7 +22,6 @@ struct std::formatter<MyVector<T, Formatter>, CharT>
{
constexpr formatter() noexcept
{
- using _CharT = CharT;
_formatter.set_brackets(WIDEN("<"), WIDEN(">"));
_formatter.set_separator(WIDEN("; "));
}
@@ -41,12 +40,12 @@ private:
Formatter<T, CharT> _formatter;
};
-template<typename _CharT, template<typename, typename> class Formatter>
+template<typename CharT, template<typename, typename> class Formatter>
void
test_default()
{
MyVector<int, Formatter> vec{1, 2, 3};
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{}"), vec);
VERIFY( res == WIDEN("<1; 2; 3>") );
@@ -93,13 +92,13 @@ test_default()
VERIFY( res == WIDEN("< +1 ; +2 ; +3 >") );
}
-template<typename _CharT, template<typename, typename> class Formatter>
+template<typename CharT, template<typename, typename> class Formatter>
void
test_override()
{
- MyVector<_CharT, Formatter> vc{'a', 'b', 'c', 'd'};
+ MyVector<CharT, Formatter> vc{'a', 'b', 'c', 'd'};
MyVector<std::pair<int, int>, Formatter> vp{{1, 11}, {2, 21}};
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{:s}"), vc);
VERIFY( res == WIDEN("abcd") );
diff --git a/libstdc++-v3/testsuite/std/format/ranges/map.cc b/libstdc++-v3/testsuite/std/format/ranges/map.cc
index 1838480..5e1b98f 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/map.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/map.cc
@@ -57,7 +57,7 @@ bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
}
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
void
test_format_string()
@@ -83,10 +83,10 @@ test_format_string()
VERIFY( !is_format_string_for("{:{}m}", std::vector<std::pair<int, int>>(), 1.0f) );
}
-template<typename _CharT, typename Range>
+template<typename CharT, typename Range>
void test_output(bool mapIsDefault)
{
- using Sv = std::basic_string_view<_CharT>;
+ using Sv = std::basic_string_view<CharT>;
using Pt = std::ranges::range_value_t<Range>;
using Ft = std::remove_cvref_t<std::tuple_element_t<0, Pt>>;
using St = std::remove_cvref_t<std::tuple_element_t<1, Pt>>;
@@ -94,7 +94,7 @@ void test_output(bool mapIsDefault)
return Range(s.data(), s.data() + s.size());
};
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
size_t size = 0;
Ft f1[]{1, 2, 3};
diff --git a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
index 3224286..7fb65f9 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
@@ -76,12 +76,12 @@ test_format_string()
}
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
-template<typename _CharT, typename Range, typename Storage>
+template<typename CharT, typename Range, typename Storage>
void test_output()
{
- using Sv = std::basic_string_view<_CharT>;
+ using Sv = std::basic_string_view<CharT>;
using T = std::ranges::range_value_t<Range>;
auto makeRange = [](Storage& s) -> Range {
if constexpr (std::is_same_v<std::remove_cvref_t<Range>, Storage>)
@@ -91,7 +91,7 @@ void test_output()
std::ranges::data(s) + std::ranges::size(s));
};
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
size_t size = 0;
Storage v1{1, 2, 3};
diff --git a/libstdc++-v3/testsuite/std/format/ranges/string.cc b/libstdc++-v3/testsuite/std/format/ranges/string.cc
index cebdd53..99e5eaf 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/string.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/string.cc
@@ -48,7 +48,7 @@ bool is_range_formatter_spec_for(CharT const* spec, Rg&& rg)
}
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
void
test_format_string()
@@ -81,14 +81,14 @@ test_format_string()
template<typename Range>
void test_output()
{
- using _CharT = std::ranges::range_value_t<Range>;
- auto makeRange = [](std::basic_string<_CharT>& s) {
+ using CharT = std::ranges::range_value_t<Range>;
+ auto makeRange = [](std::basic_string<CharT>& s) {
return Range(s.data(), s.data() + s.size());
};
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
size_t size = 0;
- std::basic_string<_CharT> s1 = WIDEN("abcd");
+ std::basic_string<CharT> s1 = WIDEN("abcd");
res = std::format(WIDEN("{}"), makeRange(s1));
VERIFY( res == WIDEN("['a', 'b', 'c', 'd']") );
@@ -122,7 +122,7 @@ void test_output()
res = std::format(WIDEN("{:=^8s}"), makeRange(s1));
VERIFY( res == WIDEN("==abcd==") );
- std::basic_string<_CharT> s2(512, static_cast<_CharT>('a'));
+ std::basic_string<CharT> s2(512, static_cast<CharT>('a'));
res = std::format(WIDEN("{:=^8s}"), makeRange(s2));
VERIFY( res == s2 );
diff --git a/libstdc++-v3/testsuite/std/format/tuple.cc b/libstdc++-v3/testsuite/std/format/tuple.cc
index ff0359b..ba6dae8 100644
--- a/libstdc++-v3/testsuite/std/format/tuple.cc
+++ b/libstdc++-v3/testsuite/std/format/tuple.cc
@@ -39,7 +39,7 @@ is_format_string_for(const wchar_t* str, Args&&... args)
}
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
void
test_format_string()
@@ -62,13 +62,13 @@ test_format_string()
VERIFY( !is_format_string_for("{:{}}", std::tuple<>(), 1.0f) );
}
-template<typename _CharT>
+template<typename CharT>
void test_multi()
{
- using Sv = std::basic_string_view<_CharT>;
- using Str = std::basic_string<_CharT>;
+ using Sv = std::basic_string_view<CharT>;
+ using Str = std::basic_string<CharT>;
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
std::size_t size = 0;
std::tuple<int, Str, float> t1(1, WIDEN("test"), 2.1);
@@ -122,10 +122,10 @@ void test_multi()
}
-template<typename _CharT, typename Tuple>
+template<typename CharT, typename Tuple>
void test_empty()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
Tuple e1;
res = std::format(WIDEN("{}"), e1);
@@ -141,13 +141,13 @@ void test_empty()
VERIFY( res == WIDEN(R"(^^^^())") );
}
-template<typename _CharT, typename Pair>
+template<typename CharT, typename Pair>
void test_pair()
{
using Ft = std::remove_cvref_t<std::tuple_element_t<0, Pair>>;
using St = std::remove_cvref_t<std::tuple_element_t<1, Pair>>;
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
Ft f1 = 1;
St s1 = WIDEN("abc");
@@ -187,7 +187,6 @@ struct std::formatter<MyPair<Pair>, CharT>
{
constexpr formatter() noexcept
{
- using _CharT = CharT;
_formatter.set_brackets(WIDEN("<"), WIDEN(">"));
_formatter.set_separator(WIDEN("; "));
}
@@ -206,11 +205,11 @@ private:
std::formatter<Pair, CharT> _formatter;
};
-template<typename _CharT, template<typename, typename> class PairT>
+template<typename CharT, template<typename, typename> class PairT>
void test_custom()
{
- std::basic_string<_CharT> res;
- MyPair<PairT<int, const _CharT*>> c1(1, WIDEN("abc"));
+ std::basic_string<CharT> res;
+ MyPair<PairT<int, const CharT*>> c1(1, WIDEN("abc"));
res = std::format(WIDEN("{}"), c1);
VERIFY( res == WIDEN(R"(<1; "abc">)") );
diff --git a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
index a94eee1..5f7b868 100644
--- a/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
+++ b/libstdc++-v3/testsuite/std/time/format/empty_spec.cc
@@ -10,7 +10,7 @@
using namespace std::chrono;
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
template<typename CharT, typename T>
void
@@ -34,15 +34,15 @@ test_no_empty_spec()
}
}
-template<typename T, typename _CharT>
-void verify(const T& t, std::basic_string_view<_CharT> str)
+template<typename T, typename CharT>
+void verify(const T& t, std::basic_string_view<CharT> str)
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{}"), t);
VERIFY( res == str );
- std::basic_stringstream<_CharT> os;
+ std::basic_stringstream<CharT> os;
os << t;
res = std::move(os).str();
VERIFY( res == str );
@@ -52,11 +52,11 @@ template<typename T, typename CharT>
void verify(const T& t, const CharT* str)
{ verify(t, std::basic_string_view<CharT>(str)); }
-template<typename _CharT>
+template<typename CharT>
void
test_padding()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{:5}"), day(2));
VERIFY( res == WIDEN("02 ") );
@@ -114,9 +114,9 @@ struct Rep
friend auto operator<=>(Rep, Rep) = default;
- template<typename _CharT>
- friend std::basic_ostream<_CharT>&
- operator<<(std::basic_ostream<_CharT>& os, const Rep& t)
+ template<typename CharT>
+ friend std::basic_ostream<CharT>&
+ operator<<(std::basic_ostream<CharT>& os, const Rep& t)
{ return os << t.val << WIDEN("[via <<]"); }
long val;
@@ -140,27 +140,27 @@ struct std::numeric_limits<Rep<Ret>>
: std::numeric_limits<long>
{ };
-template<typename Ret, typename _CharT>
-struct std::formatter<Rep<Ret>, _CharT>
- : std::formatter<long, _CharT>
+template<typename Ret, typename CharT>
+struct std::formatter<Rep<Ret>, CharT>
+ : std::formatter<long, CharT>
{
template<typename Out>
- typename std::basic_format_context<Out, _CharT>::iterator
- format(const Rep<Ret>& t, std::basic_format_context<Out, _CharT>& ctx) const
+ typename std::basic_format_context<Out, CharT>::iterator
+ format(const Rep<Ret>& t, std::basic_format_context<Out, CharT>& ctx) const
{
- constexpr std::basic_string_view<_CharT> suffix = WIDEN("[via format]");
- auto out = std::formatter<long, _CharT>::format(t.val, ctx);
+ constexpr std::basic_string_view<CharT> suffix = WIDEN("[via format]");
+ auto out = std::formatter<long, CharT>::format(t.val, ctx);
return std::ranges::copy(suffix, out).out;
}
};
using deciseconds = duration<seconds::rep, std::deci>;
-template<typename _CharT>
+template<typename CharT>
void
test_duration()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const milliseconds di(40);
verify( di, WIDEN("40ms") );
@@ -172,11 +172,11 @@ test_duration()
VERIFY( res == WIDEN(" -40ms") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_duration_fp()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const duration<double> df(11.22);
verify( df, WIDEN("11.22s") );
@@ -192,11 +192,11 @@ test_duration_fp()
VERIFY( res == WIDEN("11.22s") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_duration_cust()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const duration<char, std::ratio<1, 10>> charRep(123);
verify( charRep, WIDEN("123ds") );
@@ -253,7 +253,7 @@ hms(const duration<Rep, Period>& d)
return hh_mm_ss<Dur>(duration_cast<Dur>(d));
}
-template<typename _CharT>
+template<typename CharT>
void
test_hh_mm_ss()
{
@@ -303,7 +303,7 @@ test_hh_mm_ss()
WIDEN("-14322:24:54.111222333") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_hh_mm_ss_fp()
{
@@ -341,7 +341,7 @@ test_hh_mm_ss_fp()
WIDEN("-22:24:54") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_hh_mm_ss_cust()
{
@@ -396,7 +396,7 @@ test_durations()
test_hh_mm_ss_cust<CharT>();
}
-template<typename _CharT>
+template<typename CharT>
void
test_day()
{
@@ -408,7 +408,7 @@ test_day()
verify( day(255), WIDEN("255 is not a valid day") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_month()
{
@@ -422,7 +422,7 @@ test_month()
verify( month(255), WIDEN("255 is not a valid month") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_year()
{
@@ -437,7 +437,7 @@ test_year()
verify( year(32767), WIDEN( "32767") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_weekday()
{
@@ -451,7 +451,7 @@ test_weekday()
verify( weekday(255), WIDEN("255 is not a valid weekday") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_weekday_indexed()
{
@@ -466,7 +466,7 @@ test_weekday_indexed()
verify( weekday(32)[7], WIDEN("32 is not a valid weekday[7 is not a valid index]") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_weekday_last()
{
@@ -474,7 +474,7 @@ test_weekday_last()
verify( weekday(9)[last], WIDEN("9 is not a valid weekday[last]") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_month_day()
{
@@ -484,7 +484,7 @@ test_month_day()
verify( month(13)/32, WIDEN("13 is not a valid month/32 is not a valid day") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_month_day_last()
{
@@ -492,7 +492,7 @@ test_month_day_last()
verify( month(14)/last, WIDEN("14 is not a valid month/last") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_month_weekday()
{
@@ -508,7 +508,7 @@ test_month_weekday()
WIDEN("13 is not a valid month/130 is not a valid weekday[0 is not a valid index]") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_month_weekday_last()
{
@@ -522,7 +522,7 @@ test_month_weekday_last()
WIDEN("13 is not a valid month/10 is not a valid weekday[last]") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_year_month()
{
@@ -536,7 +536,7 @@ test_year_month()
WIDEN("-32768 is not a valid year/0 is not a valid month") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_year_month_day()
{
@@ -556,7 +556,7 @@ test_year_month_day()
WIDEN("-32768-14-55 is not a valid date") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_year_month_last()
{
@@ -570,7 +570,7 @@ test_year_month_last()
WIDEN("-32768 is not a valid year/0 is not a valid month/last") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_year_month_weekday()
{
@@ -586,7 +586,7 @@ test_year_month_weekday()
WIDEN("-32768 is not a valid year/13 is not a valid month/130 is not a valid weekday[0 is not a valid index]") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_year_month_weekday_last()
{
@@ -644,14 +644,14 @@ wall_cast(const local_time<Dur2>& tp)
using decadays = duration<days::rep, std::ratio_multiply<std::deca, days::period>>;
using kilodays = duration<days::rep, std::ratio_multiply<std::kilo, days::period>>;
-template<typename _CharT, typename Clock>
+template<typename CharT, typename Clock>
void
test_time_point(bool daysAsTime)
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const auto lt = local_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
- auto strip_time = [daysAsTime](std::basic_string_view<_CharT> sv)
+ auto strip_time = [daysAsTime](std::basic_string_view<CharT> sv)
{ return daysAsTime ? sv : sv.substr(0, 10); };
verify( wall_cast<Clock, nanoseconds>(lt),
@@ -674,11 +674,11 @@ test_time_point(bool daysAsTime)
strip_time(WIDEN("2022-01-08 00:00:00")) );
}
-template<typename _CharT>
+template<typename CharT>
void
test_leap_second()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const auto st = sys_days(2012y/June/30) + 23h + 59min + 59s + 111222333ns;
auto tp = clock_cast<utc_clock>(st);
@@ -700,7 +700,7 @@ auto
make_zoned(const sys_time<Dur2>& st, const time_zone* tz)
{ return zoned_time<Dur>(tz, floor<Dur>(st)); }
-template<typename _CharT>
+template<typename CharT>
void
test_zoned_time()
{
@@ -734,11 +734,11 @@ auto
local_fmt(const local_time<Dur2>& lt, std::string* zone)
{ return local_time_format(floor<Dur>(lt), zone); }
-template<typename _CharT>
+template<typename CharT>
void
test_local_time_format()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
std::string abbrev = "Zone";
const auto lt = local_days(2024y/March/22) + 13h + 24min + 54s + 111222333ns;
@@ -784,7 +784,7 @@ test_time_points()
}
#if _GLIBCXX_USE_CXX11_ABI || !_GLIBCXX_USE_DUAL_ABI
-template<typename _CharT>
+template<typename CharT>
void
test_sys_info()
{
@@ -796,13 +796,13 @@ test_sys_info()
15min,
"Zone"
};
- const std::basic_string_view<_CharT> txt
+ const std::basic_string_view<CharT> txt
= WIDEN("[2024-03-22 02:00:00,2025-04-11 23:15:10,02:13:04,15min,Zone]");
verify( si, txt );
- std::basic_string<_CharT> res;
- std::basic_string_view<_CharT> sv;
+ std::basic_string<CharT> res;
+ std::basic_string_view<CharT> sv;
sv = res = std::format(WIDEN("{:65}"), si);
VERIFY( sv.ends_with(WIDEN(" ")) );
@@ -817,11 +817,11 @@ test_sys_info()
VERIFY( sv == txt );
}
-template<typename _CharT>
+template<typename CharT>
void test_local_info()
{
- using String = std::basic_string<_CharT>;
- using StringView = std::basic_string_view<_CharT>;
+ using String = std::basic_string<CharT>;
+ using StringView = std::basic_string_view<CharT>;
const sys_info s1
{
diff --git a/libstdc++-v3/testsuite/std/time/format/pr117214.cc b/libstdc++-v3/testsuite/std/time/format/pr117214.cc
index 87c703d..79109c3 100644
--- a/libstdc++-v3/testsuite/std/time/format/pr117214.cc
+++ b/libstdc++-v3/testsuite/std/time/format/pr117214.cc
@@ -7,10 +7,14 @@
#include <chrono>
#include <locale>
+#include <span>
#include <testsuite_hooks.h>
+
+template<typename ChronoType>
void
-test_c()
+test_locale_formats(const ChronoType& t,
+ std::span<const char* const> test_specifiers)
{
const char *test_locales[] = {
"aa_DJ.UTF-8",
@@ -19,15 +23,44 @@ test_c()
"az_IR.UTF-8",
"my_MM.UTF-8",
};
- std::chrono::sys_seconds t{std::chrono::seconds{1}};
+ auto format_args = std::make_format_args(t);
for (auto locale_name : test_locales)
{
- auto s = std::format(std::locale(locale_name), "{:L%c}", t);
- VERIFY( !s.empty() );
+ std::locale loc(locale_name);
+ for (auto specifier : test_specifiers)
+ {
+ auto s = std::vformat(loc, specifier, format_args);
+ VERIFY( !s.empty() );
+ }
}
}
+void
+test_locale_formats()
+{
+ using namespace std::chrono;
+
+ const char* test_specifiers[] = {
+ "{:L%x}", "{:L%Ex}",
+ "{:L%c}", "{:L%Ec}",
+ "{:L%X}", "{:L%EX}",
+ "{:L%r}",
+ };
+ auto date_time_specifiers = std::span(test_specifiers);
+ auto date_specifiers = date_time_specifiers.subspan(0, 2);
+ auto time_specifiers = date_time_specifiers.subspan(4);
+
+ auto ymd = 2020y/November/12d;
+ test_locale_formats(ymd, date_specifiers);
+
+ auto tod = 25h + 10min + 12s;
+ test_locale_formats(tod, time_specifiers);
+
+ auto tp = sys_days(ymd) + tod;
+ test_locale_formats(tp, date_time_specifiers);
+}
+
#include <stdlib.h>
#include <time.h>
@@ -93,7 +126,7 @@ test_c_local()
int main()
{
- test_c();
+ test_locale_formats();
test_c_zoned();
test_c_local();
}
diff --git a/libstdc++-v3/testsuite/std/time/format/pr120114.cc b/libstdc++-v3/testsuite/std/time/format/pr120114.cc
index c630bb3..cdde468 100644
--- a/libstdc++-v3/testsuite/std/time/format/pr120114.cc
+++ b/libstdc++-v3/testsuite/std/time/format/pr120114.cc
@@ -7,13 +7,13 @@
#include <testsuite_hooks.h>
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
-template<typename _CharT>
+template<typename CharT>
void
test_from_format_string()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
using namespace std::chrono_literals;
auto date = 2025y/std::chrono::May/05d;
@@ -27,24 +27,24 @@ test_from_format_string()
VERIFY( res == WIDEN("====2025-05-05\U0001f921====") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_formatted_value()
{
// Custom time_put facet which returns Ideographic Telegraph Symbol
// for given month for Om.
- struct TimePut : std::time_put<_CharT>
+ struct TimePut : std::time_put<CharT>
{
- using iter_type = std::time_put<_CharT>::iter_type;
- using char_type = std::time_put<_CharT>::char_type;
+ using iter_type = std::time_put<CharT>::iter_type;
+ using char_type = std::time_put<CharT>::char_type;
iter_type
do_put(iter_type out, std::ios_base& io, char_type fill, const tm* t,
char format, char modifier) const override
{
if (format != 'm' && modifier != 'm')
- return std::time_put<_CharT>::do_put(out, io, fill, t, format, modifier);
- std::basic_string_view<_CharT> str;
+ return std::time_put<CharT>::do_put(out, io, fill, t, format, modifier);
+ std::basic_string_view<CharT> str;
switch (t->tm_mon)
{
case 0:
@@ -89,7 +89,7 @@ test_formatted_value()
};
const std::locale loc(std::locale::classic(), new TimePut);
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(loc, WIDEN("{:<1L%Om}"), std::chrono::January);
VERIFY( res == WIDEN("\u32C0") );
diff --git a/libstdc++-v3/testsuite/std/time/format/pr120481.cc b/libstdc++-v3/testsuite/std/time/format/pr120481.cc
index 5878c5b..a748acb 100644
--- a/libstdc++-v3/testsuite/std/time/format/pr120481.cc
+++ b/libstdc++-v3/testsuite/std/time/format/pr120481.cc
@@ -7,15 +7,15 @@
#include <testsuite_hooks.h>
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
using namespace std::chrono;
-template<typename _CharT>
+template<typename CharT>
void
test_year()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{:%Y}"), year(0));
VERIFY( res == WIDEN("0000") );
@@ -77,11 +77,11 @@ test_year()
VERIFY( res == WIDEN("01") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_month()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{:%m}"), month(5));
VERIFY( res == WIDEN("05") );
@@ -93,11 +93,11 @@ test_month()
VERIFY( res == WIDEN("254") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_day()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{:%d}"), day(3));
VERIFY( res == WIDEN("03") );
@@ -118,11 +118,11 @@ test_day()
VERIFY( res == WIDEN("214") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_date()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{:%F}"), year(-22)/month(10)/day(20));
VERIFY( res == WIDEN("-0022-10-20") );
@@ -145,11 +145,11 @@ test_date()
VERIFY( res == WIDEN("220/100/00") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_weekday()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{:%w}"), weekday(0));
VERIFY( res == WIDEN("0") );
@@ -187,11 +187,11 @@ test_weekday()
VERIFY( res == WIDEN("202") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_hour()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
res = std::format(WIDEN("{:%H}"), 0h + 5min + 6s);
VERIFY( res == WIDEN("00") );
diff --git a/libstdc++-v3/testsuite/std/time/format/precision.cc b/libstdc++-v3/testsuite/std/time/format/precision.cc
index 5a9acbf..ccb2c77 100644
--- a/libstdc++-v3/testsuite/std/time/format/precision.cc
+++ b/libstdc++-v3/testsuite/std/time/format/precision.cc
@@ -7,13 +7,13 @@
using namespace std::chrono;
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
-#define WIDEN(S) WIDEN_(_CharT, S)
+#define WIDEN(S) WIDEN_(CharT, S)
-template<typename _CharT>
+template<typename CharT>
void
test_empty()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const duration<double> d(33.111222);
res = std::format(WIDEN("{:.3}"), d);
@@ -33,11 +33,11 @@ test_empty()
VERIFY( res == WIDEN("3.31112e+10ns") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_Q()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
const duration<double> d(7.111222);
res = std::format(WIDEN("{:.3%Q}"), d);
@@ -56,11 +56,11 @@ test_Q()
VERIFY( res == WIDEN("7111222000") );
}
-template<typename _CharT>
+template<typename CharT>
void
test_S()
{
- std::basic_string<_CharT> res;
+ std::basic_string<CharT> res;
// Precision is ignored, but period affects output
const duration<double> d(5.111222);
diff --git a/libstdc++-v3/testsuite/std/time/format/whitespace.cc b/libstdc++-v3/testsuite/std/time/format/whitespace.cc
new file mode 100644
index 0000000..debda08
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/format/whitespace.cc
@@ -0,0 +1,56 @@
+// { dg-do run { target c++20 } }
+
+#include <chrono>
+#include <testsuite_hooks.h>
+
+using namespace std::chrono;
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template<typename _CharT, typename ChronoType>
+void
+test(const ChronoType& ct)
+{
+ std::basic_string<_CharT> res;
+
+ res = std::format(WIDEN("{:%% %t %n more text}"), ct);
+ VERIFY( res == WIDEN("% \t \n more text") );
+
+ res = std::format(WIDEN("{:7%% %t %n}"), ct);
+ VERIFY( res == WIDEN("% \t \n ") );
+
+ res = std::format(WIDEN("{:>6%% %t %n}"), ct);
+ VERIFY( res == WIDEN(" % \t \n") );
+
+ res = std::format(WIDEN("{:+>7%% %t %n}"), ct);
+ VERIFY( res == WIDEN("++% \t \n") );
+
+ res = std::format(WIDEN("{:=^7%% %t %n}"), ct);
+ VERIFY( res == WIDEN("=% \t \n=") );
+}
+
+template<typename CharT>
+void
+test_all()
+{
+ test<CharT>(20s);
+ test<CharT>(10d);
+ test<CharT>(Monday);
+ test<CharT>(2020y/January/8);
+ test<CharT>(local_days(2020y/January/8));
+ test<CharT>(sys_days(2020y/January/8) + 13h + 10min + 5s);
+#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI
+ test<CharT>(sys_info());
+ test<CharT>(local_info());
+#endif
+}
+
+int main()
+{
+ test_all<char>();
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ test_all<wchar_t>();
+#endif // _GLIBCXX_USE_WCHAR_T
+}