aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog104
-rw-r--r--libstdc++-v3/acinclude.m4305
-rw-r--r--libstdc++-v3/config.h.in4
-rwxr-xr-xlibstdc++-v3/configure432
-rw-r--r--libstdc++-v3/configure.host2
-rw-r--r--libstdc++-v3/doc/doxygen/user.cfg.in1
-rw-r--r--libstdc++-v3/include/Makefile.am1
-rw-r--r--libstdc++-v3/include/Makefile.in1
-rw-r--r--libstdc++-v3/include/bits/chrono_io.h9
-rw-r--r--libstdc++-v3/include/bits/ptr_traits.h2
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h12
-rw-r--r--libstdc++-v3/include/bits/version.def9
-rw-r--r--libstdc++-v3/include/bits/version.h9
-rw-r--r--libstdc++-v3/include/debug/debug.h2
-rw-r--r--libstdc++-v3/include/ext/atomicity.h4
-rw-r--r--libstdc++-v3/include/precompiled/stdc++.h1
-rw-r--r--libstdc++-v3/include/pstl/glue_numeric_impl.h16
-rw-r--r--libstdc++-v3/include/pstl/numeric_impl.h36
-rw-r--r--libstdc++-v3/include/std/mdspan309
-rw-r--r--libstdc++-v3/include/std/numeric6
-rw-r--r--libstdc++-v3/src/c++17/fs_path.cc10
-rw-r--r--libstdc++-v3/src/c++23/std.cc.in10
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc8
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc82
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc62
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc160
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc87
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc224
-rw-r--r--libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/108236.cc25
-rw-r--r--libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/move_only.cc90
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/path/concat/120029.cc72
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/path/concat/120029.cc74
-rw-r--r--libstdc++-v3/testsuite/std/time/format/pr120114.cc125
33 files changed, 1740 insertions, 554 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index b849d545..b7cce6d 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,107 @@
+2025-05-07 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/120159
+ * src/c++23/std.cc.in (is_layout_compatible_v): Export.
+
+2025-05-07 Jonathan Wakely <jwakely@redhat.com>
+
+ * src/c++23/std.cc.in: Fix export for std::extents.
+
+2025-05-07 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * testsuite/23_containers/mdspan/extents/class_mandates_neg.cc: New test.
+ * testsuite/23_containers/mdspan/extents/ctor_copy.cc: New test.
+ * testsuite/23_containers/mdspan/extents/ctor_ints.cc: New test.
+ * testsuite/23_containers/mdspan/extents/ctor_shape.cc: New test.
+ * testsuite/23_containers/mdspan/extents/custom_integer.cc: New test.
+ * testsuite/23_containers/mdspan/extents/misc.cc: New test.
+
+2025-05-07 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ PR libstdc++/107761
+ * include/std/mdspan (extents): New class.
+ * src/c++23/std.cc.in: Add 'using std::extents'.
+
+2025-05-07 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * doc/doxygen/user.cfg.in: Add <mdspan>.
+ * include/Makefile.am: Ditto.
+ * include/Makefile.in: Ditto.
+ * include/precompiled/stdc++.h: Ditto.
+ * include/std/mdspan: New file.
+
+2025-05-07 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/bits/version.def: Add internal feature testing macro
+ __glibcxx_mdspan.
+ * include/bits/version.h: Regenerate.
+
+2025-05-07 Tomasz KamiƄski <tkaminsk@redhat.com>
+
+ PR libstdc++/120114
+ * include/bits/chrono_io.h (__formatter_chrono::_M_format): Use __field_width.
+ * testsuite/std/time/format/pr120114.cc: New test.
+
+2025-05-07 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/120147
+ * acinclude.m4 (GLIBCXX_ENABLE_BACKTRACE): Restore use of
+ AC_LANG_CPLUSPLUS.
+ * configure: Regenerate.
+
+2025-05-06 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/70560
+ PR libstdc++/119667
+ * acinclude.m4 (GLIBCXX_ENABLE_ATOMIC_BUILTINS): Only check for
+ __atomic_fetch_add on _Atomic_word. Define new macro
+ _GLIBCXX_ATOMIC_WORD_BUILTINS and stop defining macro
+ _GLIBCXX_ATOMIC_BUILTINS.
+ (GLIBCXX_ENABLE_BACKTRACE): Check for __atomic_load_n and
+ __atomic_store_n on int, void* and size_t.
+ * config.h.in: Regenerate.
+ * configure: Regenerate.
+ * configure.host: Fix typo in comment.
+ * include/ext/atomicity.h (__exchange_and_add, __atomic_add):
+ Depend on _GLIBCXX_ATOMIC_WORD_BUILTINS macro instead of old
+ _GLIBCXX_ATOMIC_BUILTINS macro.
+
+2025-05-06 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/117905
+ * include/pstl/glue_numeric_impl.h (reduce, transform_reduce)
+ (transform_reduce, inclusive_scan, transform_exclusive_scan)
+ (transform_inclusive_scan): Use std::move for __init parameter.
+ * include/pstl/numeric_impl.h (__brick_transform_reduce)
+ (__pattern_transform_reduce, __brick_transform_scan)
+ (__pattern_transform_scan): Likewise.
+ * include/std/numeric (inclusive_scan, transform_exclusive_scan):
+ Use std::move to create local copy of the first element.
+ * testsuite/26_numerics/pstl/numeric_ops/108236.cc: Move test
+ using move-only type to ...
+ * testsuite/26_numerics/pstl/numeric_ops/move_only.cc: New test.
+
+2025-05-06 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/120029
+ * src/c++17/fs_path.cc (path::operator+=(const path&)): Handle
+ parameters that alias the path or one of its components.
+ * testsuite/27_io/filesystem/path/concat/120029.cc: New test.
+ * testsuite/experimental/filesystem/path/concat/120029.cc: New
+ test.
+
+2025-05-06 Jonathan Wakely <jwakely@redhat.com>
+
+ PR c++/120112
+ * include/bits/ptr_traits.h (_Safe_iterator_base): Use class
+ keyword in class-head of declaration.
+ * include/debug/debug.h (_Safe_iterator): Likewise.
+
+2025-05-06 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/stl_iterator.h (counted_iterator): Add noexcept
+ to friend operators which only access the _M_length member.
+
2025-05-02 Dhruv Chawla <dhruvc@nvidia.com>
* include/std/memory: Define __glibcxx_want_addressof_constexpr.
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index a0094c2..204bed5b 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -3709,16 +3709,22 @@ AC_DEFUN([GLIBCXX_ENABLE_PCH], [
AC_SUBST(glibcxx_PCHFLAGS)
])
-
dnl
dnl Check for atomic builtins.
dnl See:
dnl http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
dnl
-dnl This checks to see if the host supports the compiler-generated
-dnl builtins for atomic operations for various integral sizes. Note, this
-dnl is intended to be an all-or-nothing switch, so all the atomic operations
-dnl that are used should be checked.
+dnl This checks to see if the host supports __atomic_fetch_add on _Atomic_word.
+dnl
+dnl We don't want libstdc++.so to depend on libatomic.so for basic
+dnl functionality like library-internal reference counting. This means we
+dnl should not use atomics for reference counting unless it can be done
+dnl using native instructions and not by calling into libatomic.
+dnl This policy could change if linking to libatomic.so becomes implicit.
+dnl
+dnl Defines:
+dnl GLIBCXX_ATOMIC_WORD_BUILTINS - if atomic builtins should be used for
+dnl increments and decrements of _Atomic_word.
dnl
dnl Note:
dnl libgomp and libgfortran use a link test, see CHECK_SYNC_FETCH_AND_ADD.
@@ -3728,7 +3734,7 @@ AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
AC_LANG_CPLUSPLUS
old_CXXFLAGS="$CXXFLAGS"
- # Do link tests if possible, instead asm tests, limited to some platforms
+ # Do link tests if possible, otherwise asm tests. Limited to some platforms
# see discussion in PR target/40134, PR libstdc++/40133 and the thread
# starting at http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html
atomic_builtins_link_tests=no
@@ -3741,223 +3747,59 @@ AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
esac
fi
- if test x$atomic_builtins_link_tests = xyes; then
-
- # Do link tests.
-
- CXXFLAGS="$CXXFLAGS -fno-exceptions"
-
- AC_CACHE_CHECK([for atomic builtins for bool],
- glibcxx_cv_atomic_bool, [
- AC_TRY_LINK(
- [ ],
- [typedef bool atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- // N.B. __atomic_fetch_add is not supported for bool.
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
- ],
- [glibcxx_cv_atomic_bool=yes],
- [glibcxx_cv_atomic_bool=no])
- ])
+ if test "$atomic_builtins_link_tests" = yes; then
- AC_CACHE_CHECK([for atomic builtins for short],
- glibcxx_cv_atomic_short, [
- AC_TRY_LINK(
- [ ],
- [typedef short atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
- ],
- [glibcxx_cv_atomic_short=yes],
- [glibcxx_cv_atomic_short=no])
- ])
+ # Do link tests.
- AC_CACHE_CHECK([for atomic builtins for int],
- glibcxx_cv_atomic_int, [
- AC_TRY_LINK(
- [ ],
- [typedef int atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
- ],
- [glibcxx_cv_atomic_int=yes],
- [glibcxx_cv_atomic_int=no])
- ])
+ CXXFLAGS="$CXXFLAGS -fno-exceptions"
- AC_CACHE_CHECK([for atomic builtins for long long],
- glibcxx_cv_atomic_long_long, [
- AC_TRY_LINK(
- [ ],
- [typedef long long atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
- ],
- [glibcxx_cv_atomic_long_long=yes],
- [glibcxx_cv_atomic_long_long=no])
- ])
+ AC_CACHE_CHECK([for atomic builtins for _Atomic_word],
+ glibcxx_cv_atomic_word,
+ [AC_TRY_LINK([#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"],
+ [_Atomic_word a = 0, b;
+ b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);],
+ [glibcxx_cv_atomic_word=yes],
+ [glibcxx_cv_atomic_word=no])])
else
+ # Do asm tests.
- # Do asm tests.
-
- # Compile unoptimized.
- CXXFLAGS='-O0 -S'
+ # Compile unoptimized.
+ CXXFLAGS='-O0 -S'
- # Fake what AC_TRY_COMPILE does.
+ # Fake what AC_TRY_COMPILE does.
cat > conftest.$ac_ext << EOF
[#]line __oline__ "configure"
+[#]include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
int main()
{
- typedef bool atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- // N.B. __atomic_fetch_add is not supported for bool.
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- return 0;
+ _Atomic_word a = 0, b;
+ b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
}
EOF
- AC_MSG_CHECKING([for atomic builtins for bool])
+ AC_MSG_CHECKING([for atomic builtins for _Atomic_word])
if AC_TRY_EVAL(ac_compile); then
if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
- glibcxx_cv_atomic_bool=no
+ glibcxx_cv_atomic_word=no
else
- glibcxx_cv_atomic_bool=yes
+ glibcxx_cv_atomic_word=yes
fi
fi
- AC_MSG_RESULT($glibcxx_cv_atomic_bool)
+ AC_MSG_RESULT($glibcxx_cv_atomic_word)
rm -f conftest*
-
- cat > conftest.$ac_ext << EOF
-[#]line __oline__ "configure"
-int main()
-{
- typedef short atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- return 0;
-}
-EOF
-
- AC_MSG_CHECKING([for atomic builtins for short])
- if AC_TRY_EVAL(ac_compile); then
- if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
- glibcxx_cv_atomic_short=no
- else
- glibcxx_cv_atomic_short=yes
- fi
- fi
- AC_MSG_RESULT($glibcxx_cv_atomic_short)
- rm -f conftest*
-
- cat > conftest.$ac_ext << EOF
-[#]line __oline__ "configure"
-int main()
-{
- // NB: _Atomic_word not necessarily int.
- typedef int atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- return 0;
-}
-EOF
-
- AC_MSG_CHECKING([for atomic builtins for int])
- if AC_TRY_EVAL(ac_compile); then
- if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
- glibcxx_cv_atomic_int=no
- else
- glibcxx_cv_atomic_int=yes
- fi
- fi
- AC_MSG_RESULT($glibcxx_cv_atomic_int)
- rm -f conftest*
-
- cat > conftest.$ac_ext << EOF
-[#]line __oline__ "configure"
-int main()
-{
- typedef long long atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- return 0;
-}
-EOF
-
- AC_MSG_CHECKING([for atomic builtins for long long])
- if AC_TRY_EVAL(ac_compile); then
- if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
- glibcxx_cv_atomic_long_long=no
- else
- glibcxx_cv_atomic_long_long=yes
- fi
- fi
- AC_MSG_RESULT($glibcxx_cv_atomic_long_long)
- rm -f conftest*
-
fi
CXXFLAGS="$old_CXXFLAGS"
AC_LANG_RESTORE
- # Set atomicity_dir to builtins if all but the long long test above passes,
+ # Set atomicity_dir to builtins if the test above passes,
# or if the builtins were already chosen (e.g. by configure.host).
- if { test "$glibcxx_cv_atomic_bool" = yes \
- && test "$glibcxx_cv_atomic_short" = yes \
- && test "$glibcxx_cv_atomic_int" = yes; } \
+ if test "$glibcxx_cv_atomic_word" = yes \
|| test "$atomicity_dir" = "cpu/generic/atomicity_builtins"; then
- AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS, 1,
- [Define if the compiler supports C++11 atomics.])
+ AC_DEFINE(_GLIBCXX_ATOMIC_WORD_BUILTINS, 1,
+ [Define if the compiler supports native atomics for _Atomic_word.])
atomicity_dir=cpu/generic/atomicity_builtins
fi
@@ -5448,8 +5290,77 @@ AC_DEFUN([GLIBCXX_ENABLE_BACKTRACE], [
BACKTRACE_CPPFLAGS="-D_GNU_SOURCE"
- # libbacktrace only needs atomics for int, which we've already tested
- if test "$glibcxx_cv_atomic_int" = "yes"; then
+ AC_LANG_CPLUSPLUS
+ old_CXXFLAGS="$CXXFLAGS"
+
+ # libbacktrace's own configure.ac only tests atomics for int,
+ # but the code actually uses atomics for size_t and pointers as well.
+ if test "$atomic_builtins_link_tests" = yes; then
+
+ CXXFLAGS='-O0'
+
+ AC_CACHE_CHECK([for atomic builtins for libbacktrace],
+ glibcxx_cv_libbacktrace_atomics,
+ [AC_TRY_LINK([], [
+ int i = 0;
+ int* p = &i;
+ size_t s = 0;
+ // backtrace_atomic_load_pointer
+ void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
+ // backtrace_atomic_load_int
+ int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
+ // backtrace_atomic_store_pointer
+ __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
+ // backtrace_atomic_store_size_t
+ __atomic_store_n(&s, s, __ATOMIC_RELEASE);
+ // backtrace_atomic_store_int
+ __atomic_store_n(&i, i, __ATOMIC_RELEASE);
+ ],
+ [glibcxx_cv_libbacktrace_atomics=yes],
+ [glibcxx_cv_libbacktrace_atomics=no])])
+
+ else
+ # Do asm tests.
+
+ CXXFLAGS='-O0 -S'
+
+ cat > conftest.$ac_ext << EOF
+[#]line __oline__ "configure"
+[#]include <stddef.h>
+int main()
+{
+ int i = 0;
+ int* p = &i;
+ size_t s = 0;
+ // backtrace_atomic_load_pointer
+ void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
+ // backtrace_atomic_load_int
+ int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
+ // backtrace_atomic_store_pointer
+ __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
+ // backtrace_atomic_store_size_t
+ __atomic_store_n(&s, s, __ATOMIC_RELEASE);
+ // backtrace_atomic_store_int
+ __atomic_store_n(&i, i, __ATOMIC_RELEASE);
+}
+EOF
+
+ AC_MSG_CHECKING([for atomic builtins for libbacktrace])
+ if AC_TRY_EVAL(ac_compile); then
+ if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+ glibcxx_cv_libbacktrace_atomics=no
+ else
+ glibcxx_cv_libbacktrace_atomics=yes
+ fi
+ fi
+ AC_MSG_RESULT($glibcxx_cv_libbacktrace_atomics)
+ rm -f conftest*
+ fi
+
+ CXXFLAGS="$old_CXXFLAGS"
+ AC_LANG_RESTORE
+
+ if test "$glibcxx_cv_libbacktrace_atomics" = yes; then
BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DHAVE_ATOMIC_FUNCTIONS=1"
fi
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 77bbaf1..3dbe00b 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -643,8 +643,8 @@
<cwchar> in namespace std for C++98. */
#undef _GLIBCXX98_USE_C99_WCHAR
-/* Define if the compiler supports C++11 atomics. */
-#undef _GLIBCXX_ATOMIC_BUILTINS
+/* Define if the compiler supports native atomics for _Atomic_word. */
+#undef _GLIBCXX_ATOMIC_WORD_BUILTINS
/* Define if global objects can be aligned to
std::hardware_destructive_interference_size. */
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 819a1d82..0529ff5 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -15989,7 +15989,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
old_CXXFLAGS="$CXXFLAGS"
- # Do link tests if possible, instead asm tests, limited to some platforms
+ # Do link tests if possible, otherwise asm tests. Limited to some platforms
# see discussion in PR target/40134, PR libstdc++/40133 and the thread
# starting at http://gcc.gnu.org/ml/gcc-patches/2009-07/msg00322.html
atomic_builtins_link_tests=no
@@ -16002,326 +16002,77 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
esac
fi
- if test x$atomic_builtins_link_tests = xyes; then
+ if test "$atomic_builtins_link_tests" = yes; then
- # Do link tests.
+ # Do link tests.
- CXXFLAGS="$CXXFLAGS -fno-exceptions"
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for bool" >&5
-$as_echo_n "checking for atomic builtins for bool... " >&6; }
-if ${glibcxx_cv_atomic_bool+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- if test x$gcc_no_link = xyes; then
- as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-typedef bool atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- // N.B. __atomic_fetch_add is not supported for bool.
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- glibcxx_cv_atomic_bool=yes
-else
- glibcxx_cv_atomic_bool=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_bool" >&5
-$as_echo "$glibcxx_cv_atomic_bool" >&6; }
+ CXXFLAGS="$CXXFLAGS -fno-exceptions"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for short" >&5
-$as_echo_n "checking for atomic builtins for short... " >&6; }
-if ${glibcxx_cv_atomic_short+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for _Atomic_word" >&5
+$as_echo_n "checking for atomic builtins for _Atomic_word... " >&6; }
+if ${glibcxx_cv_atomic_word+:} false; then :
$as_echo_n "(cached) " >&6
else
-
- if test x$gcc_no_link = xyes; then
- as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-typedef short atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- glibcxx_cv_atomic_short=yes
-else
- glibcxx_cv_atomic_short=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_short" >&5
-$as_echo "$glibcxx_cv_atomic_short" >&6; }
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for int" >&5
-$as_echo_n "checking for atomic builtins for int... " >&6; }
-if ${glibcxx_cv_atomic_int+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- if test x$gcc_no_link = xyes; then
- as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
-fi
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-int
-main ()
-{
-typedef int atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- glibcxx_cv_atomic_int=yes
-else
- glibcxx_cv_atomic_int=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_int" >&5
-$as_echo "$glibcxx_cv_atomic_int" >&6; }
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for long long" >&5
-$as_echo_n "checking for atomic builtins for long long... " >&6; }
-if ${glibcxx_cv_atomic_long_long+:} false; then :
- $as_echo_n "(cached) " >&6
-else
-
- if test x$gcc_no_link = xyes; then
+ if test x$gcc_no_link = xyes; then
as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-
+#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
int
main ()
{
-typedef long long atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
+_Atomic_word a = 0, b;
+ b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
;
return 0;
}
_ACEOF
if ac_fn_cxx_try_link "$LINENO"; then :
- glibcxx_cv_atomic_long_long=yes
+ glibcxx_cv_atomic_word=yes
else
- glibcxx_cv_atomic_long_long=no
+ glibcxx_cv_atomic_word=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
-
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_long_long" >&5
-$as_echo "$glibcxx_cv_atomic_long_long" >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_word" >&5
+$as_echo "$glibcxx_cv_atomic_word" >&6; }
else
+ # Do asm tests.
- # Do asm tests.
-
- # Compile unoptimized.
- CXXFLAGS='-O0 -S'
-
- # Fake what AC_TRY_COMPILE does.
-
- cat > conftest.$ac_ext << EOF
-#line 16185 "configure"
-int main()
-{
- typedef bool atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- // N.B. __atomic_fetch_add is not supported for bool.
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- return 0;
-}
-EOF
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for bool" >&5
-$as_echo_n "checking for atomic builtins for bool... " >&6; }
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
- glibcxx_cv_atomic_bool=no
- else
- glibcxx_cv_atomic_bool=yes
- fi
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_bool" >&5
-$as_echo "$glibcxx_cv_atomic_bool" >&6; }
- rm -f conftest*
-
- cat > conftest.$ac_ext << EOF
-#line 16220 "configure"
-int main()
-{
- typedef short atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- return 0;
-}
-EOF
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for short" >&5
-$as_echo_n "checking for atomic builtins for short... " >&6; }
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
- glibcxx_cv_atomic_short=no
- else
- glibcxx_cv_atomic_short=yes
- fi
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_short" >&5
-$as_echo "$glibcxx_cv_atomic_short" >&6; }
- rm -f conftest*
-
- cat > conftest.$ac_ext << EOF
-#line 16255 "configure"
-int main()
-{
- // NB: _Atomic_word not necessarily int.
- typedef int atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- return 0;
-}
-EOF
+ # Compile unoptimized.
+ CXXFLAGS='-O0 -S'
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for int" >&5
-$as_echo_n "checking for atomic builtins for int... " >&6; }
- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
- glibcxx_cv_atomic_int=no
- else
- glibcxx_cv_atomic_int=yes
- fi
- fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_int" >&5
-$as_echo "$glibcxx_cv_atomic_int" >&6; }
- rm -f conftest*
+ # Fake what AC_TRY_COMPILE does.
cat > conftest.$ac_ext << EOF
-#line 16291 "configure"
+#line 16051 "configure"
+#include "${glibcxx_srcdir}/config/$atomic_word_dir/atomic_word.h"
int main()
{
- typedef long long atomic_type;
- atomic_type c1;
- atomic_type c2;
- atomic_type c3(0);
- __atomic_fetch_add(&c1, c2, __ATOMIC_RELAXED);
- __atomic_compare_exchange_n(&c1, &c2, c3, true, __ATOMIC_ACQ_REL,
- __ATOMIC_RELAXED);
- __atomic_test_and_set(&c1, __ATOMIC_RELAXED);
- __atomic_load_n(&c1, __ATOMIC_RELAXED);
-
- return 0;
+ _Atomic_word a = 0, b;
+ b = __atomic_fetch_add(&a, 1, __ATOMIC_ACQ_REL);
}
EOF
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for long long" >&5
-$as_echo_n "checking for atomic builtins for long long... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for _Atomic_word" >&5
+$as_echo_n "checking for atomic builtins for _Atomic_word... " >&6; }
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
test $ac_status = 0; }; then
if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
- glibcxx_cv_atomic_long_long=no
+ glibcxx_cv_atomic_word=no
else
- glibcxx_cv_atomic_long_long=yes
+ glibcxx_cv_atomic_word=yes
fi
fi
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_long_long" >&5
-$as_echo "$glibcxx_cv_atomic_long_long" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_word" >&5
+$as_echo "$glibcxx_cv_atomic_word" >&6; }
rm -f conftest*
-
fi
CXXFLAGS="$old_CXXFLAGS"
@@ -16332,14 +16083,12 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
- # Set atomicity_dir to builtins if all but the long long test above passes,
+ # Set atomicity_dir to builtins if the test above passes,
# or if the builtins were already chosen (e.g. by configure.host).
- if { test "$glibcxx_cv_atomic_bool" = yes \
- && test "$glibcxx_cv_atomic_short" = yes \
- && test "$glibcxx_cv_atomic_int" = yes; } \
+ if test "$glibcxx_cv_atomic_word" = yes \
|| test "$atomicity_dir" = "cpu/generic/atomicity_builtins"; then
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS 1" >>confdefs.h
+$as_echo "#define _GLIBCXX_ATOMIC_WORD_BUILTINS 1" >>confdefs.h
atomicity_dir=cpu/generic/atomicity_builtins
fi
@@ -16445,7 +16194,7 @@ $as_echo "mutex" >&6; }
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 16448 "configure"
+#line 16197 "configure"
int main()
{
_Decimal32 d1;
@@ -16487,7 +16236,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
# unnecessary for this test.
cat > conftest.$ac_ext << EOF
-#line 16490 "configure"
+#line 16239 "configure"
template<typename T1, typename T2>
struct same
{ typedef T2 type; };
@@ -53788,8 +53537,117 @@ fi
BACKTRACE_CPPFLAGS="-D_GNU_SOURCE"
- # libbacktrace only needs atomics for int, which we've already tested
- if test "$glibcxx_cv_atomic_int" = "yes"; then
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ old_CXXFLAGS="$CXXFLAGS"
+
+ # libbacktrace's own configure.ac only tests atomics for int,
+ # but the code actually uses atomics for size_t and pointers as well.
+ if test "$atomic_builtins_link_tests" = yes; then
+
+ CXXFLAGS='-O0'
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for libbacktrace" >&5
+$as_echo_n "checking for atomic builtins for libbacktrace... " >&6; }
+if ${glibcxx_cv_libbacktrace_atomics+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test x$gcc_no_link = xyes; then
+ as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ int i = 0;
+ int* p = &i;
+ size_t s = 0;
+ // backtrace_atomic_load_pointer
+ void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
+ // backtrace_atomic_load_int
+ int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
+ // backtrace_atomic_store_pointer
+ __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
+ // backtrace_atomic_store_size_t
+ __atomic_store_n(&s, s, __ATOMIC_RELEASE);
+ // backtrace_atomic_store_int
+ __atomic_store_n(&i, i, __ATOMIC_RELEASE);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ glibcxx_cv_libbacktrace_atomics=yes
+else
+ glibcxx_cv_libbacktrace_atomics=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_libbacktrace_atomics" >&5
+$as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; }
+
+ else
+ # Do asm tests.
+
+ CXXFLAGS='-O0 -S'
+
+ cat > conftest.$ac_ext << EOF
+#line 53604 "configure"
+#include <stddef.h>
+int main()
+{
+ int i = 0;
+ int* p = &i;
+ size_t s = 0;
+ // backtrace_atomic_load_pointer
+ void* vp = __atomic_load_n(&p, __ATOMIC_ACQUIRE);
+ // backtrace_atomic_load_int
+ int i2 = __atomic_load_n(&i, __ATOMIC_ACQUIRE);
+ // backtrace_atomic_store_pointer
+ __atomic_store_n(&p, &i, __ATOMIC_RELEASE);
+ // backtrace_atomic_store_size_t
+ __atomic_store_n(&s, s, __ATOMIC_RELEASE);
+ // backtrace_atomic_store_int
+ __atomic_store_n(&i, i, __ATOMIC_RELEASE);
+}
+EOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic builtins for libbacktrace" >&5
+$as_echo_n "checking for atomic builtins for libbacktrace... " >&6; }
+ if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ if grep __atomic_ conftest.s >/dev/null 2>&1 ; then
+ glibcxx_cv_libbacktrace_atomics=no
+ else
+ glibcxx_cv_libbacktrace_atomics=yes
+ fi
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_libbacktrace_atomics" >&5
+$as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; }
+ rm -f conftest*
+ fi
+
+ CXXFLAGS="$old_CXXFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+ if test "$glibcxx_cv_libbacktrace_atomics" = yes; then
BACKTRACE_CPPFLAGS="$BACKTRACE_CPPFLAGS -DHAVE_ATOMIC_FUNCTIONS=1"
fi
diff --git a/libstdc++-v3/configure.host b/libstdc++-v3/configure.host
index 253e5a9..3cd1bb1 100644
--- a/libstdc++-v3/configure.host
+++ b/libstdc++-v3/configure.host
@@ -180,7 +180,7 @@ esac
# Set specific CPU overrides for atomicity_dir.
-# This can be over-ridden in GLIBCXX_ENABLE_ATOMIC_BUILTINS.
+# This can be overridden in GLIBCXX_ENABLE_ATOMIC_BUILTINS.
# THIS TABLE IS SORTED. KEEP IT THAT WAY.
if test -f ${glibcxx_srcdir}/config/${cpu_include_dir}/atomicity.h ; then
atomicity_dir=$cpu_include_dir
diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index 19ae67a..e926c67 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -880,6 +880,7 @@ INPUT = @srcdir@/doc/doxygen/doxygroups.cc \
include/list \
include/locale \
include/map \
+ include/mdspan \
include/memory \
include/memory_resource \
include/mutex \
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 537774c..1140fa0 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -38,6 +38,7 @@ std_freestanding = \
${std_srcdir}/generator \
${std_srcdir}/iterator \
${std_srcdir}/limits \
+ ${std_srcdir}/mdspan \
${std_srcdir}/memory \
${std_srcdir}/numbers \
${std_srcdir}/numeric \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 7b96b22..c96e981 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -396,6 +396,7 @@ std_freestanding = \
${std_srcdir}/generator \
${std_srcdir}/iterator \
${std_srcdir}/limits \
+ ${std_srcdir}/mdspan \
${std_srcdir}/memory \
${std_srcdir}/numbers \
${std_srcdir}/numeric \
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index b7f6f5f..620227a 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -705,8 +705,13 @@ namespace __format
if (__write_direct)
return __out;
- auto __str = std::move(__sink).get();
- return __format::__write_padded_as_spec(__str, __str.size(),
+ auto __str = __sink.view();
+ size_t __width;
+ if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>())
+ __width = __unicode::__field_width(__str);
+ else
+ __width = __str.size();
+ return __format::__write_padded_as_spec(__str, __width,
__fc, _M_spec);
}
diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h
index 4308669..91da88b 100644
--- a/libstdc++-v3/include/bits/ptr_traits.h
+++ b/libstdc++-v3/include/bits/ptr_traits.h
@@ -36,7 +36,7 @@
#if __cplusplus > 201703L
#include <concepts>
-namespace __gnu_debug { struct _Safe_iterator_base; }
+namespace __gnu_debug { class _Safe_iterator_base; }
#endif
namespace std _GLIBCXX_VISIBILITY(default)
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index bed7295..478a98f 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -2511,17 +2511,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[nodiscard]]
friend constexpr iter_difference_t<_It2>
operator-(const counted_iterator& __x,
- const counted_iterator<_It2>& __y)
+ const counted_iterator<_It2>& __y) noexcept
{ return __y._M_length - __x._M_length; }
[[nodiscard]]
friend constexpr iter_difference_t<_It>
- operator-(const counted_iterator& __x, default_sentinel_t)
+ operator-(const counted_iterator& __x, default_sentinel_t) noexcept
{ return -__x._M_length; }
[[nodiscard]]
friend constexpr iter_difference_t<_It>
- operator-(default_sentinel_t, const counted_iterator& __y)
+ operator-(default_sentinel_t, const counted_iterator& __y) noexcept
{ return __y._M_length; }
constexpr counted_iterator&
@@ -2548,19 +2548,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[nodiscard]]
friend constexpr bool
operator==(const counted_iterator& __x,
- const counted_iterator<_It2>& __y)
+ const counted_iterator<_It2>& __y) noexcept
{ return __x._M_length == __y._M_length; }
[[nodiscard]]
friend constexpr bool
- operator==(const counted_iterator& __x, default_sentinel_t)
+ operator==(const counted_iterator& __x, default_sentinel_t) noexcept
{ return __x._M_length == 0; }
template<common_with<_It> _It2>
[[nodiscard]]
friend constexpr strong_ordering
operator<=>(const counted_iterator& __x,
- const counted_iterator<_It2>& __y)
+ const counted_iterator<_It2>& __y) noexcept
{ return __y._M_length <=> __x._M_length; }
[[nodiscard]]
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 282667e..f4d3de8 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1000,6 +1000,15 @@ ftms = {
};
ftms = {
+ name = mdspan;
+ no_stdname = true; // FIXME: remove
+ values = {
+ v = 1; // FIXME: 202207
+ cxxmin = 23;
+ };
+};
+
+ftms = {
name = ssize;
values = {
v = 201902;
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index bb7c047..d5d75ce 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1114,6 +1114,15 @@
#endif /* !defined(__cpp_lib_span) && defined(__glibcxx_want_span) */
#undef __glibcxx_want_span
+#if !defined(__cpp_lib_mdspan)
+# if (__cplusplus >= 202100L)
+# define __glibcxx_mdspan 1L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_mdspan)
+# endif
+# endif
+#endif /* !defined(__cpp_lib_mdspan) && defined(__glibcxx_want_mdspan) */
+#undef __glibcxx_want_mdspan
+
#if !defined(__cpp_lib_ssize)
# if (__cplusplus >= 202002L)
# define __glibcxx_ssize 201902L
diff --git a/libstdc++-v3/include/debug/debug.h b/libstdc++-v3/include/debug/debug.h
index 0e02d58..0131c0a 100644
--- a/libstdc++-v3/include/debug/debug.h
+++ b/libstdc++-v3/include/debug/debug.h
@@ -58,7 +58,7 @@ namespace __gnu_debug
using namespace std::__debug;
template<typename _Ite, typename _Seq, typename _Cat>
- struct _Safe_iterator;
+ class _Safe_iterator;
}
#if ! defined _GLIBCXX_DEBUG || ! _GLIBCXX_HOSTED
diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h
index 98f745c..650b786 100644
--- a/libstdc++-v3/include/ext/atomicity.h
+++ b/libstdc++-v3/include/ext/atomicity.h
@@ -61,7 +61,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// To abstract locking primitives across all thread policies, use:
// __exchange_and_add_dispatch
// __atomic_add_dispatch
-#ifdef _GLIBCXX_ATOMIC_BUILTINS
+#ifdef _GLIBCXX_ATOMIC_WORD_BUILTINS
inline _Atomic_word
__attribute__((__always_inline__))
__exchange_and_add(volatile _Atomic_word* __mem, int __val)
@@ -71,7 +71,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__attribute__((__always_inline__))
__atomic_add(volatile _Atomic_word* __mem, int __val)
{ __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
-#else
+#else // Defined in config/cpu/.../atomicity.h
_Atomic_word
__exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW;
diff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h
index f4b312d..e7d89c9 100644
--- a/libstdc++-v3/include/precompiled/stdc++.h
+++ b/libstdc++-v3/include/precompiled/stdc++.h
@@ -228,6 +228,7 @@
#include <flat_map>
#include <flat_set>
#include <generator>
+#include <mdspan>
#include <print>
#include <spanstream>
#include <stacktrace>
diff --git a/libstdc++-v3/include/pstl/glue_numeric_impl.h b/libstdc++-v3/include/pstl/glue_numeric_impl.h
index 10d4912..fe2d0fd 100644
--- a/libstdc++-v3/include/pstl/glue_numeric_impl.h
+++ b/libstdc++-v3/include/pstl/glue_numeric_impl.h
@@ -25,7 +25,7 @@ __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
_BinaryOperation __binary_op)
{
- return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, __binary_op,
+ return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::move(__init), __binary_op,
__pstl::__internal::__no_op());
}
@@ -33,7 +33,7 @@ template <class _ExecutionPolicy, class _ForwardIterator, class _Tp>
__pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, _Tp>
reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Tp __init)
{
- return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, __init, std::plus<_Tp>(),
+ return transform_reduce(std::forward<_ExecutionPolicy>(__exec), __first, __last, std::move(__init), std::plus<_Tp>(),
__pstl::__internal::__no_op());
}
@@ -58,7 +58,7 @@ transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forward
typedef typename iterator_traits<_ForwardIterator1>::value_type _InputType;
return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
- __first1, __last1, __first2, __init, std::plus<_InputType>(),
+ __first1, __last1, __first2, std::move(__init), std::plus<_InputType>(),
std::multiplies<_InputType>());
}
@@ -70,7 +70,7 @@ transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator1 __first1, _Forward
{
auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first1, __first2);
return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
- __first1, __last1, __first2, __init, __binary_op1,
+ __first1, __last1, __first2, std::move(__init), __binary_op1,
__binary_op2);
}
@@ -81,7 +81,7 @@ transform_reduce(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIt
{
auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first);
return __pstl::__internal::__pattern_transform_reduce(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec),
- __first, __last, __init, __binary_op, __unary_op);
+ __first, __last, std::move(__init), __binary_op, __unary_op);
}
// [exclusive.scan]
@@ -139,7 +139,7 @@ inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _ForwardIte
_ForwardIterator2 __result, _BinaryOperation __binary_op, _Tp __init)
{
return transform_inclusive_scan(std::forward<_ExecutionPolicy>(__exec), __first, __last, __result, __binary_op,
- __pstl::__internal::__no_op(), __init);
+ __pstl::__internal::__no_op(), std::move(__init));
}
// [transform.exclusive.scan]
@@ -154,7 +154,7 @@ transform_exclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _
auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
- __last, __result, __unary_op, __init, __binary_op,
+ __last, __result, __unary_op, std::move(__init), __binary_op,
/*inclusive=*/std::false_type());
}
@@ -170,7 +170,7 @@ transform_inclusive_scan(_ExecutionPolicy&& __exec, _ForwardIterator1 __first, _
auto __dispatch_tag = __pstl::__internal::__select_backend(__exec, __first, __result);
return __pstl::__internal::__pattern_transform_scan(__dispatch_tag, std::forward<_ExecutionPolicy>(__exec), __first,
- __last, __result, __unary_op, __init, __binary_op,
+ __last, __result, __unary_op, std::move(__init), __binary_op,
/*inclusive=*/std::true_type());
}
diff --git a/libstdc++-v3/include/pstl/numeric_impl.h b/libstdc++-v3/include/pstl/numeric_impl.h
index e1ebec1..b285a66 100644
--- a/libstdc++-v3/include/pstl/numeric_impl.h
+++ b/libstdc++-v3/include/pstl/numeric_impl.h
@@ -35,7 +35,7 @@ __brick_transform_reduce(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
_BinaryOperation1 __binary_op1, _BinaryOperation2 __binary_op2,
/*is_vector=*/std::false_type) noexcept
{
- return std::inner_product(__first1, __last1, __first2, __init, __binary_op1, __binary_op2);
+ return std::inner_product(__first1, __last1, __first2, std::move(__init), __binary_op1, __binary_op2);
}
template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Tp, class _BinaryOperation1,
@@ -48,7 +48,7 @@ __brick_transform_reduce(_RandomAccessIterator1 __first1, _RandomAccessIterator1
{
typedef typename std::iterator_traits<_RandomAccessIterator1>::difference_type _DifferenceType;
return __unseq_backend::__simd_transform_reduce(
- __last1 - __first1, __init, __binary_op1,
+ __last1 - __first1, std::move(__init), __binary_op1,
[=, &__binary_op2](_DifferenceType __i) { return __binary_op2(__first1[__i], __first2[__i]); });
}
@@ -59,7 +59,7 @@ __pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator1 __first1,
_ForwardIterator2 __first2, _Tp __init, _BinaryOperation1 __binary_op1,
_BinaryOperation2 __binary_op2) noexcept
{
- return __brick_transform_reduce(__first1, __last1, __first2, __init, __binary_op1, __binary_op2,
+ return __brick_transform_reduce(__first1, __last1, __first2, std::move(__init), __binary_op1, __binary_op2,
typename _Tag::__is_vector{});
}
@@ -79,12 +79,12 @@ __pattern_transform_reduce(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& _
__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first1, __last1,
[__first1, __first2, __binary_op2](_RandomAccessIterator1 __i) mutable
{ return __binary_op2(*__i, *(__first2 + (__i - __first1))); },
- __init,
+ std::move(__init),
__binary_op1, // Combine
[__first1, __first2, __binary_op1, __binary_op2](_RandomAccessIterator1 __i, _RandomAccessIterator1 __j,
_Tp __init) -> _Tp
{
- return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), __init,
+ return __internal::__brick_transform_reduce(__i, __j, __first2 + (__i - __first1), std::move(__init),
__binary_op1, __binary_op2, _IsVector{});
});
});
@@ -99,7 +99,7 @@ _Tp
__brick_transform_reduce(_ForwardIterator __first, _ForwardIterator __last, _Tp __init, _BinaryOperation __binary_op,
_UnaryOperation __unary_op, /*is_vector=*/std::false_type) noexcept
{
- return std::transform_reduce(__first, __last, __init, __binary_op, __unary_op);
+ return std::transform_reduce(__first, __last, std::move(__init), __binary_op, __unary_op);
}
template <class _RandomAccessIterator, class _Tp, class _UnaryOperation, class _BinaryOperation>
@@ -110,7 +110,7 @@ __brick_transform_reduce(_RandomAccessIterator __first, _RandomAccessIterator __
{
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type _DifferenceType;
return __unseq_backend::__simd_transform_reduce(
- __last - __first, __init, __binary_op,
+ __last - __first, std::move(__init), __binary_op,
[=, &__unary_op](_DifferenceType __i) { return __unary_op(__first[__i]); });
}
@@ -120,7 +120,7 @@ _Tp
__pattern_transform_reduce(_Tag, _ExecutionPolicy&&, _ForwardIterator __first, _ForwardIterator __last, _Tp __init,
_BinaryOperation __binary_op, _UnaryOperation __unary_op) noexcept
{
- return __internal::__brick_transform_reduce(__first, __last, __init, __binary_op, __unary_op,
+ return __internal::__brick_transform_reduce(__first, __last, std::move(__init), __binary_op, __unary_op,
typename _Tag::__is_vector{});
}
@@ -138,9 +138,9 @@ __pattern_transform_reduce(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& _
{
return __par_backend::__parallel_transform_reduce(
__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __first, __last,
- [__unary_op](_RandomAccessIterator __i) mutable { return __unary_op(*__i); }, __init, __binary_op,
+ [__unary_op](_RandomAccessIterator __i) mutable { return __unary_op(*__i); }, std::move(__init), __binary_op,
[__unary_op, __binary_op](_RandomAccessIterator __i, _RandomAccessIterator __j, _Tp __init) {
- return __internal::__brick_transform_reduce(__i, __j, __init, __binary_op, __unary_op, _IsVector{});
+ return __internal::__brick_transform_reduce(__i, __j, std::move(__init), __binary_op, __unary_op, _IsVector{});
});
});
}
@@ -181,7 +181,7 @@ __brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __la
__init = __binary_op(__init, __unary_op(*__first));
*__result = __init;
}
- return std::make_pair(__result, __init);
+ return std::make_pair(__result, std::move(__init));
}
// type is arithmetic and binary operation is a user defined operation.
@@ -199,11 +199,11 @@ __brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __la
/*is_vector=*/std::true_type) noexcept
{
#if defined(_PSTL_UDS_PRESENT)
- return __unseq_backend::__simd_scan(__first, __last - __first, __result, __unary_op, __init, __binary_op,
+ return __unseq_backend::__simd_scan(__first, __last - __first, __result, __unary_op, std::move(__init), __binary_op,
_Inclusive());
#else
// We need to call serial brick here to call function for inclusive and exclusive scan that depends on _Inclusive() value
- return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
+ return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, std::move(__init), __binary_op, _Inclusive(),
/*is_vector=*/std::false_type());
#endif
}
@@ -215,7 +215,7 @@ __brick_transform_scan(_RandomAccessIterator __first, _RandomAccessIterator __la
_UnaryOperation __unary_op, _Tp __init, _BinaryOperation __binary_op, _Inclusive,
/*is_vector=*/std::true_type) noexcept
{
- return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, __init, __binary_op, _Inclusive(),
+ return __internal::__brick_transform_scan(__first, __last, __result, __unary_op, std::move(__init), __binary_op, _Inclusive(),
/*is_vector=*/std::false_type());
}
@@ -247,19 +247,19 @@ __pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __e
{
__par_backend::__parallel_transform_scan(
__backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __last - __first,
- [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, __init,
+ [__first, __unary_op](_DifferenceType __i) mutable { return __unary_op(__first[__i]); }, std::move(__init),
__binary_op,
[__first, __unary_op, __binary_op](_DifferenceType __i, _DifferenceType __j, _Tp __init)
{
// Execute serial __brick_transform_reduce, due to the explicit SIMD vectorization (reduction) requires a commutative operation for the guarantee of correct scan.
- return __internal::__brick_transform_reduce(__first + __i, __first + __j, __init, __binary_op,
+ return __internal::__brick_transform_reduce(__first + __i, __first + __j, std::move(__init), __binary_op,
__unary_op,
/*__is_vector*/ std::false_type());
},
[__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __j, _Tp __init)
{
return __internal::__brick_transform_scan(__first + __i, __first + __j, __result + __i, __unary_op,
- __init, __binary_op, _Inclusive(), _IsVector{})
+ std::move(__init), __binary_op, _Inclusive(), _IsVector{})
.second;
});
return __result + (__last - __first);
@@ -286,7 +286,7 @@ __pattern_transform_scan(__parallel_tag<_IsVector> __tag, _ExecutionPolicy&& __e
[&]()
{
__par_backend::__parallel_strict_scan(
- __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, __init,
+ __backend_tag{}, std::forward<_ExecutionPolicy>(__exec), __n, std::move(__init),
[__first, __unary_op, __binary_op, __result](_DifferenceType __i, _DifferenceType __len)
{
return __internal::__brick_transform_scan(__first + __i, __first + (__i + __len), __result + __i,
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
new file mode 100644
index 0000000..aee96dd
--- /dev/null
+++ b/libstdc++-v3/include/std/mdspan
@@ -0,0 +1,309 @@
+// <mdspan> -*- C++ -*-
+
+// Copyright The GNU Toolchain Authors.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file mdspan
+ * This is a Standard C++ Library header.
+ */
+
+#ifndef _GLIBCXX_MDSPAN
+#define _GLIBCXX_MDSPAN 1
+
+#ifdef _GLIBCXX_SYSHDR
+#pragma GCC system_header
+#endif
+
+#include <span>
+#include <array>
+#include <type_traits>
+#include <limits>
+#include <utility>
+
+#define __glibcxx_want_mdspan
+#include <bits/version.h>
+
+#ifdef __glibcxx_mdspan
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ namespace __mdspan
+ {
+ template<typename _IndexType, array _Extents>
+ class _ExtentsStorage
+ {
+ public:
+ static consteval bool
+ _S_is_dyn(size_t __ext) noexcept
+ { return __ext == dynamic_extent; }
+
+ template<typename _OIndexType>
+ static constexpr _IndexType
+ _S_int_cast(const _OIndexType& __other) noexcept
+ { return _IndexType(__other); }
+
+ static constexpr size_t _S_rank = _Extents.size();
+
+ // For __r in [0, _S_rank], _S_dynamic_index[__r] is the number
+ // of dynamic extents up to (and not including) __r.
+ //
+ // If __r is the index of a dynamic extent, then
+ // _S_dynamic_index[__r] is the index of that extent in
+ // _M_dynamic_extents.
+ 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)
+ {
+ __ret[__i] = __dyn;
+ __dyn += _S_is_dyn(_Extents[__i]);
+ }
+ __ret[_S_rank] = __dyn;
+ return __ret;
+ }();
+
+ static constexpr size_t _S_rank_dynamic = _S_dynamic_index[_S_rank];
+
+ // For __r in [0, _S_rank_dynamic), _S_dynamic_index_inv[__r] is the
+ // index of the __r-th dynamic extent in _Extents.
+ static constexpr auto _S_dynamic_index_inv = [] consteval
+ {
+ array<size_t, _S_rank_dynamic> __ret;
+ for (size_t __i = 0, __r = 0; __i < _S_rank; ++__i)
+ if (_S_is_dyn(_Extents[__i]))
+ __ret[__r++] = __i;
+ return __ret;
+ }();
+
+ static constexpr size_t
+ _S_static_extent(size_t __r) noexcept
+ { return _Extents[__r]; }
+
+ constexpr _IndexType
+ _M_extent(size_t __r) const noexcept
+ {
+ auto __se = _Extents[__r];
+ if (__se == dynamic_extent)
+ return _M_dynamic_extents[_S_dynamic_index[__r]];
+ else
+ return __se;
+ }
+
+ template<size_t _OtherRank, typename _GetOtherExtent>
+ constexpr void
+ _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept
+ {
+ 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));
+ }
+ }
+
+ constexpr
+ _ExtentsStorage() noexcept = default;
+
+ template<typename _OIndexType, array _OExtents>
+ constexpr
+ _ExtentsStorage(const _ExtentsStorage<_OIndexType, _OExtents>&
+ __other) noexcept
+ {
+ _M_init_dynamic_extents<_S_rank>([&__other](size_t __i)
+ { return __other._M_extent(__i); });
+ }
+
+ template<typename _OIndexType, size_t _Nm>
+ constexpr
+ _ExtentsStorage(span<const _OIndexType, _Nm> __exts) noexcept
+ {
+ _M_init_dynamic_extents<_Nm>(
+ [&__exts](size_t __i) -> const _OIndexType&
+ { return __exts[__i]; });
+ }
+
+ private:
+ using _S_storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type;
+ [[no_unique_address]] _S_storage _M_dynamic_extents;
+ };
+
+ template<typename _OIndexType, typename _SIndexType>
+ concept __valid_index_type =
+ is_convertible_v<_OIndexType, _SIndexType> &&
+ is_nothrow_constructible_v<_SIndexType, _OIndexType>;
+
+ template<size_t _Extent, typename _IndexType>
+ concept
+ __valid_static_extent = _Extent == dynamic_extent
+ || _Extent <= numeric_limits<_IndexType>::max();
+ }
+
+ template<typename _IndexType, size_t... _Extents>
+ class extents
+ {
+ static_assert(is_integral_v<_IndexType>, "_IndexType must be integral.");
+ static_assert(
+ (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...),
+ "Extents must either be dynamic or representable as _IndexType");
+
+ public:
+ using index_type = _IndexType;
+ using size_type = make_unsigned_t<index_type>;
+ using rank_type = size_t;
+
+ static constexpr rank_type
+ rank() noexcept { return _S_storage::_S_rank; }
+
+ static constexpr rank_type
+ rank_dynamic() noexcept { return _S_storage::_S_rank_dynamic; }
+
+ static constexpr size_t
+ static_extent(rank_type __r) noexcept
+ {
+ __glibcxx_assert(__r < rank());
+ if constexpr (rank() == 0)
+ __builtin_trap();
+ else
+ return _S_storage::_S_static_extent(__r);
+ }
+
+ constexpr index_type
+ extent(rank_type __r) const noexcept
+ {
+ __glibcxx_assert(__r < rank());
+ if constexpr (rank() == 0)
+ __builtin_trap();
+ else
+ return _M_dynamic_extents._M_extent(__r);
+ }
+
+ constexpr
+ extents() noexcept = default;
+
+ private:
+ static consteval bool
+ _S_is_less_dynamic(size_t __ext, size_t __oext)
+ { return (__ext != dynamic_extent) && (__oext == dynamic_extent); }
+
+ template<typename _OIndexType, size_t... _OExtents>
+ static consteval bool
+ _S_ctor_explicit()
+ {
+ return (_S_is_less_dynamic(_Extents, _OExtents) || ...)
+ || (numeric_limits<index_type>::max()
+ < numeric_limits<_OIndexType>::max());
+ }
+
+ template<size_t... _OExtents>
+ static consteval bool
+ _S_is_compatible_extents()
+ {
+ if constexpr (sizeof...(_OExtents) != rank())
+ return false;
+ else
+ return ((_OExtents == dynamic_extent || _Extents == dynamic_extent
+ || _OExtents == _Extents) && ...);
+ }
+
+ public:
+ template<typename _OIndexType, size_t... _OExtents>
+ 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)
+ { }
+
+ 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)>(
+ initializer_list{_S_storage::_S_int_cast(__exts)...}))
+ { }
+
+ template<__mdspan::__valid_index_type<index_type> _OIndexType, size_t _Nm>
+ 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))
+ { }
+
+
+ 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))
+ { }
+
+ template<typename _OIndexType, size_t... _OExtents>
+ friend constexpr bool
+ operator==(const extents& __self,
+ const extents<_OIndexType, _OExtents...>& __other) noexcept
+ {
+ if constexpr (!_S_is_compatible_extents<_OExtents...>())
+ return false;
+ else
+ {
+ for (size_t __i = 0; __i < __self.rank(); ++__i)
+ if (!cmp_equal(__self.extent(__i), __other.extent(__i)))
+ return false;
+ return true;
+ }
+ }
+
+ private:
+ using _S_storage = __mdspan::_ExtentsStorage<
+ _IndexType, array<size_t, sizeof...(_Extents)>{_Extents...}>;
+ [[no_unique_address]] _S_storage _M_dynamic_extents;
+
+ template<typename _OIndexType, size_t... _OExtents>
+ friend class extents;
+ };
+
+ namespace __mdspan
+ {
+ template<typename _IndexType, size_t... _Counts>
+ auto __build_dextents_type(integer_sequence<size_t, _Counts...>)
+ -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>;
+
+ template<typename _Tp>
+ consteval size_t
+ __dynamic_extent() { return dynamic_extent; }
+ }
+
+ template<typename _IndexType, size_t _Rank>
+ using dextents = decltype(__mdspan::__build_dextents_type<_IndexType>(
+ make_index_sequence<_Rank>()));
+
+ template<typename... _Integrals>
+ requires (is_convertible_v<_Integrals, size_t> && ...)
+ explicit extents(_Integrals...) ->
+ extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>;
+
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+#endif
+#endif
diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric
index 490963e..cbabf031 100644
--- a/libstdc++-v3/include/std/numeric
+++ b/libstdc++-v3/include/std/numeric
@@ -582,7 +582,7 @@ namespace __detail
{
if (__first != __last)
{
- auto __init = *__first;
+ auto __init = std::move(*__first);
*__result++ = __init;
++__first;
if (__first != __last)
@@ -645,8 +645,8 @@ namespace __detail
{
while (__first != __last)
{
- auto __v = __init;
- __init = __binary_op(__init, __unary_op(*__first));
+ auto __v = std::move(__init);
+ __init = __binary_op(__v, __unary_op(*__first));
++__first;
*__result++ = std::move(__v);
}
diff --git a/libstdc++-v3/src/c++17/fs_path.cc b/libstdc++-v3/src/c++17/fs_path.cc
index 6582f10..215afa0 100644
--- a/libstdc++-v3/src/c++17/fs_path.cc
+++ b/libstdc++-v3/src/c++17/fs_path.cc
@@ -880,6 +880,16 @@ path::operator+=(const path& p)
return *this;
}
+ // Handle p += p which would otherwise access dangling pointers after
+ // reallocating _M_cmpts and _M_pathname.
+ if (&p == this) [[unlikely]]
+ return *this += p.native();
+ // Handle p += *i where i is in [p.begin(),p.end()), for the same reason.
+ if (_M_type() == _Type::_Multi && p._M_type() != _Type::_Multi)
+ for (const path& cmpt : *this)
+ if (&cmpt == &p) [[unlikely]]
+ return *this += p.native();
+
#if _GLIBCXX_FILESYSTEM_IS_WINDOWS
if (_M_type() == _Type::_Root_name
|| (_M_type() == _Type::_Filename && _M_pathname.size() == 1))
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index 930a489..d45ae63 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -1833,7 +1833,14 @@ export namespace std
}
}
-// FIXME <mdspan>
+// <mdspan>
+#if __glibcxx_mdspan
+export namespace std
+{
+ using std::extents;
+ // FIXME layout_*, default_accessor and mdspan
+}
+#endif
// 20.2 <memory>
export namespace std
@@ -3107,6 +3114,7 @@ export namespace std
#if __cpp_lib_is_layout_compatible
using std::is_corresponding_member;
using std::is_layout_compatible;
+ using std::is_layout_compatible_v;
#endif
#if __cpp_lib_is_pointer_interconvertible
using std::is_pointer_interconvertible_base_of;
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
new file mode 100644
index 0000000..b654e39
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++23 } }
+#include<mdspan>
+
+std::extents<char, size_t(1) << 9> e1; // { dg-error "from here" }
+std::extents<double, 1> e2; // { dg-error "from here" }
+// { dg-prune-output "dynamic or representable as _IndexType" }
+// { dg-prune-output "must be integral" }
+// { dg-prune-output "invalid use of incomplete type" }
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc
new file mode 100644
index 0000000..a7b3a169
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_copy.cc
@@ -0,0 +1,82 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+
+// Test the copy ctor and the ctor from other extents.
+
+constexpr auto dyn = std::dynamic_extent;
+
+// Not constructible
+static_assert(!std::is_constructible_v<std::extents<int>,
+ std::extents<int, 1>>);
+
+static_assert(!std::is_constructible_v<std::extents<int, 1, 1>,
+ std::extents<int, 1>>);
+
+static_assert(!std::is_constructible_v<std::extents<int, dyn>,
+ std::extents<int, dyn, dyn>>);
+
+static_assert(!std::is_constructible_v<std::extents<int, 2, 2>,
+ std::extents<int, 1, 2>>);
+
+// Nothrow constructible
+static_assert(std::is_nothrow_constructible_v<std::extents<int, 1>,
+ std::extents<unsigned int, dyn>>);
+static_assert(std::is_nothrow_constructible_v<std::extents<unsigned int, dyn>,
+ std::extents<int, 1>>);
+
+// Implicit conversion
+static_assert(!std::is_convertible_v<std::extents<unsigned int>,
+ std::extents<int>>);
+static_assert(std::is_convertible_v<std::extents<int>,
+ std::extents<unsigned int>>);
+
+static_assert(!std::is_convertible_v<std::extents<unsigned int, 1>,
+ std::extents<int, 1>>);
+static_assert(std::is_convertible_v<std::extents<int, 1>,
+ std::extents<unsigned int, 1>>);
+
+static_assert(!std::is_convertible_v<std::extents<int, dyn>,
+ std::extents<int, 1>>);
+static_assert(std::is_convertible_v<std::extents<int, 1>,
+ std::extents<int, dyn>>);
+
+static_assert(!std::is_convertible_v<std::extents<unsigned int, 1>,
+ std::extents<int, dyn>>);
+static_assert(std::is_convertible_v<std::extents<int, 1>,
+ std::extents<unsigned int, dyn>>);
+
+template<typename T, size_t... Extents, typename Other>
+ constexpr void
+ test_ctor(const Other& other)
+ {
+ auto e = std::extents<T, Extents...>(other);
+ VERIFY(e == other);
+ }
+
+constexpr int
+test_all()
+{
+ auto e0 = std::extents<int>();
+ test_ctor<int>(e0);
+
+ auto e1 = std::extents<int, 1, 2, 3>();
+ test_ctor<int, 1, 2, 3>(e1);
+ test_ctor<int, 1, dyn, 3>(e1);
+ test_ctor<unsigned int, 1, dyn, 3>(e1);
+
+ auto e2 = std::extents<unsigned int, 1, dyn, 3>{1, 2, 3};
+ test_ctor<int, 1, 2, 3>(e2);
+ test_ctor<int, 1, dyn, 3>(e2);
+ test_ctor<int, 1, dyn, dyn>(e2);
+ return true;
+}
+
+int
+main()
+{
+ test_all();
+ static_assert(test_all());
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
new file mode 100644
index 0000000..3a70efd
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc
@@ -0,0 +1,62 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+
+constexpr auto dyn = std::dynamic_extent;
+
+class A {};
+
+// Not constructible if the number of integer-like arguments isn't either
+// rank() or rank_dynamic().
+static_assert(!std::is_constructible_v<std::extents<int>, int>);
+static_assert(!std::is_constructible_v<std::extents<int, dyn, dyn>, int>);
+static_assert(!std::is_constructible_v<std::extents<int, 1, dyn, 3>, int, int>);
+
+// Not constructible from non integer-like objects.
+static_assert(!std::is_constructible_v<std::extents<int, 1>, int, A>);
+
+// No implicit conversion from integer-like objects.
+template<typename Extent, typename... OExtents>
+ constexpr bool
+ is_explicit()
+ {
+ return std::is_nothrow_constructible_v<Extent, OExtents...>
+ && !std::is_convertible_v<Extent, OExtents...>;
+ }
+
+static_assert(is_explicit<std::extents<int, 1>, int>());
+static_assert(is_explicit<std::extents<int, 1>, unsigned int>());
+static_assert(is_explicit<std::extents<unsigned int, 1>, int>());
+
+constexpr bool
+test_all()
+{
+ auto expected = std::extents<int, 1, 2, 3>(1, 2, 3);
+
+ // From all extents.
+ VERIFY((std::extents<int, 1, 2, 3>(1, 2, 3)) == expected);
+ VERIFY((std::extents<int, dyn, 2, 3>(1, 2, 3)) == expected);
+ VERIFY((std::extents<int, dyn, 2, dyn>(1, 2, 3)) == expected);
+
+ VERIFY((std::extents<int, 1, 2, 3>{1, 2, 3}) == expected);
+ VERIFY((std::extents<int, dyn, 2, 3>{1, 2, 3}) == expected);
+ VERIFY((std::extents<int, dyn, 2, dyn>{1, 2, 3}) == expected);
+
+ // From only dynamic extents.
+ VERIFY((std::extents<int, dyn, 2, 3>(1)) == expected);
+ VERIFY((std::extents<int, dyn, 2, dyn>(1, 3)) == expected);
+
+ VERIFY((std::extents<int, dyn, 2, 3>{1}) == expected);
+ VERIFY((std::extents<int, dyn, 2, dyn>{1, 3}) == expected);
+
+ return true;
+}
+
+int
+main()
+{
+ test_all();
+ static_assert(test_all());
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc
new file mode 100644
index 0000000..01624f2
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_shape.cc
@@ -0,0 +1,160 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+
+constexpr auto dyn = std::dynamic_extent;
+
+template<typename Extent, typename T, size_t N>
+ constexpr bool
+ constructible()
+ {
+ return std::is_nothrow_constructible_v<Extent, std::array<T, N>>
+ && std::is_nothrow_constructible_v<Extent, std::span<T, N>>;
+ }
+
+template<typename Extent, typename T, size_t N>
+ constexpr bool
+ not_constructible()
+ {
+ return !std::is_constructible_v<Extent, std::array<T, N>>
+ && !std::is_constructible_v<Extent, std::span<T, N>>;
+ }
+
+template<typename Extent, typename T, size_t N>
+ constexpr bool
+ convertible()
+ {
+ return std::is_convertible_v<std::array<T, N>, Extent>
+ && std::is_convertible_v<std::span<T, N>, Extent>;
+ }
+
+template<typename Extent, typename T, size_t N>
+ constexpr bool
+ not_convertible()
+ {
+ return !std::is_convertible_v<std::array<T, N>, Extent>
+ && !std::is_convertible_v<std::span<T, N>, Extent>;
+ }
+
+static_assert(constructible<std::extents<int, 1, 2>, int, 2>());
+static_assert(not_constructible<std::extents<int, 1, 2>, int, 1>());
+
+static_assert(constructible<std::extents<int>, int, 0>());
+static_assert(convertible<std::extents<int>, int, 0>());
+static_assert(convertible<std::extents<unsigned int>, int, 0>());
+static_assert(convertible<std::extents<int>, unsigned int, 0>());
+
+static_assert(constructible<std::extents<int, 1, dyn>, int, 1>());
+static_assert(convertible<std::extents<int, 1, dyn>, int, 1>());
+static_assert(convertible<std::extents<unsigned int, 1, dyn>, int, 1>());
+static_assert(convertible<std::extents<int, 1, dyn>, unsigned int, 1>());
+
+static_assert(constructible<std::extents<int, 1, dyn>, int, 2>());
+static_assert(not_convertible<std::extents<int, 1, dyn>, int, 2>());
+static_assert(not_convertible<std::extents<unsigned int, 1, dyn>, int, 2>());
+static_assert(not_convertible<std::extents<int, 1, dyn>, unsigned int, 2>());
+
+// Non-integer, but convertible.
+static_assert(constructible<std::extents<int, dyn>, double, 1>());
+static_assert(convertible<std::extents<int, dyn>, double, 1>());
+
+namespace all_extents
+{
+ template<typename Shape>
+ constexpr void
+ test_ctor(Shape shape)
+ {
+ auto expected = std::extents<int, 1, 2, 3>();
+ VERIFY((std::extents<int, 1, dyn, 3>(shape)) == expected);
+ VERIFY((std::extents<int, dyn, dyn, dyn>(shape)) == expected);
+ VERIFY((std::extents<int, 1, 2, 3>(shape)) == expected);
+ }
+
+ constexpr void
+ test_common_shapes()
+ {
+ auto array = std::array<int, 3>{1, 2, 3};
+ auto span_const = std::span<const int, 3>(array);
+ auto span = std::span<int, 3>(array);
+
+ test_ctor(array);
+ test_ctor(span);
+ test_ctor(span_const);
+ }
+
+ constexpr void
+ test_empty_shapes()
+ {
+ auto shape = std::array<int, 0>();
+ auto span = std::span<int, 0>(shape);
+
+ auto expected = std::extents<int>();
+ VERIFY((std::extents<int>(shape)) == expected);
+ VERIFY((std::extents<int>(span)) == expected);
+ }
+
+ constexpr bool
+ test_all()
+ {
+ test_common_shapes();
+ test_empty_shapes();
+ return true;
+ }
+}
+
+namespace only_dynamic_extents
+{
+ template<typename Extents, typename Shape>
+ constexpr void
+ test_ctor(const Shape& shape)
+ {
+ Extents e = shape;
+
+ VERIFY(e.rank_dynamic() == shape.size());
+
+ size_t di = 0;
+ for(size_t i = 0; i < e.rank(); ++i)
+ if(e.static_extent(i) == dyn)
+ VERIFY(e.extent(i) == shape[di++]);
+ }
+
+ template<typename Extents, typename T, size_t N>
+ constexpr void
+ test_all_shape_types(std::array<T, N> shape)
+ {
+ test_ctor<Extents>(shape);
+ test_ctor<Extents>(std::span<T, N>(shape));
+ test_ctor<Extents>(std::span<const T, N>(shape));
+ }
+
+ constexpr void
+ test_common_shapes()
+ {
+ auto s = std::array<int, 0>{};
+ auto s2 = std::array<int, 1>{2};
+ auto s123 = std::array<int, 3>{1, 2, 3};
+
+ test_all_shape_types<std::extents<int, 1, dyn, 3>>(s2);
+ test_all_shape_types<std::extents<int, dyn, dyn, dyn>>(s123);
+ test_all_shape_types<std::extents<int, 1, 2, 3>>(s);
+ }
+
+ constexpr bool
+ test_all()
+ {
+ test_common_shapes();
+ return true;
+ }
+}
+
+int
+main()
+{
+ all_extents::test_all();
+ static_assert(all_extents::test_all());
+
+ only_dynamic_extents::test_all();
+ static_assert(only_dynamic_extents::test_all());
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
new file mode 100644
index 0000000..2907ad1
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/custom_integer.cc
@@ -0,0 +1,87 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+
+// Test construction from a custom integer-like object, that has
+// no copy/move ctor or copy/move assignment operator.
+
+constexpr size_t dyn = std::dynamic_extent;
+
+class IntLike
+{
+public:
+ explicit
+ IntLike(int i)
+ : _M_i(i)
+ { }
+
+ IntLike() = delete;
+ IntLike(const IntLike&) = delete;
+ IntLike(IntLike&&) = delete;
+
+ const IntLike&
+ operator=(const IntLike&) = delete;
+
+ const IntLike&
+ operator=(IntLike&&) = delete;
+
+ constexpr
+ operator int() const noexcept
+ { return _M_i; }
+
+private:
+ int _M_i;
+};
+
+static_assert(std::is_convertible_v<IntLike, int>);
+static_assert(std::is_nothrow_constructible_v<int, IntLike>);
+
+void
+test_shape(const auto& s2, const auto& s23)
+{
+ std::extents<int, 2, 3> expected;
+
+ std::extents<int, 2, 3> e1(s23);
+ VERIFY(e1 == expected);
+
+ std::extents<int, dyn, 3> e2(s2);
+ VERIFY(e2 == expected);
+
+ std::extents<int, dyn, 3> e3(s23);
+ VERIFY(e3 == expected);
+
+ std::extents<int, dyn, dyn> e4(s23);
+ VERIFY(e4 == expected);
+}
+
+void
+test_pack()
+{
+ std::extents<int, 2, 3> expected;
+
+ std::extents<int, dyn, 3> e1(IntLike(2));
+ VERIFY(e1 == expected);
+
+ std::extents<int, dyn, 3> e2(IntLike(2), IntLike(3));
+ VERIFY(e2 == expected);
+
+ std::extents<int, dyn, dyn> e3(IntLike(2), IntLike(3));
+ VERIFY(e3 == expected);
+}
+
+int
+main()
+{
+ auto a2 = std::array<IntLike, 1>{IntLike(2)};
+ auto s2 = std::span<IntLike, 1>(a2);
+
+ auto a23 = std::array<IntLike, 2>{IntLike(2), IntLike(3)};
+ auto s23 = std::span<IntLike, 2>(a23);
+
+ test_shape(a2, a23);
+ test_shape(s2, s23);
+ test_pack();
+
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
new file mode 100644
index 0000000..16204aa
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/extents/misc.cc
@@ -0,0 +1,224 @@
+// { dg-do run { target c++23 } }
+#include <mdspan>
+
+#include <testsuite_hooks.h>
+
+constexpr size_t dyn = std::dynamic_extent;
+
+// Check class traits.
+static_assert(std::regular<std::extents<int>>);
+static_assert(std::regular<std::extents<int, 1>>);
+static_assert(std::regular<std::extents<int, dyn>>);
+
+static_assert(std::is_trivially_copyable_v<std::extents<int>>);
+static_assert(std::is_trivially_copyable_v<std::extents<int, 1>>);
+static_assert(std::is_trivially_copyable_v<std::extents<int, dyn>>);
+
+// Check member typedefs.
+static_assert(std::is_same_v<std::extents<int, 1, 2>::rank_type, size_t>);
+
+static_assert(std::is_unsigned_v<std::extents<int, 2>::size_type>);
+static_assert(std::is_unsigned_v<std::extents<unsigned int, 2>::size_type>);
+
+static_assert(std::is_same_v<std::extents<char, 2>::index_type, char>);
+static_assert(std::is_same_v<std::extents<int, 2>::index_type, int>);
+static_assert(std::is_same_v<std::extents<unsigned int, 2>::index_type,
+ unsigned int>);
+
+// Check `rank`.
+static_assert(std::extents<int, 1>::rank() == 1);
+static_assert(std::extents<int, dyn>::rank() == 1);
+static_assert(std::extents<int, 2, dyn>::rank() == 2);
+
+// Check `rank_dynamic`.
+static_assert(std::extents<int, 1>::rank_dynamic() == 0);
+static_assert(std::extents<int, dyn>::rank_dynamic() == 1);
+static_assert(std::extents<int, 2, dyn>::rank_dynamic() == 1);
+static_assert(std::extents<int, dyn, dyn>::rank_dynamic() == 2);
+
+template<typename T, size_t... Extents>
+ constexpr bool
+ check_rank_return_types()
+ {
+ auto e = std::extents<T, Extents...>();
+ return std::is_same_v<decltype(e.rank()), size_t>
+ && std::is_same_v<decltype(e.rank_dynamic()), size_t>;
+ }
+
+static_assert(check_rank_return_types<int, 1>());
+
+// Check that the static extents don't take up space.
+static_assert(sizeof(std::extents<int, 1, dyn>) == sizeof(int));
+static_assert(sizeof(std::extents<char, 1, dyn>) == sizeof(char));
+
+template<typename Extents>
+class Container
+{
+ int dummy;
+ [[no_unique_address]] std::extents<size_t> b0;
+};
+
+static_assert(sizeof(Container<std::extents<char, 1, 2>>) == sizeof(int));
+static_assert(sizeof(Container<std::extents<size_t, 1, 2>>) == sizeof(int));
+
+// operator=
+static_assert(std::is_nothrow_assignable_v<std::extents<int, dyn, 2>,
+ std::extents<int, 1, 2>>);
+
+constexpr bool
+test_assign()
+{
+ auto e1 = std::extents<int, 1, 2>();
+ auto e2 = std::extents<int, 1, 2>();
+
+ e2 = e1;
+ VERIFY(e2 == e1);
+
+ auto e5 = std::extents<int, 1, dyn>();
+ e5 = e1;
+ VERIFY(e5 == e1);
+
+ auto e3 = std::extents<int, dyn, dyn>(1, 2);
+ auto e4 = std::extents<int, dyn, dyn>(3, 4);
+ e3 = e4;
+ VERIFY(e3 == e4);
+ return true;
+}
+
+// Deduction guide
+template<size_t Rank, typename... Extents>
+constexpr void
+test_deduction(Extents... exts)
+{
+ std::array<size_t, sizeof...(exts)> shape{static_cast<size_t>(exts)...};
+ std::dextents<size_t, Rank> expected(shape);
+ std::extents e(exts...);
+ static_assert(std::is_same_v<decltype(e), std::dextents<size_t, Rank>>);
+ VERIFY(e == expected);
+}
+
+constexpr bool
+test_deduction_all()
+{
+ test_deduction<0>();
+ test_deduction<1>(1);
+ test_deduction<2>(1.0, 2.0f);
+ test_deduction<3>(int(1), char(2), size_t(3));
+ return true;
+}
+
+class A {};
+
+template<typename... Extents>
+ concept deducible = requires
+ {
+ { std::extents(Extents{}...) }
+ -> std::convertible_to<std::dextents<size_t, sizeof...(Extents)>>;
+ };
+
+static_assert(deducible<int>);
+static_assert(!deducible<A, A>);
+
+// dextents
+static_assert(std::is_same_v<std::dextents<int, 0>, std::extents<int>>);
+static_assert(std::is_same_v<std::dextents<int, 1>, std::extents<int, dyn>>);
+static_assert(std::is_same_v<std::dextents<int, 5>,
+ std::extents<int, dyn, dyn, dyn, dyn, dyn>>);
+
+static_assert(std::dextents<int, 5>::rank() == 5);
+static_assert(std::dextents<int, 5>::rank_dynamic() == 5);
+static_assert(std::is_same_v<typename std::dextents<int, 5>::index_type, int>);
+
+// static_extent
+static_assert(std::extents<int, 1, 2>::static_extent(0) == 1);
+static_assert(std::extents<int, 1, 2>::static_extent(1) == 2);
+
+static_assert(std::extents<int, 1, dyn>::static_extent(0) == 1);
+static_assert(std::extents<int, 1, dyn>::static_extent(1) == dyn);
+
+static_assert(std::extents<int, dyn, dyn>::static_extent(0) == dyn);
+static_assert(std::extents<int, dyn, dyn>::static_extent(1) == dyn);
+
+// extent
+template<typename Extent>
+ constexpr void
+ test_extent(const Extent& e,
+ const std::array<typename Extent::index_type, Extent::rank()>& shape)
+ {
+ for(size_t i = 0; i < e.rank(); ++i)
+ VERIFY(e.extent(i) == shape[i]);
+ }
+
+constexpr bool
+test_extent_all()
+{
+ test_extent(std::extents<int, 1, 2>{}, {1, 2});
+ test_extent(std::extents<int, 1, dyn>{2}, {1, 2});
+ test_extent(std::extents<int, dyn, dyn>{1, 2}, {1, 2});
+ return true;
+}
+
+// operator==
+template<typename Lhs, typename Rhs>
+ constexpr void
+ test_ops_eq(const Lhs& lhs, const Rhs& rhs, bool expected)
+ {
+ VERIFY((lhs == rhs) == expected);
+ VERIFY((lhs != rhs) == !expected);
+ }
+
+constexpr void
+test_op_eq_rank_zero()
+{
+ auto e1 = std::extents<int>();
+ auto e2 = std::extents<int>();
+ auto e3 = std::extents<unsigned int>();
+
+ test_ops_eq(e1, e2, true);
+ test_ops_eq(e1, e3, true);
+}
+
+constexpr void
+test_op_eq_common()
+{
+ auto e1 = std::extents<int, 1, 2, 3>();
+ auto e2 = std::extents<int, 1, 2, 3>();
+ auto e3 = std::extents<int, 1, dyn, 3>(2);
+ auto e4 = std::extents<int, 1, dyn, 3>(3);
+
+ auto e5 = std::extents<int, 1>();
+ auto e6 = std::extents<int, 1, 3, 3>();
+
+ test_ops_eq(e1, e2, true);
+ test_ops_eq(e1, e3, true);
+ test_ops_eq(e1, e4, false);
+
+ test_ops_eq(e1, e5, false);
+ test_ops_eq(e1, e6, false);
+ test_ops_eq(e3, e6, false);
+}
+
+constexpr bool
+test_op_eq_all()
+{
+ test_op_eq_rank_zero();
+ test_op_eq_common();
+ return true;
+}
+
+int
+main()
+{
+ test_assign();
+ static_assert(test_assign());
+
+ test_deduction_all();
+ static_assert(test_deduction_all());
+
+ test_extent_all();
+ static_assert(test_extent_all());
+
+ test_op_eq_all();
+ static_assert(test_op_eq_all());
+ return 0;
+}
diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/108236.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/108236.cc
index e0e3027..cbef8ab 100644
--- a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/108236.cc
+++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/108236.cc
@@ -8,30 +8,6 @@
#include <execution>
#include <testsuite_hooks.h>
-struct Mint
-{
- Mint(int i = 0) : val(i) { }
- Mint(Mint&&) = default;
- Mint& operator=(Mint&&) = default;
-
- operator int() const { return val; }
-
-private:
- int val;
-};
-
-void
-test_move_only()
-{
- const int input[]{10, 20, 30};
- int output[3];
- std::exclusive_scan(std::execution::seq, input, input+3, output, Mint(5),
- std::plus<int>{});
- VERIFY( output[0] == 5 );
- VERIFY( output[1] == 15 );
- VERIFY( output[2] == 35 );
-}
-
void
test_pr108236()
{
@@ -45,6 +21,5 @@ test_pr108236()
int main()
{
- test_move_only();
test_pr108236();
}
diff --git a/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/move_only.cc b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/move_only.cc
new file mode 100644
index 0000000..38ad3c2
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/pstl/numeric_ops/move_only.cc
@@ -0,0 +1,90 @@
+// { dg-options "-ltbb" }
+// { dg-do run { target c++17 } }
+// { dg-require-effective-target tbb_backend }
+
+#include <numeric>
+#include <execution>
+#include <testsuite_hooks.h>
+
+struct Mint
+{
+ Mint(int i = 0) : val(i) { }
+
+ Mint(Mint&& m) : val(m.val) { m.val = -1; }
+
+ Mint& operator=(Mint&& m)
+ {
+ val = m.val;
+ m.val = -1;
+ return *this;
+ }
+
+ operator int() const
+ {
+ VERIFY(val >= 0); // Check we don't read value of a moved-from instance.
+ return val;
+ }
+
+ friend Mint operator+(const Mint& lhs, const Mint& rhs)
+ { return Mint(lhs.val + rhs.val); }
+
+private:
+ int val;
+};
+
+void
+test_reduce()
+{
+ Mint input[]{1, 2, 3};
+ Mint m = std::reduce(std::execution::seq, input, input+3);
+ VERIFY( static_cast<int>(m) == 6 );
+
+ m = std::reduce(std::execution::seq, input, input+3, Mint(100));
+ VERIFY( static_cast<int>(m) == 106 );
+
+ m = std::reduce(std::execution::seq, input, input+3, Mint(200),
+ std::plus<>{});
+ VERIFY( static_cast<int>(m) == 206 );
+}
+
+void
+test_transform_reduce()
+{
+}
+
+void
+test_exclusive_scan()
+{
+ const int input[]{10, 20, 30};
+ int output[3];
+ std::exclusive_scan(std::execution::seq, input, input+3, output, Mint(5),
+ std::plus<int>{});
+ VERIFY( output[0] == 5 );
+ VERIFY( output[1] == 15 );
+ VERIFY( output[2] == 35 );
+}
+
+void
+test_inclusive_scan()
+{
+}
+
+void
+test_transform_exclusive_scan()
+{
+}
+
+void
+test_transform_inclusive_scan()
+{
+}
+
+int main()
+{
+ test_reduce();
+ test_transform_reduce();
+ test_exclusive_scan();
+ test_inclusive_scan();
+ test_transform_exclusive_scan();
+ test_transform_inclusive_scan();
+}
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/concat/120029.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/120029.cc
new file mode 100644
index 0000000..5153d59
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/concat/120029.cc
@@ -0,0 +1,72 @@
+// { dg-do run { target c++17 } }
+
+// Bug libstdc++/120029
+// Dangling iterator usage in path::operator+=(const path& p) when this == p
+
+#include <filesystem>
+#include <testsuite_hooks.h>
+
+namespace fs = std::filesystem;
+
+void
+test_root_dir()
+{
+ fs::path p = "/";
+ p += p;
+ p += p;
+ VERIFY( p == "////" );
+ p += p.filename();
+ VERIFY( p == "////" );
+ p += *std::prev(p.end());
+ VERIFY( p == "////" );
+}
+
+void
+test_root_name()
+{
+ fs::path p = "C:/";
+ p += p;
+ p += p;
+ VERIFY( p == "C:/C:/C:/C:/" );
+ p += p.filename();
+ VERIFY( p == "C:/C:/C:/C:/" );
+ p += *std::prev(p.end());
+ VERIFY( p == "C:/C:/C:/C:/" );
+}
+
+void
+test_filename()
+{
+ fs::path p = "file";
+ p += p;
+ p += p;
+ VERIFY( p == "filefilefilefile" );
+ p += p.filename();
+ VERIFY( p == "filefilefilefilefilefilefilefile" );
+ p += *std::prev(p.end());
+ VERIFY( p == "filefilefilefilefilefilefilefilefilefilefilefilefilefilefilefile" );
+}
+
+void
+test_multi()
+{
+ fs::path p = "/home/username/Documents/mu";
+ p += p;
+ p += p;
+ VERIFY( p == "/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mu" );
+ p += p.filename();
+ VERIFY( p == "/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mumu" );
+ p += *std::prev(p.end());
+ VERIFY( p == "/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mumumumu" );
+ auto n = std::distance(p.begin(), p.end());
+ for (int i = 0; i < n; ++i)
+ p += *std::next(p.begin(), i);
+}
+
+int main()
+{
+ test_root_dir();
+ test_root_name();
+ test_filename();
+ test_multi();
+}
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/concat/120029.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/concat/120029.cc
new file mode 100644
index 0000000..209d968
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/filesystem/path/concat/120029.cc
@@ -0,0 +1,74 @@
+// { dg-options "-DUSE_FILESYSTEM_TS -lstdc++fs" }
+// { dg-do run { target c++11 } }
+// { dg-require-filesystem-ts "" }
+
+// Bug libstdc++/120029
+// Dangling iterator usage in path::operator+=(const path& p) when this == p
+
+#include <experimental/filesystem>
+#include <testsuite_hooks.h>
+
+namespace fs = std::experimental::filesystem;
+
+void
+test_root_dir()
+{
+ fs::path p = "/";
+ p += p;
+ p += p;
+ VERIFY( p == "////" );
+ p += p.filename();
+ VERIFY( p == "////////" );
+ p += *std::prev(p.end());
+ VERIFY( p == "////////////////" );
+}
+
+void
+test_root_name()
+{
+ fs::path p = "C:/";
+ p += p;
+ p += p;
+ VERIFY( p == "C:/C:/C:/C:/" );
+ p += p.filename(); // For Filesystem TS the filename is "."
+ VERIFY( p == "C:/C:/C:/C:/." );
+ p += *std::prev(p.end());
+ VERIFY( p == "C:/C:/C:/C:/.." );
+}
+
+void
+test_filename()
+{
+ fs::path p = "file";
+ p += p;
+ p += p;
+ VERIFY( p == "filefilefilefile" );
+ p += p.filename();
+ VERIFY( p == "filefilefilefilefilefilefilefile" );
+ p += *std::prev(p.end());
+ VERIFY( p == "filefilefilefilefilefilefilefilefilefilefilefilefilefilefilefile" );
+}
+
+void
+test_multi()
+{
+ fs::path p = "/home/username/Documents/mu";
+ p += p;
+ p += p;
+ VERIFY( p == "/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mu" );
+ p += p.filename();
+ VERIFY( p == "/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mumu" );
+ p += *std::prev(p.end());
+ VERIFY( p == "/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mu/home/username/Documents/mumumumu" );
+ auto n = std::distance(p.begin(), p.end());
+ for (int i = 0; i < n; ++i)
+ p += *std::next(p.begin(), i);
+}
+
+int main()
+{
+ test_root_dir();
+ test_root_name();
+ test_filename();
+ test_multi();
+}
diff --git a/libstdc++-v3/testsuite/std/time/format/pr120114.cc b/libstdc++-v3/testsuite/std/time/format/pr120114.cc
new file mode 100644
index 0000000..c630bb3
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/format/pr120114.cc
@@ -0,0 +1,125 @@
+// { dg-do run { target c++23 } }
+// { dg-options "-fexec-charset=UTF-8" }
+// { dg-timeout-factor 2 }
+
+#include <algorithm>
+#include <chrono>
+#include <testsuite_hooks.h>
+
+#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
+#define WIDEN(S) WIDEN_(_CharT, S)
+
+template<typename _CharT>
+void
+test_from_format_string()
+{
+ std::basic_string<_CharT> res;
+ using namespace std::chrono_literals;
+ auto date = 2025y/std::chrono::May/05d;
+
+ res = std::format(WIDEN("{:+<13%F\U0001f921}"), date);
+ VERIFY( res == WIDEN("2025-05-05\U0001f921+") );
+
+ res = std::format(WIDEN("{:->15%F\U0001f921}"), date);
+ VERIFY( res == WIDEN("---2025-05-05\U0001f921") );
+
+ res = std::format(WIDEN("{:=^20%F\U0001f921}"), date);
+ VERIFY( res == WIDEN("====2025-05-05\U0001f921====") );
+}
+
+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>
+ {
+ 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;
+ switch (t->tm_mon)
+ {
+ case 0:
+ str = WIDEN("\u32C0");
+ break;
+ case 1:
+ str = WIDEN("\u32C1");
+ break;
+ case 2:
+ str = WIDEN("\u32C2");
+ break;
+ case 3:
+ str = WIDEN("\u32C3");
+ break;
+ case 4:
+ str = WIDEN("\u32C4");
+ break;
+ case 5:
+ str = WIDEN("\u32C5");
+ break;
+ case 6:
+ str = WIDEN("\u32C6");
+ break;
+ case 7:
+ str = WIDEN("\u32C7");
+ break;
+ case 8:
+ str = WIDEN("\u32C8");
+ break;
+ case 9:
+ str = WIDEN("\u32C9");
+ break;
+ case 10:
+ str = WIDEN("\u32CA");
+ break;
+ case 11:
+ str = WIDEN("\u32CB");
+ break;
+ };
+ return std::copy(str.begin(), str.end(), out);
+ }
+ };
+ const std::locale loc(std::locale::classic(), new TimePut);
+
+ std::basic_string<_CharT> res;
+
+ res = std::format(loc, WIDEN("{:<1L%Om}"), std::chrono::January);
+ VERIFY( res == WIDEN("\u32C0") );
+
+ res = std::format(loc, WIDEN("{:>2L%Om}"), std::chrono::February);
+ VERIFY( res == WIDEN("\u32C1") );
+
+ res = std::format(loc, WIDEN("{:<3L%Om}"), std::chrono::March);
+ VERIFY( res == WIDEN("\u32C2 ") );
+
+ res = std::format(loc, WIDEN("{:^4L%Om}"), std::chrono::April);
+ VERIFY( res == WIDEN(" \u32C3 ") );
+
+ res = std::format(loc, WIDEN("{:>5L%Om}"), std::chrono::May);
+ VERIFY( res == WIDEN(" \u32C4") );
+
+ res = std::format(loc, WIDEN("{:+<6L%Om}"), std::chrono::June);
+ VERIFY( res == WIDEN("\u32C5++++") );
+
+ res = std::format(loc, WIDEN("{:=^7L%Om}"), std::chrono::July);
+ VERIFY( res == WIDEN("==\u32C6===") );
+
+ res = std::format(loc, WIDEN("{:->8L%Om}"), std::chrono::August);
+ VERIFY( res == WIDEN("------\u32C7") );
+}
+
+int main()
+{
+ test_from_format_string<char>();
+ test_from_format_string<wchar_t>();
+ test_formatted_value<char>();
+ test_formatted_value<wchar_t>();
+}