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