From 988dd22ec6665117e8587389ac85389f1c321c45 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 25 Oct 2022 13:03:12 +0100 Subject: libstdc++: Fix allocator propagation in regex algorithms [PR107376] The PR points out that we assume the match_results allocator is default constuctible, which might not be true. We also have a related issue with unwanted propagation from an object that might have an unequal allocator. Ideally we use the same allocator type for _State_info::_M_match_queue but that would be an ABI change now. We should investigate if that can be done without breaking anything, which might be possible because the _Executor object is short-lived and never leaks out of the regex_match, regex_search, and regex_replace algorithms. If we change the mangled name for _Executor then there would be no ODR violations when mixing old and new definitions. This commit does not attempt that. libstdc++-v3/ChangeLog: PR libstdc++/107376 * include/bits/regex_executor.h (_Executor::_Executor): Use same allocator for _M_cur_results and _M_results. * include/bits/regex_executor.tcc (_Executor::_M_main_dispatch): Prevent possibly incorrect allocator propagating to _M_cur_results. * testsuite/28_regex/algorithms/regex_match/107376.cc: New test. --- libstdc++-v3/include/bits/regex_executor.h | 17 ++--- libstdc++-v3/include/bits/regex_executor.tcc | 3 +- .../28_regex/algorithms/regex_match/107376.cc | 76 ++++++++++++++++++++++ 3 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/regex_executor.h b/libstdc++-v3/include/bits/regex_executor.h index dc0878c..cdafcd5 100644 --- a/libstdc++-v3/include/bits/regex_executor.h +++ b/libstdc++-v3/include/bits/regex_executor.h @@ -71,14 +71,15 @@ namespace __detail _ResultsVec& __results, const _RegexT& __re, _FlagT __flags) - : _M_begin(__begin), - _M_end(__end), - _M_re(__re), - _M_nfa(*__re._M_automaton), - _M_results(__results), - _M_rep_count(_M_nfa.size()), - _M_states(_M_nfa._M_start(), _M_nfa.size()), - _M_flags(__flags) + : _M_cur_results(__results.get_allocator()), + _M_begin(__begin), + _M_end(__end), + _M_re(__re), + _M_nfa(*__re._M_automaton), + _M_results(__results), + _M_rep_count(_M_nfa.size()), + _M_states(_M_nfa._M_start(), _M_nfa.size()), + _M_flags(__flags) { using namespace regex_constants; if (__flags & match_prev_avail) // ignore not_bol and not_bow diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc index b93e958..a5885ed 100644 --- a/libstdc++-v3/include/bits/regex_executor.tcc +++ b/libstdc++-v3/include/bits/regex_executor.tcc @@ -124,9 +124,10 @@ namespace __detail break; std::fill_n(_M_states._M_visited_states, _M_nfa.size(), false); auto __old_queue = std::move(_M_states._M_match_queue); + auto __alloc = _M_cur_results.get_allocator(); for (auto& __task : __old_queue) { - _M_cur_results = std::move(__task.second); + _M_cur_results = _ResultsVec(std::move(__task.second), __alloc); _M_dfs(__match_mode, __task.first); } if (__match_mode == _Match_mode::_Prefix) diff --git a/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc new file mode 100644 index 0000000..da4f7ad --- /dev/null +++ b/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/107376.cc @@ -0,0 +1,76 @@ +// { dg-do run { target c++11 } } +#include +#include +#include + +template +struct Alloc +{ + using value_type = T; + explicit Alloc(int) { } + template Alloc(const Alloc&) { } + + T* allocate(std::size_t n) + { return std::allocator().allocate(n); } + void deallocate(T* ptr, std::size_t n) + { std::allocator().deallocate(ptr, n); } + + bool operator==(const Alloc&) const { return true; } + bool operator!=(const Alloc&) const { return false; } +}; + +void +test_non_default_constructible() +{ + using sub_match = std::sub_match; + using alloc_type = Alloc; + using match_results = std::match_results; + match_results res(alloc_type(1)); + + std::regex_match("x", res, std::regex(".")); // PR libstdc++/107376 +} + +template +struct PropAlloc +{ + int id; + + using value_type = T; + explicit PropAlloc(int id) : id(id) { } + template PropAlloc(const PropAlloc& a) : id(a.id) { } + + using propagate_on_container_move_assignment = std::true_type; + using propagate_on_container_copy_assignment = std::true_type; + + PropAlloc select_on_container_copy_construction() const + { return PropAlloc(0); } + + T* allocate(std::size_t n) + { return std::allocator().allocate(n); } + void deallocate(T* ptr, std::size_t n) + { std::allocator().deallocate(ptr, n); } + + bool operator==(const PropAlloc& a) const { return id == a.id; } + bool operator!=(const PropAlloc& a) const { return id != a.id; } +}; + +void +test_propagation() +{ + using sub_match = std::sub_match; + using alloc_type = PropAlloc; + using match_results = std::match_results; + alloc_type alloc(107376); + match_results res(alloc); + + std::regex re("..", std::regex_constants::__polynomial); + std::regex_match("xx", res, re); + + VERIFY( res.get_allocator() == alloc ); +} + +int main() +{ + test_non_default_constructible(); + test_propagation(); +} -- cgit v1.1 From 655271e47ff87d23d174bd29f66c791beba66ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Date: Thu, 20 Oct 2022 16:20:19 +0200 Subject: libstdc++: Don't use gstdint.h anymore libstdc++-v3/ChangeLog: * configure.ac: Stop generating gstdint.h. * src/c++11/compatibility-atomic-c++0x.cc: Stop using gstdint.h. * Makefile.in: Regenerate. * aclocal.m4: Regenerate. * config.h.in: Regenerate. * configure: Regenerate. * doc/Makefile.in: Regenerate. * include/Makefile.in: Regenerate. * libsupc++/Makefile.in: Regenerate. * po/Makefile.in: Regenerate. * python/Makefile.in: Regenerate. * src/Makefile.in: Regenerate. * src/c++11/Makefile.in: Regenerate. * src/c++17/Makefile.in: Regenerate. * src/c++20/Makefile.in: Regenerate. * src/c++98/Makefile.in: Regenerate. * src/filesystem/Makefile.in: Regenerate. * src/libbacktrace/Makefile.in: Regenerate. * testsuite/Makefile.in: Regenerate. --- libstdc++-v3/Makefile.in | 1 - libstdc++-v3/aclocal.m4 | 1 - libstdc++-v3/config.h.in | 15 - libstdc++-v3/configure | 867 +-------------------- libstdc++-v3/configure.ac | 6 - libstdc++-v3/doc/Makefile.in | 1 - libstdc++-v3/include/Makefile.in | 1 - libstdc++-v3/libsupc++/Makefile.in | 1 - libstdc++-v3/po/Makefile.in | 1 - libstdc++-v3/python/Makefile.in | 1 - libstdc++-v3/src/Makefile.in | 1 - libstdc++-v3/src/c++11/Makefile.in | 1 - .../src/c++11/compatibility-atomic-c++0x.cc | 8 +- libstdc++-v3/src/c++17/Makefile.in | 1 - libstdc++-v3/src/c++20/Makefile.in | 1 - libstdc++-v3/src/c++98/Makefile.in | 1 - libstdc++-v3/src/filesystem/Makefile.in | 1 - libstdc++-v3/src/libbacktrace/Makefile.in | 1 - libstdc++-v3/testsuite/Makefile.in | 1 - 19 files changed, 12 insertions(+), 899 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/Makefile.in b/libstdc++-v3/Makefile.in index a7c2b60..e6a5a5c 100644 --- a/libstdc++-v3/Makefile.in +++ b/libstdc++-v3/Makefile.in @@ -103,7 +103,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/aclocal.m4 b/libstdc++-v3/aclocal.m4 index b2f43aa..e5af3f6 100644 --- a/libstdc++-v3/aclocal.m4 +++ b/libstdc++-v3/aclocal.m4 @@ -865,7 +865,6 @@ m4_include([../config/lthostflags.m4]) m4_include([../config/multi.m4]) m4_include([../config/no-executables.m4]) m4_include([../config/override.m4]) -m4_include([../config/stdint.m4]) m4_include([../config/toolexeclibdir.m4]) m4_include([../config/unwind_ipinfo.m4]) m4_include([../libtool.m4]) diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 2a3972e..acdfa99 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -760,21 +760,6 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION -/* The size of `char', as computed by sizeof. */ -#undef SIZEOF_CHAR - -/* The size of `int', as computed by sizeof. */ -#undef SIZEOF_INT - -/* The size of `long', as computed by sizeof. */ -#undef SIZEOF_LONG - -/* The size of `short', as computed by sizeof. */ -#undef SIZEOF_SHORT - -/* The size of `void *', as computed by sizeof. */ -#undef SIZEOF_VOID_P - /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 9159ffb..db3f6b1 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -2619,60 +2619,6 @@ $as_echo "$ac_res" >&6; } } # ac_fn_cxx_check_func -# ac_fn_c_check_type LINENO TYPE VAR INCLUDES -# ------------------------------------------- -# Tests whether TYPE exists after having included INCLUDES, setting cache -# variable VAR accordingly. -ac_fn_c_check_type () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=no" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -if (sizeof ($2)) - return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -if (sizeof (($2))) - return 0; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - eval "$3=yes" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_type - # ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES # --------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -12236,7 +12182,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12239 "configure" +#line 12185 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12342,7 +12288,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12345 "configure" +#line 12291 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16066,7 +16012,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; } # Fake what AC_TRY_COMPILE does. cat > conftest.$ac_ext << EOF -#line 16069 "configure" +#line 16015 "configure" int main() { typedef bool atomic_type; @@ -16101,7 +16047,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16104 "configure" +#line 16050 "configure" int main() { typedef short atomic_type; @@ -16136,7 +16082,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16139 "configure" +#line 16085 "configure" int main() { // NB: _Atomic_word not necessarily int. @@ -16172,7 +16118,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; } rm -f conftest* cat > conftest.$ac_ext << EOF -#line 16175 "configure" +#line 16121 "configure" int main() { typedef long long atomic_type; @@ -16328,7 +16274,7 @@ $as_echo "mutex" >&6; } # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 16331 "configure" +#line 16277 "configure" int main() { _Decimal32 d1; @@ -16370,7 +16316,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu # unnecessary for this test. cat > conftest.$ac_ext << EOF -#line 16373 "configure" +#line 16319 "configure" template struct same { typedef T2 type; }; @@ -68484,412 +68430,6 @@ $as_echo "#define HAVE_LINUX_FUTEX 1" >>confdefs.h fi -if test "$is_hosted" = yes; then -# TODO: remove this and change src/c++11/compatibility-atomic-c++0x.cc to -# use instead of . - - -inttype_headers=`echo inttypes.h sys/inttypes.h | sed -e 's/,/ /g'` - -acx_cv_header_stdint=stddef.h -acx_cv_header_stdint_kind="(already complete)" -for i in stdint.h $inttype_headers; do - unset ac_cv_type_uintptr_t - unset ac_cv_type_uintmax_t - unset ac_cv_type_int_least32_t - unset ac_cv_type_int_fast32_t - unset ac_cv_type_uint64_t - $as_echo_n "looking for a compliant stdint.h in $i, " >&6 - ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "#include -#include <$i> -" -if test "x$ac_cv_type_uintmax_t" = xyes; then : - acx_cv_header_stdint=$i -else - continue -fi - - ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include -#include <$i> -" -if test "x$ac_cv_type_uintptr_t" = xyes; then : - -else - acx_cv_header_stdint_kind="(mostly complete)" -fi - - ac_fn_c_check_type "$LINENO" "int_least32_t" "ac_cv_type_int_least32_t" "#include -#include <$i> -" -if test "x$ac_cv_type_int_least32_t" = xyes; then : - -else - acx_cv_header_stdint_kind="(mostly complete)" -fi - - ac_fn_c_check_type "$LINENO" "int_fast32_t" "ac_cv_type_int_fast32_t" "#include -#include <$i> -" -if test "x$ac_cv_type_int_fast32_t" = xyes; then : - -else - acx_cv_header_stdint_kind="(mostly complete)" -fi - - ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include -#include <$i> -" -if test "x$ac_cv_type_uint64_t" = xyes; then : - -else - acx_cv_header_stdint_kind="(lacks uint64_t)" -fi - - break -done -if test "$acx_cv_header_stdint" = stddef.h; then - acx_cv_header_stdint_kind="(lacks uintmax_t)" - for i in stdint.h $inttype_headers; do - unset ac_cv_type_uintptr_t - unset ac_cv_type_uint32_t - unset ac_cv_type_uint64_t - $as_echo_n "looking for an incomplete stdint.h in $i, " >&6 - ac_fn_c_check_type "$LINENO" "uint32_t" "ac_cv_type_uint32_t" "#include -#include <$i> -" -if test "x$ac_cv_type_uint32_t" = xyes; then : - acx_cv_header_stdint=$i -else - continue -fi - - ac_fn_c_check_type "$LINENO" "uint64_t" "ac_cv_type_uint64_t" "#include -#include <$i> -" -if test "x$ac_cv_type_uint64_t" = xyes; then : - -fi - - ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "#include -#include <$i> -" -if test "x$ac_cv_type_uintptr_t" = xyes; then : - -fi - - break - done -fi -if test "$acx_cv_header_stdint" = stddef.h; then - acx_cv_header_stdint_kind="(u_intXX_t style)" - for i in sys/types.h $inttype_headers; do - unset ac_cv_type_u_int32_t - unset ac_cv_type_u_int64_t - $as_echo_n "looking for u_intXX_t types in $i, " >&6 - ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "#include -#include <$i> -" -if test "x$ac_cv_type_u_int32_t" = xyes; then : - acx_cv_header_stdint=$i -else - continue -fi - - ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "#include -#include <$i> -" -if test "x$ac_cv_type_u_int64_t" = xyes; then : - -fi - - break - done -fi -if test "$acx_cv_header_stdint" = stddef.h; then - acx_cv_header_stdint_kind="(using manual detection)" -fi - -test -z "$ac_cv_type_uintptr_t" && ac_cv_type_uintptr_t=no -test -z "$ac_cv_type_uint64_t" && ac_cv_type_uint64_t=no -test -z "$ac_cv_type_u_int64_t" && ac_cv_type_u_int64_t=no -test -z "$ac_cv_type_int_least32_t" && ac_cv_type_int_least32_t=no -test -z "$ac_cv_type_int_fast32_t" && ac_cv_type_int_fast32_t=no - -# ----------------- Summarize what we found so far - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking what to include in include/gstdint.h" >&5 -$as_echo_n "checking what to include in include/gstdint.h... " >&6; } - -case `$as_basename -- include/gstdint.h || -$as_expr X/include/gstdint.h : '.*/\([^/][^/]*\)/*$' \| \ - Xinclude/gstdint.h : 'X\(//\)$' \| \ - Xinclude/gstdint.h : 'X\(/\)' \| . 2>/dev/null || -$as_echo X/include/gstdint.h | - sed '/^.*\/\([^/][^/]*\)\/*$/{ - s//\1/ - q - } - /^X\/\(\/\/\)$/{ - s//\1/ - q - } - /^X\/\(\/\).*/{ - s//\1/ - q - } - s/.*/./; q'` in - stdint.h) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: are you sure you want it there?" >&5 -$as_echo "$as_me: WARNING: are you sure you want it there?" >&2;} ;; - inttypes.h) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: are you sure you want it there?" >&5 -$as_echo "$as_me: WARNING: are you sure you want it there?" >&2;} ;; - *) ;; -esac - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_header_stdint $acx_cv_header_stdint_kind" >&5 -$as_echo "$acx_cv_header_stdint $acx_cv_header_stdint_kind" >&6; } - -# ----------------- done included file, check C basic types -------- - -# Lacking an uintptr_t? Test size of void * -case "$acx_cv_header_stdint:$ac_cv_type_uintptr_t" in - stddef.h:* | *:no) # The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5 -$as_echo_n "checking size of void *... " >&6; } -if ${ac_cv_sizeof_void_p+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_void_p" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (void *) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_void_p=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5 -$as_echo "$ac_cv_sizeof_void_p" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_VOID_P $ac_cv_sizeof_void_p -_ACEOF - - ;; -esac - -# Lacking an uint64_t? Test size of long -case "$acx_cv_header_stdint:$ac_cv_type_uint64_t:$ac_cv_type_u_int64_t" in - stddef.h:*:* | *:no:no) # The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 -$as_echo_n "checking size of long... " >&6; } -if ${ac_cv_sizeof_long+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_long" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (long) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_long=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 -$as_echo "$ac_cv_sizeof_long" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_LONG $ac_cv_sizeof_long -_ACEOF - - ;; -esac - -if test $acx_cv_header_stdint = stddef.h; then - # Lacking a good header? Test size of everything and deduce all types. - # The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 -$as_echo_n "checking size of int... " >&6; } -if ${ac_cv_sizeof_int+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_int" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (int) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_int=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 -$as_echo "$ac_cv_sizeof_int" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_INT $ac_cv_sizeof_int -_ACEOF - - - # The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 -$as_echo_n "checking size of short... " >&6; } -if ${ac_cv_sizeof_short+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_short" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (short) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_short=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 -$as_echo "$ac_cv_sizeof_short" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_SHORT $ac_cv_sizeof_short -_ACEOF - - - # The cast to long int works around a bug in the HP C Compiler -# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects -# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. -# This bug is HP SR number 8606223364. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5 -$as_echo_n "checking size of char... " >&6; } -if ${ac_cv_sizeof_char+:} false; then : - $as_echo_n "(cached) " >&6 -else - if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$ac_includes_default"; then : - -else - if test "$ac_cv_type_char" = yes; then - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error 77 "cannot compute sizeof (char) -See \`config.log' for more details" "$LINENO" 5; } - else - ac_cv_sizeof_char=0 - fi -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5 -$as_echo "$ac_cv_sizeof_char" >&6; } - - - -cat >>confdefs.h <<_ACEOF -#define SIZEOF_CHAR $ac_cv_sizeof_char -_ACEOF - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int8_t" >&5 -$as_echo_n "checking for type equivalent to int8_t... " >&6; } - case "$ac_cv_sizeof_char" in - 1) acx_cv_type_int8_t=char ;; - *) as_fn_error $? "no 8-bit type, please report a bug" "$LINENO" 5 - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int8_t" >&5 -$as_echo "$acx_cv_type_int8_t" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int16_t" >&5 -$as_echo_n "checking for type equivalent to int16_t... " >&6; } - case "$ac_cv_sizeof_int:$ac_cv_sizeof_short" in - 2:*) acx_cv_type_int16_t=int ;; - *:2) acx_cv_type_int16_t=short ;; - *) as_fn_error $? "no 16-bit type, please report a bug" "$LINENO" 5 - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int16_t" >&5 -$as_echo "$acx_cv_type_int16_t" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int32_t" >&5 -$as_echo_n "checking for type equivalent to int32_t... " >&6; } - case "$ac_cv_sizeof_int:$ac_cv_sizeof_long" in - 4:*) acx_cv_type_int32_t=int ;; - *:4) acx_cv_type_int32_t=long ;; - *) as_fn_error $? "no 32-bit type, please report a bug" "$LINENO" 5 - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_int32_t" >&5 -$as_echo "$acx_cv_type_int32_t" >&6; } -fi - -# These tests are here to make the output prettier - -if test "$ac_cv_type_uint64_t" != yes && test "$ac_cv_type_u_int64_t" != yes; then - case "$ac_cv_sizeof_long" in - 8) acx_cv_type_int64_t=long ;; - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to int64_t" >&5 -$as_echo_n "checking for type equivalent to int64_t... " >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${acx_cv_type_int64_t-'using preprocessor symbols'}" >&5 -$as_echo "${acx_cv_type_int64_t-'using preprocessor symbols'}" >&6; } -fi - -# Now we can use the above types - -if test "$ac_cv_type_uintptr_t" != yes; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for type equivalent to intptr_t" >&5 -$as_echo_n "checking for type equivalent to intptr_t... " >&6; } - case $ac_cv_sizeof_void_p in - 2) acx_cv_type_intptr_t=int16_t ;; - 4) acx_cv_type_intptr_t=int32_t ;; - 8) acx_cv_type_intptr_t=int64_t ;; - *) as_fn_error $? "no equivalent for intptr_t, please report a bug" "$LINENO" 5 - esac - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_cv_type_intptr_t" >&5 -$as_echo "$acx_cv_type_intptr_t" >&6; } -fi - -# ----------------- done all checks, emit header ------------- -ac_config_commands="$ac_config_commands include/gstdint.h" - - - -fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU c++filt" >&5 $as_echo_n "checking for GNU c++filt... " >&6; } @@ -74304,24 +73844,6 @@ fi -GCC="$GCC" -CC="$CC" -acx_cv_header_stdint="$acx_cv_header_stdint" -acx_cv_type_int8_t="$acx_cv_type_int8_t" -acx_cv_type_int16_t="$acx_cv_type_int16_t" -acx_cv_type_int32_t="$acx_cv_type_int32_t" -acx_cv_type_int64_t="$acx_cv_type_int64_t" -acx_cv_type_intptr_t="$acx_cv_type_intptr_t" -ac_cv_type_uintmax_t="$ac_cv_type_uintmax_t" -ac_cv_type_uintptr_t="$ac_cv_type_uintptr_t" -ac_cv_type_uint64_t="$ac_cv_type_uint64_t" -ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" -ac_cv_type_u_int32_t="$ac_cv_type_u_int32_t" -ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" -ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" -ac_cv_sizeof_void_p="$ac_cv_sizeof_void_p" - - _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 @@ -74333,7 +73855,6 @@ do "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; - "include/gstdint.h") CONFIG_COMMANDS="$CONFIG_COMMANDS include/gstdint.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "scripts/testsuite_flags") CONFIG_FILES="$CONFIG_FILES scripts/testsuite_flags" ;; "scripts/extract_symvers") CONFIG_FILES="$CONFIG_FILES scripts/extract_symvers" ;; @@ -75766,378 +75287,6 @@ compiler_lib_search_path=$lt_compiler_lib_search_path_CXX _LT_EOF ;; - "include/gstdint.h":C) -if test "$GCC" = yes; then - echo "/* generated for " `$CC --version | sed 1q` "*/" > tmp-stdint.h -else - echo "/* generated for $CC */" > tmp-stdint.h -fi - -sed 's/^ *//' >> tmp-stdint.h < -EOF - -if test "$acx_cv_header_stdint" != stdint.h; then - echo "#include " >> tmp-stdint.h -fi -if test "$acx_cv_header_stdint" != stddef.h; then - echo "#include <$acx_cv_header_stdint>" >> tmp-stdint.h -fi - -sed 's/^ *//' >> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <= 199901L - #ifndef _INT64_T - #define _INT64_T - #ifndef __int64_t_defined - #ifndef int64_t - typedef long long int64_t; - #endif - #endif - #endif - #ifndef _UINT64_T - #define _UINT64_T - #ifndef uint64_t - typedef unsigned long long uint64_t; - #endif - #endif - - #elif defined __GNUC__ && defined (__STDC__) && __STDC__-0 - /* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and - does not implement __extension__. But that compiler doesn't define - __GNUC_MINOR__. */ - # if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) - # define __extension__ - # endif - - # ifndef _INT64_T - # define _INT64_T - # ifndef int64_t - __extension__ typedef long long int64_t; - # endif - # endif - # ifndef _UINT64_T - # define _UINT64_T - # ifndef uint64_t - __extension__ typedef unsigned long long uint64_t; - # endif - # endif - - #elif !defined __STRICT_ANSI__ - # if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ - - # ifndef _INT64_T - # define _INT64_T - # ifndef int64_t - typedef __int64 int64_t; - # endif - # endif - # ifndef _UINT64_T - # define _UINT64_T - # ifndef uint64_t - typedef unsigned __int64 uint64_t; - # endif - # endif - # endif /* compiler */ - - #endif /* ANSI version */ -EOF -fi - -# ------------- done int64_t types, emit intptr types ------------ -if test "$ac_cv_type_uintptr_t" != yes; then - sed 's/^ *//' >> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h <> tmp-stdint.h < vpsed$$ << \_EOF diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index 42c4530..3e89d09 100644 --- a/libstdc++-v3/configure.ac +++ b/libstdc++-v3/configure.ac @@ -425,12 +425,6 @@ GCC_CHECK_UNWIND_GETIPINFO GCC_LINUX_FUTEX([AC_DEFINE(HAVE_LINUX_FUTEX, 1, [Define if futex syscall is available.])]) -if test "$is_hosted" = yes; then -# TODO: remove this and change src/c++11/compatibility-atomic-c++0x.cc to -# use instead of . -GCC_HEADER_STDINT(include/gstdint.h) -fi - GLIBCXX_ENABLE_SYMVERS([yes]) AC_SUBST(libtool_VERSION) diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in index 469a608..db5e81a 100644 --- a/libstdc++-v3/doc/Makefile.in +++ b/libstdc++-v3/doc/Makefile.in @@ -103,7 +103,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index dac7765..be3e12a 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -103,7 +103,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in index 1127095..2e755ab 100644 --- a/libstdc++-v3/libsupc++/Makefile.in +++ b/libstdc++-v3/libsupc++/Makefile.in @@ -105,7 +105,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/po/Makefile.in b/libstdc++-v3/po/Makefile.in index af3d4c4..8e93445 100644 --- a/libstdc++-v3/po/Makefile.in +++ b/libstdc++-v3/po/Makefile.in @@ -103,7 +103,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/python/Makefile.in b/libstdc++-v3/python/Makefile.in index 0c600de..05e79b5 100644 --- a/libstdc++-v3/python/Makefile.in +++ b/libstdc++-v3/python/Makefile.in @@ -104,7 +104,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/src/Makefile.in b/libstdc++-v3/src/Makefile.in index c54c0f6..41a00f7 100644 --- a/libstdc++-v3/src/Makefile.in +++ b/libstdc++-v3/src/Makefile.in @@ -104,7 +104,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/src/c++11/Makefile.in b/libstdc++-v3/src/c++11/Makefile.in index 013ab3c..77e11a9 100644 --- a/libstdc++-v3/src/c++11/Makefile.in +++ b/libstdc++-v3/src/c++11/Makefile.in @@ -104,7 +104,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc b/libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc index 5a0c545..e21bd76 100644 --- a/libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc +++ b/libstdc++-v3/src/c++11/compatibility-atomic-c++0x.cc @@ -22,7 +22,6 @@ // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see // . -#include "gstdint.h" #include #include @@ -119,13 +118,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_CONST __atomic_flag_base* __atomic_flag_for_address(const volatile void* __z) _GLIBCXX_NOTHROW { - uintptr_t __u = reinterpret_cast(__z); + using guintptr_t = __UINTPTR_TYPE__; + guintptr_t __u = reinterpret_cast(__z); __u += (__u >> 2) + (__u << 4); __u += (__u >> 7) + (__u << 5); __u += (__u >> 17) + (__u << 13); - if (sizeof(uintptr_t) > 4) + if (sizeof(guintptr_t) > 4) __u += (__u >> 31); - __u &= ~((~uintptr_t(0)) << LOGSIZE); + __u &= ~((~guintptr_t(0)) << LOGSIZE); return flag_table + __u; } diff --git a/libstdc++-v3/src/c++17/Makefile.in b/libstdc++-v3/src/c++17/Makefile.in index 217cbbe..84bba4d 100644 --- a/libstdc++-v3/src/c++17/Makefile.in +++ b/libstdc++-v3/src/c++17/Makefile.in @@ -104,7 +104,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/src/c++20/Makefile.in b/libstdc++-v3/src/c++20/Makefile.in index c04bb7d..9db70a3 100644 --- a/libstdc++-v3/src/c++20/Makefile.in +++ b/libstdc++-v3/src/c++20/Makefile.in @@ -104,7 +104,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/src/c++98/Makefile.in b/libstdc++-v3/src/c++98/Makefile.in index 77ec8c7..bd63782a 100644 --- a/libstdc++-v3/src/c++98/Makefile.in +++ b/libstdc++-v3/src/c++98/Makefile.in @@ -104,7 +104,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/src/filesystem/Makefile.in b/libstdc++-v3/src/filesystem/Makefile.in index 010bcfc..852390e 100644 --- a/libstdc++-v3/src/filesystem/Makefile.in +++ b/libstdc++-v3/src/filesystem/Makefile.in @@ -104,7 +104,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/src/libbacktrace/Makefile.in b/libstdc++-v3/src/libbacktrace/Makefile.in index a52f645..4bc0556 100644 --- a/libstdc++-v3/src/libbacktrace/Makefile.in +++ b/libstdc++-v3/src/libbacktrace/Makefile.in @@ -135,7 +135,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ diff --git a/libstdc++-v3/testsuite/Makefile.in b/libstdc++-v3/testsuite/Makefile.in index 328a036..5081fdf 100644 --- a/libstdc++-v3/testsuite/Makefile.in +++ b/libstdc++-v3/testsuite/Makefile.in @@ -103,7 +103,6 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../config/override.m4 \ - $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../config/toolexeclibdir.m4 \ $(top_srcdir)/../config/unwind_ipinfo.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \ -- cgit v1.1 From b80f25a3360b6850662eaea2039b255fbfbeea31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Date: Thu, 20 Oct 2022 16:58:53 +0200 Subject: libstdc++: Make placeholders inline when inline variables are available This slightly lowers the dependency of generated code on libstdc++.so. libstdc++-v3/ChangeLog: * include/std/functional: Make placeholders inline, if possible. --- libstdc++-v3/include/std/functional | 66 +++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 29 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index d22acaa..b396e8d 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -285,35 +285,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * simplify this with variadic templates, because we're introducing * unique names for each. */ - extern const _Placeholder<1> _1; - extern const _Placeholder<2> _2; - extern const _Placeholder<3> _3; - extern const _Placeholder<4> _4; - extern const _Placeholder<5> _5; - extern const _Placeholder<6> _6; - extern const _Placeholder<7> _7; - extern const _Placeholder<8> _8; - extern const _Placeholder<9> _9; - extern const _Placeholder<10> _10; - extern const _Placeholder<11> _11; - extern const _Placeholder<12> _12; - extern const _Placeholder<13> _13; - extern const _Placeholder<14> _14; - extern const _Placeholder<15> _15; - extern const _Placeholder<16> _16; - extern const _Placeholder<17> _17; - extern const _Placeholder<18> _18; - extern const _Placeholder<19> _19; - extern const _Placeholder<20> _20; - extern const _Placeholder<21> _21; - extern const _Placeholder<22> _22; - extern const _Placeholder<23> _23; - extern const _Placeholder<24> _24; - extern const _Placeholder<25> _25; - extern const _Placeholder<26> _26; - extern const _Placeholder<27> _27; - extern const _Placeholder<28> _28; - extern const _Placeholder<29> _29; +#if __cpp_inline_variables +# define _GLIBCXX_PLACEHOLDER inline +#else +# define _GLIBCXX_PLACEHOLDER extern +#endif + + _GLIBCXX_PLACEHOLDER const _Placeholder<1> _1; + _GLIBCXX_PLACEHOLDER const _Placeholder<2> _2; + _GLIBCXX_PLACEHOLDER const _Placeholder<3> _3; + _GLIBCXX_PLACEHOLDER const _Placeholder<4> _4; + _GLIBCXX_PLACEHOLDER const _Placeholder<5> _5; + _GLIBCXX_PLACEHOLDER const _Placeholder<6> _6; + _GLIBCXX_PLACEHOLDER const _Placeholder<7> _7; + _GLIBCXX_PLACEHOLDER const _Placeholder<8> _8; + _GLIBCXX_PLACEHOLDER const _Placeholder<9> _9; + _GLIBCXX_PLACEHOLDER const _Placeholder<10> _10; + _GLIBCXX_PLACEHOLDER const _Placeholder<11> _11; + _GLIBCXX_PLACEHOLDER const _Placeholder<12> _12; + _GLIBCXX_PLACEHOLDER const _Placeholder<13> _13; + _GLIBCXX_PLACEHOLDER const _Placeholder<14> _14; + _GLIBCXX_PLACEHOLDER const _Placeholder<15> _15; + _GLIBCXX_PLACEHOLDER const _Placeholder<16> _16; + _GLIBCXX_PLACEHOLDER const _Placeholder<17> _17; + _GLIBCXX_PLACEHOLDER const _Placeholder<18> _18; + _GLIBCXX_PLACEHOLDER const _Placeholder<19> _19; + _GLIBCXX_PLACEHOLDER const _Placeholder<20> _20; + _GLIBCXX_PLACEHOLDER const _Placeholder<21> _21; + _GLIBCXX_PLACEHOLDER const _Placeholder<22> _22; + _GLIBCXX_PLACEHOLDER const _Placeholder<23> _23; + _GLIBCXX_PLACEHOLDER const _Placeholder<24> _24; + _GLIBCXX_PLACEHOLDER const _Placeholder<25> _25; + _GLIBCXX_PLACEHOLDER const _Placeholder<26> _26; + _GLIBCXX_PLACEHOLDER const _Placeholder<27> _27; + _GLIBCXX_PLACEHOLDER const _Placeholder<28> _28; + _GLIBCXX_PLACEHOLDER const _Placeholder<29> _29; + +#undef _GLIBCXX_PLACEHOLDER } /** -- cgit v1.1 From 49237fe6ef677a81eae701f937546210c90b5914 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 28 Oct 2022 15:28:09 +0100 Subject: libstdc++: Fix dangling reference in filesystem::path::filename() The new -Wdangling-reference warning noticed this. libstdc++-v3/ChangeLog: * include/bits/fs_path.h (path::filename()): Fix dangling reference. --- libstdc++-v3/include/bits/fs_path.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h index 6e7b366..2fc7dcd 100644 --- a/libstdc++-v3/include/bits/fs_path.h +++ b/libstdc++-v3/include/bits/fs_path.h @@ -1262,9 +1262,9 @@ namespace __detail { if (_M_pathname.back() == preferred_separator) return {}; - auto& __last = *--end(); - if (__last._M_type() == _Type::_Filename) - return __last; + auto __last = --end(); + if (__last->_M_type() == _Type::_Filename) + return *__last; } return {}; } -- cgit v1.1 From 3055829a4addde1fa3542c8070c87e2dd17217fc Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 29 Oct 2022 00:17:49 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b3b168d..79ede72 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,44 @@ +2022-10-28 Jonathan Wakely + + * include/bits/fs_path.h (path::filename()): Fix dangling + reference. + +2022-10-28 Arsen Arsenović + + * include/std/functional: Make placeholders inline, if possible. + +2022-10-28 Arsen Arsenović + + * configure.ac: Stop generating gstdint.h. + * src/c++11/compatibility-atomic-c++0x.cc: Stop using gstdint.h. + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate. + * config.h.in: Regenerate. + * configure: Regenerate. + * doc/Makefile.in: Regenerate. + * include/Makefile.in: Regenerate. + * libsupc++/Makefile.in: Regenerate. + * po/Makefile.in: Regenerate. + * python/Makefile.in: Regenerate. + * src/Makefile.in: Regenerate. + * src/c++11/Makefile.in: Regenerate. + * src/c++17/Makefile.in: Regenerate. + * src/c++20/Makefile.in: Regenerate. + * src/c++98/Makefile.in: Regenerate. + * src/filesystem/Makefile.in: Regenerate. + * src/libbacktrace/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2022-10-28 Jonathan Wakely + + PR libstdc++/107376 + * include/bits/regex_executor.h (_Executor::_Executor): Use same + allocator for _M_cur_results and _M_results. + * include/bits/regex_executor.tcc (_Executor::_M_main_dispatch): + Prevent possibly incorrect allocator propagating to + _M_cur_results. + * testsuite/28_regex/algorithms/regex_match/107376.cc: New test. + 2022-10-26 Marek Polacek PR c++/106393 -- cgit v1.1 From cbf56503d5e2bbafb06a507cb37d30805a1013a0 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 31 Oct 2022 16:47:23 +0100 Subject: libstdc++: Small extended float support tweaks The following patch 1) enables the std::float128_t overloads for x86 with glibc 2.26+ 2) makes std::nextafter(std::float16_t, std::float16_t) and std::nextafter(std::bfloat16_t, std::bfloat16_t) constexpr 3) adds (small) testsuite coverage for that 2022-10-21 Jakub Jelinek * config/os/gnu-linux/os_defines.h (_GLIBCXX_HAVE_FLOAT128_MATH): Uncomment. * include/c_global/cmath (nextafter(_Float16, _Float16)): Make it constexpr. If std::__is_constant_evaluated() call __builtin_nextafterf16. (nextafter(__gnu_cxx::__bfloat16_t, __gnu_cxx::__bfloat16_t)): Similarly but call __builtin_nextafterf16b. * testsuite/26_numerics/headers/cmath/nextafter_c++23.cc (test): Add static assertions to test constexpr nextafter. --- libstdc++-v3/config/os/gnu-linux/os_defines.h | 2 +- libstdc++-v3/include/c_global/cmath | 8 ++++++-- .../testsuite/26_numerics/headers/cmath/nextafter_c++23.cc | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/config/os/gnu-linux/os_defines.h b/libstdc++-v3/config/os/gnu-linux/os_defines.h index e5b640a..044b4fc 100644 --- a/libstdc++-v3/config/os/gnu-linux/os_defines.h +++ b/libstdc++-v3/config/os/gnu-linux/os_defines.h @@ -57,7 +57,7 @@ || (defined(__powerpc__) && defined(_ARCH_PWR8) \ && defined(__LITTLE_ENDIAN__) && (_CALL_ELF == 2) \ && defined(__FLOAT128__))) -//# define _GLIBCXX_HAVE_FLOAT128_MATH 1 +# define _GLIBCXX_HAVE_FLOAT128_MATH 1 #endif #if __GLIBC_PREREQ(2, 27) diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath index 555d644..e52055a 100644 --- a/libstdc++-v3/include/c_global/cmath +++ b/libstdc++-v3/include/c_global/cmath @@ -2755,9 +2755,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION nearbyint(_Float16 __x) { return _Float16(__builtin_nearbyintf(__x)); } - inline _Float16 + constexpr _Float16 nextafter(_Float16 __x, _Float16 __y) { + if (std::__is_constant_evaluated()) + return __builtin_nextafterf16(__x, __y); #ifdef __INT16_TYPE__ using __float16_int_type = __INT16_TYPE__; #else @@ -3471,9 +3473,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION nearbyint(__gnu_cxx::__bfloat16_t __x) { return __gnu_cxx::__bfloat16_t(__builtin_nearbyintf(__x)); } - inline __gnu_cxx::__bfloat16_t + constexpr __gnu_cxx::__bfloat16_t nextafter(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y) { + if (std::__is_constant_evaluated()) + return __builtin_nextafterf16b(__x, __y); #ifdef __INT16_TYPE__ using __bfloat16_int_type = __INT16_TYPE__; #else diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc index 45aa3b7..8d7daa9 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc @@ -100,6 +100,8 @@ test () VERIFY(std::fpclassify(t36) == FP_NAN); T t37 = std::nextafter(T(-0.0), T()); VERIFY(t37 == T() && !std::signbit(t37)); + static_assert(std::nextafter(T(1.0), T(2.0)) > T(1.0)); + static_assert(std::nextafter(std::nextafter(T(1.0), T(5.0)), T(0.0)) == T(1.0)); } int -- cgit v1.1 From db55f1dda2692c3f778ae783bc7121891c79aec4 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 31 Oct 2022 20:13:02 +0100 Subject: libstdc++-v3: support for extended floating point types The following patch adds support for extended floating point types. C++23 removes the float/double/long double specializations from the spec and instead adds explicit(bool) specifier on the converting constructor. The patch uses that for converting constructor of the base template as well as the float/double/long double specializations's converting constructors (e.g. so that it handles convertion construction also from complex of extended floating point types). Copy ctor was already defaulted as the spec now requires. The patch also adds partial specialization for the _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t types because the base template doesn't use __complex__ but a pair of floating point values. The g++.dg/cpp23/ testcase verifies explicit(bool) works correctly. 2022-10-31 Jakub Jelinek gcc/testsuite/ * g++.dg/cpp23/ext-floating12.C: New test. libstdc++-v3/ * include/std/complex (complex::complex converting ctor): For C++23 use explicit specifier with constant expression. Explicitly cast both parts to _Tp. (__complex_abs, __complex_arg, __complex_cos, __complex_cosh, __complex_exp, __complex_log, __complex_sin, __complex_sinh, __complex_sqrt, __complex_tan, __complex_tanh, __complex_pow): Add __complex__ _Float{16,32,64,128} and __complex__ decltype(0.0bf16) overloads. (complex::complex converting ctor, complex::complex converting ctor, complex::complex converting ctor): For C++23 implement as template with explicit specifier with constant expression and explicit casts. (__complex_type): New template. (complex): New partial specialization for types with extended floating point types. (__complex_acos, __complex_asin, __complex_atan, __complex_acosh, __complex_asinh, __complex_atanh): Add __complex__ _Float{16,32,64,128} and __complex__ decltype(0.0bf16) overloads. (__complex_proj): Likewise. Add template for complex of extended floating point types. * include/bits/cpp_type_traits.h (__is_floating): Specialize for _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t. * testsuite/26_numerics/complex/ext_c++23.cc: New test. --- libstdc++-v3/include/bits/cpp_type_traits.h | 45 ++ libstdc++-v3/include/std/complex | 641 ++++++++++++++++++++- .../testsuite/26_numerics/complex/ext_c++23.cc | 89 +++ 3 files changed, 773 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h index 8f91bbe..592673a 100644 --- a/libstdc++-v3/include/bits/cpp_type_traits.h +++ b/libstdc++-v3/include/bits/cpp_type_traits.h @@ -315,6 +315,51 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3) typedef __true_type __type; }; +#ifdef __STDCPP_FLOAT16_T__ + template<> + struct __is_floating<_Float16> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT32_T__ + template<> + struct __is_floating<_Float32> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT64_T__ + template<> + struct __is_floating<_Float64> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_FLOAT128_T__ + template<> + struct __is_floating<_Float128> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + template<> + struct __is_floating<__gnu_cxx::__bfloat16_t> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + // // Pointer types // diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index 8f9368f..da2df91 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -142,8 +142,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Converting constructor. template - _GLIBCXX_CONSTEXPR complex(const complex<_Up>& __z) - : _M_real(__z.real()), _M_imag(__z.imag()) { } +#if __cplusplus > 202002L + explicit(!requires(_Up __u) { _Tp{__u}; }) +#endif + _GLIBCXX_CONSTEXPR complex(const complex<_Up>& __z) + : _M_real(_Tp(__z.real())), _M_imag(_Tp(__z.imag())) { } #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1077,6 +1080,264 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : std::pow(complex<_Tp>(__x), __y); } +#if _GLIBCXX_USE_C99_COMPLEX +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline _Float16 + __complex_abs(__complex__ _Float16 __z) + { return _Float16(__builtin_cabsf(__z)); } + + inline _Float16 + __complex_arg(__complex__ _Float16 __z) + { return _Float16(__builtin_cargf(__z)); } + + inline __complex__ _Float16 + __complex_cos(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_ccosf(__z)); } + + inline __complex__ _Float16 + __complex_cosh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_ccoshf(__z)); } + + inline __complex__ _Float16 + __complex_exp(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_cexpf(__z)); } + + inline __complex__ _Float16 + __complex_log(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_clogf(__z)); } + + inline __complex__ _Float16 + __complex_sin(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_csinf(__z)); } + + inline __complex__ _Float16 + __complex_sinh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_csinhf(__z)); } + + inline __complex__ _Float16 + __complex_sqrt(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_csqrtf(__z)); } + + inline __complex__ _Float16 + __complex_tan(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_ctanf(__z)); } + + inline __complex__ _Float16 + __complex_tanh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_ctanhf(__z)); } + + inline __complex__ _Float16 + __complex_pow(__complex__ _Float16 __x, __complex__ _Float16 __y) + { return static_cast<__complex__ _Float16>(__builtin_cpowf(__x, __y)); } +#endif + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline _Float32 + __complex_abs(__complex__ _Float32 __z) { return __builtin_cabsf(__z); } + + inline _Float32 + __complex_arg(__complex__ _Float32 __z) { return __builtin_cargf(__z); } + + inline __complex__ _Float32 + __complex_cos(__complex__ _Float32 __z) { return __builtin_ccosf(__z); } + + inline __complex__ _Float32 + __complex_cosh(__complex__ _Float32 __z) { return __builtin_ccoshf(__z); } + + inline __complex__ _Float32 + __complex_exp(__complex__ _Float32 __z) { return __builtin_cexpf(__z); } + + inline __complex__ _Float32 + __complex_log(__complex__ _Float32 __z) { return __builtin_clogf(__z); } + + inline __complex__ _Float32 + __complex_sin(__complex__ _Float32 __z) { return __builtin_csinf(__z); } + + inline __complex__ _Float32 + __complex_sinh(__complex__ _Float32 __z) { return __builtin_csinhf(__z); } + + inline __complex__ _Float32 + __complex_sqrt(__complex__ _Float32 __z) { return __builtin_csqrtf(__z); } + + inline __complex__ _Float32 + __complex_tan(__complex__ _Float32 __z) { return __builtin_ctanf(__z); } + + inline __complex__ _Float32 + __complex_tanh(__complex__ _Float32 __z) { return __builtin_ctanhf(__z); } + + inline __complex__ _Float32 + __complex_pow(__complex__ _Float32 __x, __complex__ _Float32 __y) + { return __builtin_cpowf(__x, __y); } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + inline _Float64 + __complex_abs(__complex__ _Float64 __z) { return __builtin_cabs(__z); } + + inline _Float64 + __complex_arg(__complex__ _Float64 __z) { return __builtin_carg(__z); } + + inline __complex__ _Float64 + __complex_cos(__complex__ _Float64 __z) { return __builtin_ccos(__z); } + + inline __complex__ _Float64 + __complex_cosh(__complex__ _Float64 __z) { return __builtin_ccosh(__z); } + + inline __complex__ _Float64 + __complex_exp(__complex__ _Float64 __z) { return __builtin_cexp(__z); } + + inline __complex__ _Float64 + __complex_log(__complex__ _Float64 __z) { return __builtin_clog(__z); } + + inline __complex__ _Float64 + __complex_sin(__complex__ _Float64 __z) { return __builtin_csin(__z); } + + inline __complex__ _Float64 + __complex_sinh(__complex__ _Float64 __z) { return __builtin_csinh(__z); } + + inline __complex__ _Float64 + __complex_sqrt(__complex__ _Float64 __z) { return __builtin_csqrt(__z); } + + inline __complex__ _Float64 + __complex_tan(__complex__ _Float64 __z) { return __builtin_ctan(__z); } + + inline __complex__ _Float64 + __complex_tanh(__complex__ _Float64 __z) { return __builtin_ctanh(__z); } + + inline __complex__ _Float64 + __complex_pow(__complex__ _Float64 __x, __complex__ _Float64 __y) + { return __builtin_cpow(__x, __y); } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + inline _Float128 + __complex_abs(__complex__ _Float128 __z) { return __builtin_cabsl(__z); } + + inline _Float128 + __complex_arg(__complex__ _Float128 __z) { return __builtin_cargl(__z); } + + inline __complex__ _Float128 + __complex_cos(__complex__ _Float128 __z) { return __builtin_ccosl(__z); } + + inline __complex__ _Float128 + __complex_cosh(__complex__ _Float128 __z) { return __builtin_ccoshl(__z); } + + inline __complex__ _Float128 + __complex_exp(__complex__ _Float128 __z) { return __builtin_cexpl(__z); } + + inline __complex__ _Float128 + __complex_log(__complex__ _Float128 __z) { return __builtin_clogl(__z); } + + inline __complex__ _Float128 + __complex_sin(__complex__ _Float128 __z) { return __builtin_csinl(__z); } + + inline __complex__ _Float128 + __complex_sinh(__complex__ _Float128 __z) { return __builtin_csinhl(__z); } + + inline __complex__ _Float128 + __complex_sqrt(__complex__ _Float128 __z) { return __builtin_csqrtl(__z); } + + inline __complex__ _Float128 + __complex_tan(__complex__ _Float128 __z) { return __builtin_ctanl(__z); } + + inline __complex__ _Float128 + __complex_tanh(__complex__ _Float128 __z) { return __builtin_ctanhl(__z); } + + inline __complex__ _Float128 + __complex_pow(__complex__ _Float128 __x, __complex__ _Float128 __y) + { return __builtin_cpowl(__x, __y); } +#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) + inline _Float128 + __complex_abs(__complex__ _Float128 __z) { return __builtin_cabsf128(__z); } + + inline _Float128 + __complex_arg(__complex__ _Float128 __z) { return __builtin_cargf128(__z); } + + inline __complex__ _Float128 + __complex_cos(__complex__ _Float128 __z) { return __builtin_ccosf128(__z); } + + inline __complex__ _Float128 + __complex_cosh(__complex__ _Float128 __z) { return __builtin_ccoshf128(__z); } + + inline __complex__ _Float128 + __complex_exp(__complex__ _Float128 __z) { return __builtin_cexpf128(__z); } + + inline __complex__ _Float128 + __complex_log(__complex__ _Float128 __z) { return __builtin_clogf128(__z); } + + inline __complex__ _Float128 + __complex_sin(__complex__ _Float128 __z) { return __builtin_csinf128(__z); } + + inline __complex__ _Float128 + __complex_sinh(__complex__ _Float128 __z) { return __builtin_csinhf128(__z); } + + inline __complex__ _Float128 + __complex_sqrt(__complex__ _Float128 __z) { return __builtin_csqrtf128(__z); } + + inline __complex__ _Float128 + __complex_tan(__complex__ _Float128 __z) { return __builtin_ctanf128(__z); } + + inline __complex__ _Float128 + __complex_tanh(__complex__ _Float128 __z) { return __builtin_ctanhf128(__z); } + + inline __complex__ _Float128 + __complex_pow(__complex__ _Float128 __x, __complex__ _Float128 __y) + { return __builtin_cpowf128(__x, __y); } +#endif + +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __gnu_cxx::__bfloat16_t + __complex_abs(__complex__ decltype(0.0bf16) __z) + { return __gnu_cxx::__bfloat16_t(__builtin_cabsf(__z)); } + + inline __gnu_cxx::__bfloat16_t + __complex_arg(__complex__ decltype(0.0bf16) __z) + { return __gnu_cxx::__bfloat16_t(__builtin_cargf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_cos(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ccosf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_cosh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ccoshf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_exp(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cexpf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_log(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_clogf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_sin(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csinf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_sinh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csinhf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_sqrt(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_csqrtf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_tan(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ctanf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_tanh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_ctanhf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_pow(__complex__ decltype(0.0bf16) __x, + __complex__ decltype(0.0bf16) __y) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cpowf(__x, + __y)); } +#endif +#endif + /// 26.2.3 complex specializations /// complex specialization template<> @@ -1098,8 +1359,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif +#if __cplusplus > 202002L + template + explicit(!requires(_Up __u) { value_type{__u}; }) + constexpr complex(const complex<_Up>& __z) + : _M_value{ value_type(__z.real()), value_type(__z.imag()) } { } +#else explicit _GLIBCXX_CONSTEXPR complex(const complex&); explicit _GLIBCXX_CONSTEXPR complex(const complex&); +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1244,10 +1512,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif +#if __cplusplus > 202002L + template + explicit(!requires(_Up __u) { value_type{__u}; }) + constexpr complex(const complex<_Up>& __z) + : _M_value{ value_type(__z.real()), value_type(__z.imag()) } { } +#else _GLIBCXX_CONSTEXPR complex(const complex& __z) : _M_value(__z.__rep()) { } explicit _GLIBCXX_CONSTEXPR complex(const complex&); +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1391,11 +1666,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif +#if __cplusplus > 202002L + template + explicit(!requires(_Up __u) { value_type{__u}; }) + constexpr complex(const complex<_Up>& __z) + : _M_value{ value_type(__z.real()), value_type(__z.imag()) } { } +#else _GLIBCXX_CONSTEXPR complex(const complex& __z) : _M_value(__z.__rep()) { } _GLIBCXX_CONSTEXPR complex(const complex& __z) : _M_value(__z.__rep()) { } +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1517,6 +1799,161 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ComplexT _M_value; }; +#if __cplusplus > 202002L + template + struct __complex_type + { }; + +#ifdef __STDCPP_FLOAT16_T__ + template<> + struct __complex_type<_Float16> + { typedef __complex__ _Float16 type; }; +#endif + +#ifdef __STDCPP_FLOAT32_T__ + template<> + struct __complex_type<_Float32> + { typedef __complex__ _Float32 type; }; +#endif + +#ifdef __STDCPP_FLOAT64_T__ + template<> + struct __complex_type<_Float64> + { typedef __complex__ _Float64 type; }; +#endif + +#ifdef __STDCPP_FLOAT128_T__ + template<> + struct __complex_type<_Float128> + { typedef __complex__ _Float128 type; }; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + template<> + struct __complex_type<__gnu_cxx::__bfloat16_t> + { typedef __complex__ decltype(0.0bf16) type; }; +#endif + + template + requires(__complex_type<_Tp>::type) + class complex<_Tp> + { + public: + typedef _Tp value_type; + typedef std::__complex_type<_Tp>::type _ComplexT; + + constexpr complex(_ComplexT __z) : _M_value(__z) { } + + constexpr complex(_Tp __r = _Tp(), _Tp __i = _Tp()) + : _M_value{ __r, __i } { } + + template + explicit(!requires(_Up __u) { value_type{__u}; }) + constexpr complex(const complex<_Up>& __z) + : _M_value{ value_type(__z.real()), value_type(__z.imag()) } { } + + constexpr _Tp + real() const { return __real__ _M_value; } + + constexpr _Tp + imag() const { return __imag__ _M_value; } + + constexpr void + real(_Tp __val) { __real__ _M_value = __val; } + + constexpr void + imag(_Tp __val) { __imag__ _M_value = __val; } + + constexpr complex& + operator=(_Tp __f) + { + _M_value = __f; + return *this; + } + + constexpr complex& + operator+=(_Tp __f) + { + _M_value += __f; + return *this; + } + + constexpr complex& + operator-=(_Tp __f) + { + _M_value -= __f; + return *this; + } + + constexpr complex& + operator*=(_Tp __f) + { + _M_value *= __f; + return *this; + } + + constexpr complex& + operator/=(_Tp __f) + { + _M_value /= __f; + return *this; + } + + // Let the compiler synthesize the copy and assignment + // operator. It always does a pretty good job. + constexpr complex& operator=(const complex&) = default; + + template + constexpr complex& + operator=(const complex<_Up>& __z) + { + __real__ _M_value = __z.real(); + __imag__ _M_value = __z.imag(); + return *this; + } + + template + constexpr complex& + operator+=(const complex<_Up>& __z) + { + _M_value += __z.__rep(); + return *this; + } + + template + constexpr complex& + operator-=(const complex<_Up>& __z) + { + _M_value -= __z.__rep(); + return *this; + } + + template + constexpr complex& + operator*=(const complex<_Up>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value *= __t; + return *this; + } + + template + constexpr complex& + operator/=(const complex<_Up>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value /= __t; + return *this; + } + + constexpr _ComplexT __rep() const { return _M_value; } + + private: + _ComplexT _M_value; + }; +#endif + +#if __cplusplus <= 202002L // These bits have to be at the end of this file, so that the // specializations have all been defined. inline _GLIBCXX_CONSTEXPR @@ -1530,6 +1967,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline _GLIBCXX_CONSTEXPR complex::complex(const complex& __z) : _M_value(__z.__rep()) { } +#endif // Inhibit implicit instantiations for required instantiations, // which are defined via explicit instantiations elsewhere. @@ -1809,6 +2247,162 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __complex_atanh(__z); } #endif +#if _GLIBCXX_USE_C99_COMPLEX_TR1 +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ _Float16 + __complex_acos(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_cacosf(__z)); } + + inline __complex__ _Float16 + __complex_asin(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_casinf(__z)); } + + inline __complex__ _Float16 + __complex_atan(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_catanf(__z)); } + + inline __complex__ _Float16 + __complex_acosh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_cacoshf(__z)); } + + inline __complex__ _Float16 + __complex_asinh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_casinhf(__z)); } + + inline __complex__ _Float16 + __complex_atanh(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_catanhf(__z)); } +#endif + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ _Float32 + __complex_acos(__complex__ _Float32 __z) + { return __builtin_cacosf(__z); } + + inline __complex__ _Float32 + __complex_asin(__complex__ _Float32 __z) + { return __builtin_casinf(__z); } + + inline __complex__ _Float32 + __complex_atan(__complex__ _Float32 __z) + { return __builtin_catanf(__z); } + + inline __complex__ _Float32 + __complex_acosh(__complex__ _Float32 __z) + { return __builtin_cacoshf(__z); } + + inline __complex__ _Float32 + __complex_asinh(__complex__ _Float32 __z) + { return __builtin_casinhf(__z); } + + inline __complex__ _Float32 + __complex_atanh(__complex__ _Float32 __z) + { return __builtin_catanhf(__z); } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + inline __complex__ _Float64 + __complex_acos(__complex__ _Float64 __z) + { return __builtin_cacos(__z); } + + inline __complex__ _Float64 + __complex_asin(__complex__ _Float64 __z) + { return __builtin_casin(__z); } + + inline __complex__ _Float64 + __complex_atan(__complex__ _Float64 __z) + { return __builtin_catan(__z); } + + inline __complex__ _Float64 + __complex_acosh(__complex__ _Float64 __z) + { return __builtin_cacosh(__z); } + + inline __complex__ _Float64 + __complex_asinh(__complex__ _Float64 __z) + { return __builtin_casinh(__z); } + + inline __complex__ _Float64 + __complex_atanh(__complex__ _Float64 __z) + { return __builtin_catanh(__z); } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + inline __complex__ _Float128 + __complex_acos(__complex__ _Float128 __z) + { return __builtin_cacosl(__z); } + + inline __complex__ _Float128 + __complex_asin(__complex__ _Float128 __z) + { return __builtin_casinl(__z); } + + inline __complex__ _Float128 + __complex_atan(__complex__ _Float128 __z) + { return __builtin_catanl(__z); } + + inline __complex__ _Float128 + __complex_acosh(__complex__ _Float128 __z) + { return __builtin_cacoshl(__z); } + + inline __complex__ _Float128 + __complex_asinh(__complex__ _Float128 __z) + { return __builtin_casinhl(__z); } + + inline __complex__ _Float128 + __complex_atanh(__complex__ _Float128 __z) + { return __builtin_catanhl(__z); } +#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) + inline __complex__ _Float128 + __complex_acos(__complex__ _Float128 __z) + { return __builtin_cacosf128(__z); } + + inline __complex__ _Float128 + __complex_asin(__complex__ _Float128 __z) + { return __builtin_casinf128(__z); } + + inline __complex__ _Float128 + __complex_atan(__complex__ _Float128 __z) + { return __builtin_catanf128(__z); } + + inline __complex__ _Float128 + __complex_acosh(__complex__ _Float128 __z) + { return __builtin_cacoshf128(__z); } + + inline __complex__ _Float128 + __complex_asinh(__complex__ _Float128 __z) + { return __builtin_casinhf128(__z); } + + inline __complex__ _Float128 + __complex_atanh(__complex__ _Float128 __z) + { return __builtin_catanhf128(__z); } +#endif + +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ decltype(0.0bf16) + __complex_acos(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cacosf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_asin(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_casinf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_atan(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_catanf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_acosh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cacoshf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_asinh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_casinhf(__z)); } + + inline __complex__ decltype(0.0bf16) + __complex_atanh(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_catanhf(__z)); } +#endif +#endif + template inline _Tp /// fabs(__z) [8.1.8]. @@ -1897,6 +2491,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline complex __complex_proj(const complex& __z) { return __builtin_cprojl(__z.__rep()); } + +#if __cplusplus > 202002L +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ _Float16 + __complex_proj(__complex__ _Float16 __z) + { return static_cast<__complex__ _Float16>(__builtin_cprojf(__z)); } +#endif + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ _Float32 + __complex_proj(__complex__ _Float32 __z) + { return __builtin_cprojf(__z); } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + inline __complex__ _Float64 + __complex_proj(__complex__ _Float64 __z) + { return __builtin_cproj(__z); } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + inline __complex__ _Float128 + __complex_proj(__complex__ _Float128 __z) + { return __builtin_cprojl(__z); } +#elif defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_HAVE_FLOAT128_MATH) + inline __complex__ _Float128 + __complex_proj(__complex__ _Float128 __z) + { return __builtin_cprojf128(__z); } +#endif + +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline __complex__ decltype(0.0bf16) + __complex_proj(__complex__ decltype(0.0bf16) __z) + { return static_cast<__complex__ decltype(0.0bf16)>(__builtin_cprojf(__z)); } +#endif + + template + requires(__complex_type<_Tp>::type) + inline complex<_Tp> + __complex_proj(const complex<_Tp>& __z) + { return __complex_proj(__z.__rep()); } +#endif + #elif defined _GLIBCXX_USE_C99_MATH_TR1 inline complex __complex_proj(const complex& __z) diff --git a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc new file mode 100644 index 0000000..bdc9af0 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc @@ -0,0 +1,89 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2b" } +// { dg-do link { target c++23 } } + +#include +#include + +template +__attribute__((__noipa__)) void +test_functions(T *p, std::complex *q) +{ + p[0] = std::abs(q[0]); + p[1] = std::arg(q[1]); + q[2] = std::cos(q[2]); + q[3] = std::cosh(q[3]); + q[4] = std::exp(q[4]); + q[5] = std::log(q[5]); + q[6] = std::sin(q[6]); + q[7] = std::sinh(q[7]); + q[8] = std::sqrt(q[8]); + q[9] = std::tan(q[9]); + q[10] = std::tanh(q[10]); + q[11] = std::pow(q[11], q[19]); + q[12] = std::acos(q[12]); + q[13] = std::asin(q[13]); + q[14] = std::atan(q[14]); + q[15] = std::acosh(q[15]); + q[16] = std::asinh(q[16]); + q[17] = std::atanh(q[17]); + q[18] = std::proj(q[18]); +} + +int +main() +{ +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::float16_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::float32_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + { + std::float64_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_FLOAT128_T__) \ + && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ + || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) + { + std::float128_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + { + std::bfloat16_t p[2] = {}; + std::complex q[20] = {}; + test_functions(p, q); + } +#endif +} -- cgit v1.1 From 9a8b868d7a3e0c4e754a3c2f21c524fec4a6b0ab Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 1 Nov 2022 00:19:02 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 79ede72..a4d9275 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,41 @@ +2022-10-31 Jakub Jelinek + + * include/std/complex (complex::complex converting ctor): For C++23 + use explicit specifier with constant expression. Explicitly cast + both parts to _Tp. + (__complex_abs, __complex_arg, __complex_cos, __complex_cosh, + __complex_exp, __complex_log, __complex_sin, __complex_sinh, + __complex_sqrt, __complex_tan, __complex_tanh, __complex_pow): Add + __complex__ _Float{16,32,64,128} and __complex__ decltype(0.0bf16) + overloads. + (complex::complex converting ctor, + complex::complex converting ctor, + complex::complex converting ctor): For C++23 implement + as template with explicit specifier with constant expression + and explicit casts. + (__complex_type): New template. + (complex): New partial specialization for types with extended floating + point types. + (__complex_acos, __complex_asin, __complex_atan, __complex_acosh, + __complex_asinh, __complex_atanh): Add __complex__ _Float{16,32,64,128} + and __complex__ decltype(0.0bf16) overloads. + (__complex_proj): Likewise. Add template for complex of extended + floating point types. + * include/bits/cpp_type_traits.h (__is_floating): Specialize for + _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t. + * testsuite/26_numerics/complex/ext_c++23.cc: New test. + +2022-10-31 Jakub Jelinek + + * config/os/gnu-linux/os_defines.h (_GLIBCXX_HAVE_FLOAT128_MATH): + Uncomment. + * include/c_global/cmath (nextafter(_Float16, _Float16)): Make it constexpr. + If std::__is_constant_evaluated() call __builtin_nextafterf16. + (nextafter(__gnu_cxx::__bfloat16_t, __gnu_cxx::__bfloat16_t)): Similarly + but call __builtin_nextafterf16b. + * testsuite/26_numerics/headers/cmath/nextafter_c++23.cc (test): Add + static assertions to test constexpr nextafter. + 2022-10-28 Jonathan Wakely * include/bits/fs_path.h (path::filename()): Fix dangling -- cgit v1.1 From 29ef50b6bc609130a1550cdfc3997d1e501ffb28 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 1 Nov 2022 13:34:51 +0100 Subject: libstdc++-v3: Some std::*float*_t charconv and i/ostream overloads The following patch adds the easy part of , and changes for extended floats. In particular, for the first one only overloads where the _Float* has the same format as float/double/long double and for the latter two everything but the _GLIBCXX_HAVE_FLOAT128_MATH case. For charconv, I'm not really familiar with it, I'm pretty sure we need new libstdc++.so.6 side implementation of from_chars for {,b}float16_t and for to_chars not really sure but for unspecified precision if it should emit minimum characters that to_chars then can unambiguously parse, I think it is less than in the float case. For float128_t {to,from}_chars I think we even have it on the library side already, just ifdefed for powerpc64le only. For i/o stream operator<>, not sure what is better, if not providing anything at all, or doing what we in the end do if user doesn't override the virtual functions, or use {to,from}_chars under the hood, something else? Besides this, the patch adds some further missed // { dg-options "-std=gnu++2b" } spots, I've also noticed I got the formatting wrong in some testcases by not using spaces around VERIFY conditions and elsewhere by having space before ( for calls. The testsuite coverage is limited, I've added test for from_chars because it was easy to port, but not really sure what to do about to_chars, it has for float/double huge testcases which would be excessive to repeat. And for i/ostream not really sure what exactly is worth testing. 2022-11-01 Jakub Jelinek * include/std/charconv (from_chars, to_chars): Add _Float{32,64,128} overloads for cases where those types match {float,double,long double}. * include/std/istream (basic_istream::operator>>): Add _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. * include/std/ostream (basic_ostream::operator<<): Add _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. * testsuite/20_util/from_chars/8.cc: New test. * testsuite/26_numerics/headers/cmath/nextafter_c++23.cc (test): Formatting fixes. * testsuite/26_numerics/headers/cmath/functions_std_c++23.cc: Add dg-options "-std=gnu++2b". (test_functions, main): Formatting fixes. * testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc: Add dg-options "-std=gnu++2b". --- libstdc++-v3/include/std/charconv | 86 +++++ libstdc++-v3/include/std/istream | 88 +++++ libstdc++-v3/include/std/ostream | 45 +++ libstdc++-v3/testsuite/20_util/from_chars/8.cc | 367 +++++++++++++++++++++ .../cmath/c99_classification_macros_c++23.cc | 1 + .../headers/cmath/functions_std_c++23.cc | 173 +++++----- .../26_numerics/headers/cmath/nextafter_c++23.cc | 72 ++-- 7 files changed, 710 insertions(+), 122 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/from_chars/8.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index a65fbed..9b9cd83 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -672,6 +672,45 @@ namespace __detail from_chars_result from_chars(const char* __first, const char* __last, long double& __value, chars_format __fmt = chars_format::general) noexcept; + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline from_chars_result + from_chars(const char* __first, const char* __last, _Float32& __value, + chars_format __fmt = chars_format::general) noexcept + { + float __val; + from_chars_result __res = from_chars(__first, __last, __val, __fmt); + if (__res.ec == errc{}) + __value = __val; + return __res; + } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + inline from_chars_result + from_chars(const char* __first, const char* __last, _Float64& __value, + chars_format __fmt = chars_format::general) noexcept + { + double __val; + from_chars_result __res = from_chars(__first, __last, __val, __fmt); + if (__res.ec == errc{}) + __value = __val; + return __res; + } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + inline from_chars_result + from_chars(const char* __first, const char* __last, _Float128& __value, + chars_format __fmt = chars_format::general) noexcept + { + long double __val; + from_chars_result __res = from_chars(__first, __last, __val, __fmt); + if (__res.ec == errc{}) + __value = __val; + return __res; + } +#endif #endif #if defined __cpp_lib_to_chars @@ -698,6 +737,53 @@ namespace __detail chars_format __fmt) noexcept; to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision) noexcept; + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline to_chars_result + to_chars(char* __first, char* __last, _Float32 __value) noexcept + { return to_chars(__first, __last, float(__value)); } + inline to_chars_result + to_chars(char* __first, char* __last, _Float32 __value, + chars_format __fmt) noexcept + { return to_chars(__first, __last, float(__value), __fmt); } + inline to_chars_result + to_chars(char* __first, char* __last, _Float32 __value, + chars_format __fmt, int __precision) noexcept + { return to_chars(__first, __last, float(__value), __fmt, __precision); } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + inline to_chars_result + to_chars(char* __first, char* __last, _Float64 __value) noexcept + { return to_chars(__first, __last, double(__value)); } + inline to_chars_result + to_chars(char* __first, char* __last, _Float64 __value, + chars_format __fmt) noexcept + { return to_chars(__first, __last, double(__value), __fmt); } + inline to_chars_result + to_chars(char* __first, char* __last, _Float64 __value, + chars_format __fmt, int __precision) noexcept + { return to_chars(__first, __last, double(__value), __fmt, __precision); } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + inline to_chars_result + to_chars(char* __first, char* __last, _Float128 __value) noexcept + { return to_chars(__first, __last, static_cast(__value)); } + inline to_chars_result + to_chars(char* __first, char* __last, _Float128 __value, + chars_format __fmt) noexcept + { + return to_chars(__first, __last, static_cast(__value), __fmt); + } + inline to_chars_result + to_chars(char* __first, char* __last, _Float128 __value, + chars_format __fmt, int __precision) noexcept + { + return to_chars(__first, __last, static_cast(__value), __fmt, + __precision); + } +#endif #endif _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream index 58716ce..8476d62 100644 --- a/libstdc++-v3/include/std/istream +++ b/libstdc++-v3/include/std/istream @@ -225,6 +225,94 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_extract(__f); } ///@} +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + __attribute__((__always_inline__)) + __istream_type& + operator>>(_Float16& __f) + { + float __flt; + __istream_type& __ret = _M_extract(__flt); + ios_base::iostate __err = ios_base::goodbit; + if (__flt < -__FLT16_MAX__) + { + __f = -__FLT16_MAX__; + __err = ios_base::failbit; + } + else if (__flt > __FLT16_MAX__) + { + __f = __FLT16_MAX__; + __err = ios_base::failbit; + } + else + __f = static_cast<_Float16>(__flt); + if (__err) + this->setstate(__err); + return __ret; + } +#endif + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + __attribute__((__always_inline__)) + __istream_type& + operator>>(_Float32& __f) + { + float __flt; + __istream_type& __ret = _M_extract(__flt); + __f = static_cast<_Float32> (__flt); + return __ret; + } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + __attribute__((__always_inline__)) + __istream_type& + operator>>(_Float64& __f) + { + double __dbl; + __istream_type& __ret = _M_extract(__dbl); + __f = static_cast<_Float64> (__dbl); + return __ret; + } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + __attribute__((__always_inline__)) + __istream_type& + operator>>(_Float128& __f) + { + long double __ldbl; + __istream_type& __ret = _M_extract(__ldbl); + __f = static_cast<_Float128> (__ldbl); + return __ret; + } +#endif + +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + __attribute__((__always_inline__)) + __istream_type& + operator>>(__gnu_cxx::__bfloat16_t & __f) + { + float __flt; + __istream_type& __ret = _M_extract(__flt); + ios_base::iostate __err = ios_base::goodbit; + if (__flt < -__BFLT16_MAX__) + { + __f = -__BFLT16_MAX__; + __err = ios_base::failbit; + } + else if (__flt > __BFLT16_MAX__) + { + __f = __BFLT16_MAX__; + __err = ios_base::failbit; + } + else + __f = static_cast<__gnu_cxx::__bfloat16_t>(__flt); + if (__err) + this->setstate(__err); + return __ret; + } +#endif + /** * @brief Basic arithmetic extractors * @param __p A variable of pointer type. diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index 674decf..ffffec77 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -235,6 +235,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_insert(__f); } ///@} +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + __attribute__((__always_inline__)) + __ostream_type& + operator<<(_Float16 __f) + { + return _M_insert(static_cast(__f)); + } +#endif + +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + __attribute__((__always_inline__)) + __ostream_type& + operator<<(_Float32 __f) + { + return _M_insert(static_cast(__f)); + } +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + __attribute__((__always_inline__)) + __ostream_type& + operator<<(_Float64 __f) + { + return _M_insert(static_cast(__f)); + } +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + __attribute__((__always_inline__)) + __ostream_type& + operator<<(_Float128 __f) + { + return _M_insert(static_cast(__f)); + } +#endif + +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + __attribute__((__always_inline__)) + __ostream_type& + operator<<(__gnu_cxx::__bfloat16_t __f) + { + return _M_insert(static_cast(__f)); + } +#endif + /** * @brief Pointer arithmetic inserters * @param __p A variable of pointer type. diff --git a/libstdc++-v3/testsuite/20_util/from_chars/8.cc b/libstdc++-v3/testsuite/20_util/from_chars/8.cc new file mode 100644 index 0000000..ba34c2c --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/from_chars/8.cc @@ -0,0 +1,367 @@ +// Copyright (C) 2020-2022 Free Software Foundation, Inc. +// +// 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2b" } +// { dg-do run { target c++23 } } +// { dg-add-options ieee } + +#include +#include +#include +#include +#include +#include +#include + +// Test std::from_chars floating-point conversions. + +#if __cpp_lib_to_chars >= 201611L +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) +void +test01() +{ + std::string s; + std::float64_t f64; + std::from_chars_result res; + + for (auto fmt : { std::chars_format::fixed, std::chars_format::scientific, + std::chars_format::general, std::chars_format::hex }) + { + s = "Info"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isinf(f64) ); + VERIFY( res.ptr == s.data() + 3 ); + VERIFY( res.ec == std::errc{} ); + + s = "-INFIN"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isinf(f64) ); + VERIFY( f64 < 0 ); + VERIFY( res.ptr == s.data() + 4 ); + VERIFY( res.ec == std::errc{} ); + + s = "InFiNiTy aNd BeYoNd"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isinf(f64) ); + VERIFY( res.ptr == s.data() + 8 ); + VERIFY( res.ec == std::errc{} ); + + s = "nAn"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isnan(f64) ); + VERIFY( res.ptr == s.data() + 3 ); + VERIFY( res.ec == std::errc{} ); + + s = "-NAN()"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, fmt); + VERIFY( std::isnan(f64) ); + VERIFY( res.ptr == s.data() + s.length() ); + VERIFY( res.ec == std::errc{} ); + } +} + +void +test02() +{ + std::string s; + std::float64_t f64 = 1.0f64; + std::from_chars_result res; + + s = "0x123"; + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( f64 == 0.0f64 ); + VERIFY( res.ptr == s.data() + 1 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::fixed); + VERIFY( f64 == 0.0f64 ); + VERIFY( res.ptr == s.data() + 1 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::scientific); + VERIFY( f64 == 1.0f64 ); + VERIFY( res.ptr == s.data() ); + VERIFY( res.ec == std::errc::invalid_argument ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::general); + VERIFY( f64 == 0.0f64 ); + VERIFY( res.ptr == s.data() + 1 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::hex); + VERIFY( f64 == 0.0f64 ); + VERIFY( res.ptr == s.data() + 1 ); + VERIFY( res.ec == std::errc{} ); +} + +void +test03() +{ + std::string s; + std::float64_t f64 = 1.0f64; + std::from_chars_result res; + + s = "0.5e+2azzz"; + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( f64 == 0.5e+2f64 ); + VERIFY( res.ptr == s.data() + s.length() - 1 - 3 ); + VERIFY( res.ec == std::errc{} ); + + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::fixed); + VERIFY( f64 == 0.5f64 ); + VERIFY( res.ptr == s.data() + 3 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::scientific); + VERIFY( f64 == 0.5e+2f64 ); + VERIFY( res.ptr == s.data() + s.length() - 1 - 3 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0f64; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::general); + VERIFY( f64 == 0.5e+2f64 ); + VERIFY( res.ptr == s.data() + s.length() - 1 - 3 ); + VERIFY( res.ec == std::errc{} ); + + f64 = 1.0; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::hex); + VERIFY( f64 == 0x0.5Ep0f64 ); + VERIFY( res.ptr == s.data() + 4 ); + VERIFY( res.ec == std::errc{} ); + + s = "1.Ap-2zzz"; + res = std::from_chars(s.data(), s.data() + s.length(), f64, + std::chars_format::hex); + VERIFY( f64 == 0.40625f64 ); + VERIFY( res.ptr == s.data() + s.length() - 3 ); + VERIFY( res.ec == std::errc{} ); +} + +void +test04() +{ + // Huge input strings + std::string s(1000, '0'); + std::float64_t f64 = 1.0f64; + std::from_chars_result res; + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( res.ptr == s.data() + s.length() ); + VERIFY( res.ec == std::errc{} ); + VERIFY( f64 == 0.0f64 ); + + s += ".5"; + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( res.ptr == s.data() + s.length() ); + VERIFY( res.ec == std::errc{} ); + VERIFY( f64 == 0.5f64 ); + + s += "e2"; + auto len = s.length(); + s += std::string(1000, 'a'); + res = std::from_chars(s.data(), s.data() + s.length(), f64); + VERIFY( res.ptr == s.data() + len ); + VERIFY( res.ec == std::errc{} ); + VERIFY( f64 == 50.f64 ); +} +#endif + +using std::to_string; + +#ifdef __GLIBCXX_TYPE_INT_N_0 +std::string +to_string(unsigned __GLIBCXX_TYPE_INT_N_0 val) +{ + using Limits = std::numeric_limits; + std::string s(Limits::digits10+2, '0'); + for (auto iter = s.end(); val != 0; val /= 10) + *--iter = '0' + (val % 10); + return s; +} +#endif + +template +void +test_small_num() +{ + std::from_chars_result res; + FloatT flt; + + // Small integer values that are exactly representable + + for (int i = 0; i < 100; ++i) + { + std::string s = to_string(i); + int len = s.length(); + s += "123"; + const char* s1 = s.c_str(); + const char* s1_end = s1 + len; + + for (auto fmt : { std::chars_format::fixed, + std::chars_format::general, + std::chars_format::hex }) + { + if (fmt == std::chars_format::hex && i > 9) + continue; + + res = std::from_chars(s1, s1_end, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s1_end ); + VERIFY( flt == i ); + } + + if (i > 9) + continue; + + // Test single-digit integers with small exponents. + + const char s2[] = { '.', *s1, 'e', '0', '0', '0', '1' }; + const char* s2_end = s2 + sizeof(s2); + + const char s3[] = { *s1, '0', 'e', '-', '0', '0', '1' }; + const char* s3_end = s3 + sizeof(s3); + + for (auto fmt : { std::chars_format::scientific, + std::chars_format::general }) + { + res = std::from_chars(s2, s2_end, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s2_end ); + VERIFY( flt == i ); + + res = std::from_chars(s3, s3_end, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s3_end ); + VERIFY( flt == i ); + } + } +} + +void +test05() +{ +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test_small_num(); +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + test_small_num(); +#endif +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + test_small_num(); +#endif +} + +template +void +test_max_mantissa() +{ + using Float_limits = std::numeric_limits; + using UInt_limits = std::numeric_limits; + + if (Float_limits::is_iec559 && Float_limits::digits < UInt_limits::digits) + { +#ifdef _GLIBCXX_USE_C99_MATH_TR1 + std::printf("Testing %d-bit float, using %zu-bit integer\n", + Float_limits::digits + (int)std::log2(Float_limits::max_exponent) + 1, + sizeof(UIntT) * __CHAR_BIT__); +#endif + + std::from_chars_result res; + FloatT flt; + + for (int i = 0; i < 10; ++i) + { + // (1 << digits) - 1 is the maximum value of the mantissa + const auto val = ((UIntT)1 << Float_limits::digits) - 1 - i; + std::string s = to_string(val); + auto len = s.length(); + s += "000"; // these should be ignored + for (auto fmt : { std::chars_format::fixed, + std::chars_format::general }) + { + res = std::from_chars(s.data(), s.data() + len, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s.data() + len ); + VERIFY( flt == val ); + } + s.resize(len); + const auto orig_len = len; + s += "e+000"; + len = s.length(); + s += "111"; + for (auto fmt : { std::chars_format::scientific, + std::chars_format::general }) + { + res = std::from_chars(s.data(), s.data() + len, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s.data() + len ); + VERIFY( flt == val ); + + std::string s2 = s.substr(0, len - 5); + s2.insert(s2.begin() + orig_len - 1, '.'); + s2 += "e000000000001"; + res = std::from_chars(s.data(), s.data() + len, flt, fmt); + VERIFY( res.ec == std::errc{} ); + VERIFY( res.ptr == s.data() + len ); + VERIFY( flt == val ); + } + } + } +} + +void +test06() +{ +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test_max_mantissa(); +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + test_max_mantissa(); +#endif +#if defined(__GLIBCXX_TYPE_INT_N_0) \ + && defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + test_max_mantissa(); +#endif +} +#endif + +int +main() +{ +#if __cpp_lib_to_chars >= 201611L +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + test01(); + test02(); + test03(); + test04(); +#endif + test05(); + test06(); +#endif +} diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc index 0fda6a7..193e77b 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc @@ -15,6 +15,7 @@ // with this library; see the file COPYING3. If not see // . +// { dg-options "-std=gnu++2b" } // { dg-do link { target c++23 } } // { dg-excess-errors "" { target uclibc } } diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc index 190f8d1..99436b8 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc @@ -15,6 +15,7 @@ // with this library; see the file COPYING3. If not see // . +// { dg-options "-std=gnu++2b" } // { dg-do link { target c++23 } } #include @@ -22,91 +23,91 @@ template __attribute__((__noipa__)) void -test_functions (T *p, int *q, long int *r, long long int *s) +test_functions(T *p, int *q, long int *r, long long int *s) { - p[0] = std::acos (p[0]); - p[1] = std::asin (p[1]); - p[2] = std::atan (p[2]); - p[3] = std::cos (p[3]); - p[4] = std::sin (p[4]); - p[5] = std::tan (p[5]); - p[6] = std::acosh (p[6]); - p[7] = std::asinh (p[7]); - p[8] = std::atanh (p[8]); - p[9] = std::cosh (p[9]); - p[10] = std::sinh (p[10]); - p[11] = std::tanh (p[11]); - p[12] = std::exp (p[12]); - p[13] = std::exp2 (p[13]); - p[14] = std::expm1 (p[14]); - p[15] = std::log (p[15]); - p[16] = std::log10 (p[16]); - p[17] = std::log1p (p[17]); - p[18] = std::log2 (p[18]); - p[19] = std::logb (p[19]); - p[20] = std::cbrt (p[20]); - p[21] = std::fabs (p[21]); - p[22] = std::sqrt (p[22]); - p[23] = std::erf (p[23]); - p[24] = std::erfc (p[24]); - p[25] = std::lgamma (p[25]); - p[26] = std::tgamma (p[26]); - p[27] = std::ceil (p[27]); - p[28] = std::floor (p[28]); - p[29] = std::nearbyint (p[29]); - p[30] = std::rint (p[30]); - p[31] = std::round (p[31]); - p[32] = std::trunc (p[32]); - p[33] = std::atan2 (p[33], p[100]); - p[34] = std::hypot (p[34], p[101]); - p[35] = std::pow (p[35], p[102]); - p[36] = std::fmod (p[36], p[103]); - p[37] = std::remainder (p[37], p[104]); - p[38] = std::copysign (p[38], p[105]); - p[39] = std::nextafter (p[39], p[106]); - p[40] = std::fdim (p[40], p[107]); - p[41] = std::fmax (p[41], p[108]); - p[42] = std::fmin (p[42], p[109]); - p[43] = std::atan2 (p[43], p[110]); - p[44] = std::frexp (p[44], q + 0); - q[1] = std::ilogb (p[45]); - p[46] = std::ldexp (p[46], q[2]); - p[47] = std::modf (p[47], p + 111); - p[48] = std::scalbn (p[48], q[3]); - p[49] = std::scalbln (p[49], r[0]); - p[50] = std::hypot (p[50], p[111], p[112]); - r[1] = std::lrint (p[51]); - s[0] = std::llrint (p[52]); - r[2] = std::lround (p[53]); - s[1] = std::llround (p[54]); - p[55] = std::remquo (p[55], p[113], q + 4); - p[56] = std::fma (p[56], p[114], p[115]); - p[57] = std::lerp (p[57], p[116], p[117]); - p[58] = std::assoc_laguerre (q[5], q[6], p[58]); - p[59] = std::assoc_legendre (q[7], q[8], p[59]); - p[60] = std::beta (p[60], p[118]); - p[61] = std::comp_ellint_1 (p[61]); - p[62] = std::comp_ellint_2 (p[62]); - p[63] = std::comp_ellint_3 (p[63], p[119]); - p[64] = std::cyl_bessel_i (p[64], p[120]); - p[65] = std::cyl_bessel_j (p[65], p[121]); - p[66] = std::cyl_bessel_k (p[66], p[122]); - p[67] = std::cyl_neumann (p[67], p[123]); - p[68] = std::ellint_1 (p[68], p[124]); - p[69] = std::ellint_2 (p[69], p[125]); - p[70] = std::ellint_3 (p[70], p[126], p[127]); - p[71] = std::expint (p[71]); - p[72] = std::hermite (q[9], p[72]); - p[73] = std::laguerre (q[10], p[73]); - p[74] = std::legendre (q[11], p[72]); - p[75] = std::riemann_zeta (p[75]); - p[76] = std::sph_bessel (q[12], p[76]); - p[77] = std::sph_legendre (q[13], q[14], p[77]); - p[78] = std::sph_neumann (q[15], p[78]); + p[0] = std::acos(p[0]); + p[1] = std::asin(p[1]); + p[2] = std::atan(p[2]); + p[3] = std::cos(p[3]); + p[4] = std::sin(p[4]); + p[5] = std::tan(p[5]); + p[6] = std::acosh(p[6]); + p[7] = std::asinh(p[7]); + p[8] = std::atanh(p[8]); + p[9] = std::cosh(p[9]); + p[10] = std::sinh(p[10]); + p[11] = std::tanh(p[11]); + p[12] = std::exp(p[12]); + p[13] = std::exp2(p[13]); + p[14] = std::expm1(p[14]); + p[15] = std::log(p[15]); + p[16] = std::log10(p[16]); + p[17] = std::log1p(p[17]); + p[18] = std::log2(p[18]); + p[19] = std::logb(p[19]); + p[20] = std::cbrt(p[20]); + p[21] = std::fabs(p[21]); + p[22] = std::sqrt(p[22]); + p[23] = std::erf(p[23]); + p[24] = std::erfc(p[24]); + p[25] = std::lgamma(p[25]); + p[26] = std::tgamma(p[26]); + p[27] = std::ceil(p[27]); + p[28] = std::floor(p[28]); + p[29] = std::nearbyint(p[29]); + p[30] = std::rint(p[30]); + p[31] = std::round(p[31]); + p[32] = std::trunc(p[32]); + p[33] = std::atan2(p[33], p[100]); + p[34] = std::hypot(p[34], p[101]); + p[35] = std::pow(p[35], p[102]); + p[36] = std::fmod(p[36], p[103]); + p[37] = std::remainder(p[37], p[104]); + p[38] = std::copysign(p[38], p[105]); + p[39] = std::nextafter(p[39], p[106]); + p[40] = std::fdim(p[40], p[107]); + p[41] = std::fmax(p[41], p[108]); + p[42] = std::fmin(p[42], p[109]); + p[43] = std::atan2(p[43], p[110]); + p[44] = std::frexp(p[44], q + 0); + q[1] = std::ilogb(p[45]); + p[46] = std::ldexp(p[46], q[2]); + p[47] = std::modf(p[47], p + 111); + p[48] = std::scalbn(p[48], q[3]); + p[49] = std::scalbln(p[49], r[0]); + p[50] = std::hypot(p[50], p[111], p[112]); + r[1] = std::lrint(p[51]); + s[0] = std::llrint(p[52]); + r[2] = std::lround(p[53]); + s[1] = std::llround(p[54]); + p[55] = std::remquo(p[55], p[113], q + 4); + p[56] = std::fma(p[56], p[114], p[115]); + p[57] = std::lerp(p[57], p[116], p[117]); + p[58] = std::assoc_laguerre(q[5], q[6], p[58]); + p[59] = std::assoc_legendre(q[7], q[8], p[59]); + p[60] = std::beta(p[60], p[118]); + p[61] = std::comp_ellint_1(p[61]); + p[62] = std::comp_ellint_2(p[62]); + p[63] = std::comp_ellint_3(p[63], p[119]); + p[64] = std::cyl_bessel_i(p[64], p[120]); + p[65] = std::cyl_bessel_j(p[65], p[121]); + p[66] = std::cyl_bessel_k(p[66], p[122]); + p[67] = std::cyl_neumann(p[67], p[123]); + p[68] = std::ellint_1(p[68], p[124]); + p[69] = std::ellint_2(p[69], p[125]); + p[70] = std::ellint_3(p[70], p[126], p[127]); + p[71] = std::expint(p[71]); + p[72] = std::hermite(q[9], p[72]); + p[73] = std::laguerre(q[10], p[73]); + p[74] = std::legendre(q[11], p[72]); + p[75] = std::riemann_zeta(p[75]); + p[76] = std::sph_bessel(q[12], p[76]); + p[77] = std::sph_legendre(q[13], q[14], p[77]); + p[78] = std::sph_neumann(q[15], p[78]); } int -main () +main() { int q[16] = {}; long int r[16] = {}; @@ -114,19 +115,19 @@ main () #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) { std::float16_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) { std::float32_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif #if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) { std::float64_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif #if defined(__STDCPP_FLOAT128_T__) \ @@ -134,13 +135,13 @@ main () || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) { std::float128_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) { std::bfloat16_t p[128] = {}; - test_functions (p, q, r, s); + test_functions(p, q, r, s); } #endif } diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc index 8d7daa9..c105901 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc @@ -29,77 +29,77 @@ test () { using lim = std::numeric_limits; T t0 = std::nextafter(T(-0.0), T(2.0)); - VERIFY(t0 == lim::denorm_min()); + VERIFY( t0 == lim::denorm_min() ); T t1 = std::nextafter(T(), T(1.0)); - VERIFY(t1 == lim::denorm_min()); + VERIFY( t1 == lim::denorm_min() ); T t2 = std::nextafter(T(), T()); - VERIFY(t2 == T() && !std::signbit(t2)); + VERIFY( t2 == T() && !std::signbit(t2) ); T t3 = std::nextafter(lim::denorm_min(), T(-2.0)); - VERIFY(t3 == T() && !std::signbit(t3)); + VERIFY( t3 == T() && !std::signbit(t3) ); T t4 = std::nextafter(lim::min(), T(-0.0)); - VERIFY(std::fpclassify(t4) == FP_SUBNORMAL && t4 > T()); + VERIFY( std::fpclassify(t4) == FP_SUBNORMAL && t4 > T() ); T t5 = std::nextafter(t4, T(1.0)); - VERIFY(t5 == lim::min()); + VERIFY( t5 == lim::min() ); T t6 = std::nextafter(lim::min(), lim::infinity()); - VERIFY(std::fpclassify(t6) == FP_NORMAL && t6 > lim::min()); + VERIFY( std::fpclassify(t6) == FP_NORMAL && t6 > lim::min() ); T t7 = std::nextafter(t6, -lim::infinity()); - VERIFY(t7 == lim::min()); + VERIFY( t7 == lim::min() ); T t8 = std::nextafter(T(16.0), T(16.5)); - VERIFY(t8 > t7); + VERIFY( t8 > t7 ); T t9 = std::nextafter(t8, T(15.5)); - VERIFY(t9 == T(16.0)); + VERIFY( t9 == T(16.0) ); T t10 = std::nextafter(lim::max(), T(-0.5)); - VERIFY(std::fpclassify(t10) == FP_NORMAL && t10 < lim::max()); + VERIFY( std::fpclassify(t10) == FP_NORMAL && t10 < lim::max() ); T t11 = std::nextafter(t10, lim::infinity()); - VERIFY(t11 == lim::max()); + VERIFY( t11 == lim::max() ); T t12 = std::nextafter(t11, lim::infinity()); - VERIFY(std::fpclassify(t12) == FP_INFINITE && !std::signbit(t12)); + VERIFY( std::fpclassify(t12) == FP_INFINITE && !std::signbit(t12) ); T t13 = std::nextafter(lim::infinity(), t12); - VERIFY(t13 == t12); + VERIFY( t13 == t12 ); T t14 = std::nextafter(t13, T(1.0)); - VERIFY(t14 == lim::max()); + VERIFY( t14 == lim::max() ); T t15 = std::nextafter(lim::quiet_NaN(), T()); - VERIFY(std::fpclassify(t15) == FP_NAN); + VERIFY( std::fpclassify(t15) == FP_NAN ); T t16 = std::nextafter(T(17.0), lim::quiet_NaN()); - VERIFY(std::fpclassify(t16) == FP_NAN); + VERIFY( std::fpclassify(t16) == FP_NAN ); T t17 = std::nextafter(T(), T(-0.0)); - VERIFY(t17 == T() && std::signbit(t17)); + VERIFY( t17 == T() && std::signbit(t17) ); T t20 = std::nextafter(T(-0.0), T(-2.0)); - VERIFY(t20 == -lim::denorm_min()); + VERIFY( t20 == -lim::denorm_min() ); T t21 = std::nextafter(T(), T(-1.0)); - VERIFY(t21 == -lim::denorm_min()); + VERIFY( t21 == -lim::denorm_min() ); T t22 = std::nextafter(T(-0.0), T(-0.0)); - VERIFY(t22 == T() && std::signbit(t22)); + VERIFY( t22 == T() && std::signbit(t22) ); T t23 = std::nextafter(-lim::denorm_min(), T(2.0)); - VERIFY(t23 == T() && std::signbit(t23)); + VERIFY( t23 == T() && std::signbit(t23) ); T t24 = std::nextafter(-lim::min(), T()); - VERIFY(std::fpclassify(t24) == FP_SUBNORMAL && t24 < T()); + VERIFY( std::fpclassify(t24) == FP_SUBNORMAL && t24 < T() ); T t25 = std::nextafter(t24, T(-1.0)); - VERIFY(t25 == -lim::min()); + VERIFY( t25 == -lim::min() ); T t26 = std::nextafter(-lim::min(), -lim::infinity()); - VERIFY(std::fpclassify(t26) == FP_NORMAL && t26 < -lim::min()); + VERIFY( std::fpclassify(t26) == FP_NORMAL && t26 < -lim::min() ); T t27 = std::nextafter(t26, lim::infinity()); - VERIFY(t27 == -lim::min()); + VERIFY( t27 == -lim::min() ); T t28 = std::nextafter(T(-16.0), T(-16.5)); - VERIFY(t28 < t27); + VERIFY( t28 < t27 ); T t29 = std::nextafter(t28, T(-15.5)); - VERIFY(t29 == T(-16.0)); + VERIFY( t29 == T(-16.0) ); T t30 = std::nextafter(-lim::max(), T(0.5)); - VERIFY(std::fpclassify(t30) == FP_NORMAL && t30 > -lim::max()); + VERIFY( std::fpclassify(t30) == FP_NORMAL && t30 > -lim::max() ); T t31 = std::nextafter(t30, -lim::infinity()); - VERIFY(t31 == -lim::max()); + VERIFY( t31 == -lim::max() ); T t32 = std::nextafter(t31, -lim::infinity()); - VERIFY(std::fpclassify(t32) == FP_INFINITE && std::signbit(t32)); + VERIFY( std::fpclassify(t32) == FP_INFINITE && std::signbit(t32) ); T t33 = std::nextafter(-lim::infinity(), t32); - VERIFY(t33 == t32); + VERIFY( t33 == t32 ); T t34 = std::nextafter(t33, T(-1.0)); - VERIFY(t34 == -lim::max()); + VERIFY( t34 == -lim::max() ); T t35 = std::nextafter(-lim::quiet_NaN(), T()); - VERIFY(std::fpclassify(t35) == FP_NAN); + VERIFY( std::fpclassify(t35) == FP_NAN ); T t36 = std::nextafter(T(-17.0), lim::quiet_NaN()); - VERIFY(std::fpclassify(t36) == FP_NAN); + VERIFY( std::fpclassify(t36) == FP_NAN ); T t37 = std::nextafter(T(-0.0), T()); - VERIFY(t37 == T() && !std::signbit(t37)); + VERIFY( t37 == T() && !std::signbit(t37) ); static_assert(std::nextafter(T(1.0), T(2.0)) > T(1.0)); static_assert(std::nextafter(std::nextafter(T(1.0), T(5.0)), T(0.0)) == T(1.0)); } -- cgit v1.1 From 0ae26533b3e26866f4130d40ec0659c273552643 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 1 Nov 2022 13:40:05 +0100 Subject: libstdc++: std::to_chars std::{,b}float16_t support The following patch on top of https://gcc.gnu.org/pipermail/libstdc++/2022-October/054849.html adds std::{,b}float16_t support for std::to_chars. When precision is specified (or for std::bfloat16_t for hex mode even if not), I believe we can just use the std::to_chars float (when float is mode compatible with std::float32_t) overloads, both formats are proper subsets of std::float32_t. Unfortunately when precision is not specified and we are supposed to emit shortest string, the std::{,b}float16_t strings are usually much shorter. E.g. 1.e7p-14f16 shortest fixed representation is 0.0001161 and shortest scientific representation is 1.161e-04 while 1.e7p-14f32 (same number promoted to std::float32_t) 0.00011610985 and 1.1610985e-04. Similarly for 1.38p-112bf16, 0.000000000000000000000000000000000235 2.35e-34 vs. 1.38p-112f32 0.00000000000000000000000000000000023472271 2.3472271e-34 For std::float16_t there are differences even in the shortest hex, say: 0.01p-14 vs. 1p-22 but only for denormal std::float16_t values (where all std::float16_t denormals converted to std::float32_t are normal), __FLT16_MIN__ and everything larger in absolute value than that is the same. Unless that is a bug and we should try to discover shorter representations even for denormals... std::bfloat16_t has the same exponent range as std::float32_t, so all std::bfloat16_t denormals are also std::float32_t denormals and thus the shortest hex representations are the same. As documented, ryu can handle arbitrary IEEE like floating point formats (probably not wider than IEEE quad) using the generic_128 handling, but ryu is hidden in libstdc++.so. As only few architectures support std::float16_t right now and some of them have special ISA requirements for those (e.g. on i?86 one needs -msse2) and std::bfloat16_t is right now supported only on x86 (again with -msse2), perhaps with aarch64/arm coming next if ARM is interested, but I think it is possible that more will be added later, instead of exporting APIs from the library to handle directly the std::{,b}float16_t overloads this patch instead exports functions which take a float which is a superset of those and expects the inline overloads to promote the 16-bit formats to 32-bit, then inside of the library it ensures they are printed right. With the added [[gnu::cold]] attribute because I think most users will primarily use these formats as storage formats and perform arithmetics in the excess precision for them and print also as std::float32_t the added support doesn't seem to be too large, on x86_64: readelf -Ws libstdc++.so.6.0.31 | grep float16_t 912: 00000000000ae824 950 FUNC GLOBAL DEFAULT 13 _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format@@GLIBCXX_3.4.31 5767: 00000000000ae4a1 899 FUNC GLOBAL DEFAULT 13 _ZSt20__to_chars_float16_tPcS_fSt12chars_format@@GLIBCXX_3.4.31 842: 000000000016d430 106 FUNC LOCAL DEFAULT 13 _ZN12_GLOBAL__N_113get_ieee_reprINS_23floating_type_float16_tEEENS_6ieee_tIT_EES3_ 865: 0000000000170980 1613 FUNC LOCAL DEFAULT 13 +_ZSt23__floating_to_chars_hexIN12_GLOBAL__N_123floating_type_float16_tEESt15to_chars_resultPcS3_T_St8optionalIiE.constprop.0.isra.0 7205: 00000000000ae824 950 FUNC GLOBAL DEFAULT 13 _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format 7985: 00000000000ae4a1 899 FUNC GLOBAL DEFAULT 13 _ZSt20__to_chars_float16_tPcS_fSt12chars_format so 3568 code bytes together or so. Tested with the attached test (which doesn't prove the shortest representation, just prints std::{,b}float16_t and std::float32_t shortest strings side by side, then tries to verify it can be emitted even into the exact sized range and can't be into range one smaller than that and tries to read what is printed back using from_chars float32_t overload (so there could be double rounding, but apparently there is none for the shortest strings). The only differences printed are for NaNs, where sNaNs are canonicalized to canonical qNaNs and as to_chars doesn't print NaN mantissa, even qNaNs other than the canonical one are read back just as the canonical NaN. Also attaching what Patrick wrote to generate the pow10_adjustment_tab, for std::float16_t only 1.0, 10.0, 100.0, 1000.0 and 10000.0 are powers of 10 in the range because __FLT16_MAX__ is 65504.0, and all of the above are exactly representable in std::float16_t, so we want to use 0 in pow10_adjustment_tab. 2022-11-01 Jakub Jelinek * include/std/charconv (__to_chars_float16_t, __to_chars_bfloat16_t): Declare. (to_chars): Add _Float16 and __gnu_cxx::__bfloat16_t overloads. * config/abi/pre/gnu.ver (GLIBCXX_3.4.31): Export _ZSt20__to_chars_float16_tPcS_fSt12chars_format and _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format. * src/c++17/floating_to_chars.cc (floating_type_float16_t, floating_type_bfloat16_t): New types. (floating_type_traits, floating_type_traits, get_ieee_repr, get_ieee_repr, __handle_special_value, __handle_special_value): New specializations. (floating_to_shortest_scientific): Handle floating_type_float16_t and floating_type_bfloat16_t like IEEE quad. (__floating_to_chars_shortest): For floating_type_bfloat16_t call __floating_to_chars_hex rather than __floating_to_chars_hex to avoid instantiating the latter. (__to_chars_float16_t, __to_chars_bfloat16_t): New functions. --- libstdc++-v3/config/abi/pre/gnu.ver | 2 + libstdc++-v3/include/std/charconv | 44 ++++++++ libstdc++-v3/src/c++17/floating_to_chars.cc | 164 +++++++++++++++++++++++++++- 3 files changed, 208 insertions(+), 2 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 7f30377..729e0cf 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2446,6 +2446,8 @@ GLIBCXX_3.4.30 { GLIBCXX_3.4.31 { _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE15_M_replace_cold*; + _ZSt20__to_chars_float16_tPcS_fSt12chars_format; + _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format; } GLIBCXX_3.4.30; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index 9b9cd83..e391a27 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -738,6 +738,32 @@ namespace __detail to_chars_result to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision) noexcept; + // Library routines for 16-bit extended floating point formats + // using float as interchange format. + to_chars_result __to_chars_float16_t(char* __first, char* __last, + float __value, + chars_format __fmt) noexcept; + to_chars_result __to_chars_bfloat16_t(char* __first, char* __last, + float __value, + chars_format __fmt) noexcept; + +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline to_chars_result + to_chars(char* __first, char* __last, _Float16 __value) noexcept + { + return __to_chars_float16_t(__first, __last, float(__value), + chars_format{}); + } + inline to_chars_result + to_chars(char* __first, char* __last, _Float16 __value, + chars_format __fmt) noexcept + { return __to_chars_float16_t(__first, __last, float(__value), __fmt); } + inline to_chars_result + to_chars(char* __first, char* __last, _Float16 __value, + chars_format __fmt, int __precision) noexcept + { return to_chars(__first, __last, float(__value), __fmt, __precision); } +#endif + #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) inline to_chars_result to_chars(char* __first, char* __last, _Float32 __value) noexcept @@ -784,6 +810,24 @@ namespace __detail __precision); } #endif + +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + inline to_chars_result + to_chars(char* __first, char* __last, + __gnu_cxx::__bfloat16_t __value) noexcept + { + return __to_chars_bfloat16_t(__first, __last, float(__value), + chars_format{}); + } + inline to_chars_result + to_chars(char* __first, char* __last, __gnu_cxx::__bfloat16_t __value, + chars_format __fmt) noexcept + { return __to_chars_bfloat16_t(__first, __last, float(__value), __fmt); } + inline to_chars_result + to_chars(char* __first, char* __last, __gnu_cxx::__bfloat16_t __value, + chars_format __fmt, int __precision) noexcept + { return to_chars(__first, __last, float(__value), __fmt, __precision); } +#endif #endif _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc b/libstdc++-v3/src/c++17/floating_to_chars.cc index b1c915e..43e1ff3 100644 --- a/libstdc++-v3/src/c++17/floating_to_chars.cc +++ b/libstdc++-v3/src/c++17/floating_to_chars.cc @@ -374,6 +374,44 @@ namespace }; #endif + // Wrappers around float for std::{,b}float16_t promoted to float. + struct floating_type_float16_t + { + float x; + operator float() const { return x; } + }; + struct floating_type_bfloat16_t + { + float x; + operator float() const { return x; } + }; + + template<> + struct floating_type_traits + { + static constexpr int mantissa_bits = 10; + static constexpr int exponent_bits = 5; + static constexpr bool has_implicit_leading_bit = true; + using mantissa_t = uint32_t; + using shortest_scientific_t = ryu::floating_decimal_128; + + static constexpr uint64_t pow10_adjustment_tab[] + = { 0 }; + }; + + template<> + struct floating_type_traits + { + static constexpr int mantissa_bits = 7; + static constexpr int exponent_bits = 8; + static constexpr bool has_implicit_leading_bit = true; + using mantissa_t = uint32_t; + using shortest_scientific_t = ryu::floating_decimal_128; + + static constexpr uint64_t pow10_adjustment_tab[] + = { 0b0000111001110001101010010110100101010010000000000000000000000000 }; + }; + // An IEEE-style decomposition of a floating-point value of type T. template struct ieee_t @@ -482,6 +520,79 @@ namespace } #endif + template<> + ieee_t + get_ieee_repr(const floating_type_float16_t value) + { + using mantissa_t = typename floating_type_traits::mantissa_t; + constexpr int mantissa_bits = floating_type_traits::mantissa_bits; + constexpr int exponent_bits = floating_type_traits::exponent_bits; + + uint32_t value_bits = 0; + memcpy(&value_bits, &value.x, sizeof(value)); + + ieee_t ieee_repr; + ieee_repr.mantissa + = static_cast(value_bits & ((uint32_t{1} << mantissa_bits) - 1u)); + value_bits >>= mantissa_bits; + ieee_repr.biased_exponent + = static_cast(value_bits & ((uint32_t{1} << exponent_bits) - 1u)); + value_bits >>= exponent_bits; + ieee_repr.sign = (value_bits & 1) != 0; + // We have mantissa and biased_exponent from the float (originally + // float16_t converted to float). + // Transform that to float16_t mantissa and biased_exponent. + // If biased_exponent is 0, then value is +-0.0. + // If biased_exponent is 0x67..0x70, then it is a float16_t denormal. + if (ieee_repr.biased_exponent >= 0x67 + && ieee_repr.biased_exponent <= 0x70) + { + int n = ieee_repr.biased_exponent - 0x67; + ieee_repr.mantissa = ((uint32_t{1} << n) + | (ieee_repr.mantissa >> (mantissa_bits - n))); + ieee_repr.biased_exponent = 0; + } + // If biased_exponent is 0xff, then it is a float16_t inf or NaN. + else if (ieee_repr.biased_exponent == 0xff) + { + ieee_repr.mantissa >>= 13; + ieee_repr.biased_exponent = 0x1f; + } + // If biased_exponent is 0x71..0x8e, then it is a float16_t normal number. + else if (ieee_repr.biased_exponent > 0x70) + { + ieee_repr.mantissa >>= 13; + ieee_repr.biased_exponent -= 0x70; + } + return ieee_repr; + } + + template<> + ieee_t + get_ieee_repr(const floating_type_bfloat16_t value) + { + using mantissa_t = typename floating_type_traits::mantissa_t; + constexpr int mantissa_bits = floating_type_traits::mantissa_bits; + constexpr int exponent_bits = floating_type_traits::exponent_bits; + + uint32_t value_bits = 0; + memcpy(&value_bits, &value.x, sizeof(value)); + + ieee_t ieee_repr; + ieee_repr.mantissa + = static_cast(value_bits & ((uint32_t{1} << mantissa_bits) - 1u)); + value_bits >>= mantissa_bits; + ieee_repr.biased_exponent + = static_cast(value_bits & ((uint32_t{1} << exponent_bits) - 1u)); + value_bits >>= exponent_bits; + ieee_repr.sign = (value_bits & 1) != 0; + // We have mantissa and biased_exponent from the float (originally + // bfloat16_t converted to float). + // Transform that to bfloat16_t mantissa and biased_exponent. + ieee_repr.mantissa >>= 16; + return ieee_repr; + } + // Invoke Ryu to obtain the shortest scientific form for the given // floating-point number. template @@ -493,7 +604,9 @@ namespace else if constexpr (std::is_same_v) return ryu::floating_to_fd64(value); else if constexpr (std::is_same_v - || std::is_same_v) + || std::is_same_v + || std::is_same_v + || std::is_same_v) { constexpr int mantissa_bits = floating_type_traits::mantissa_bits; @@ -678,6 +791,28 @@ template return {{first, errc{}}}; } +template<> + optional + __handle_special_value(char* first, + char* const last, + const floating_type_float16_t value, + const chars_format fmt, + const int precision) + { + return __handle_special_value(first, last, value.x, fmt, precision); + } + +template<> + optional + __handle_special_value(char* first, + char* const last, + const floating_type_bfloat16_t value, + const chars_format fmt, + const int precision) + { + return __handle_special_value(first, last, value.x, fmt, precision); + } + // This subroutine of the floating-point to_chars overloads performs // hexadecimal formatting. template @@ -922,7 +1057,15 @@ template chars_format fmt) { if (fmt == chars_format::hex) - return __floating_to_chars_hex(first, last, value, nullopt); + { + // std::bfloat16_t has the same exponent range as std::float32_t + // and so we can avoid instantiation of __floating_to_chars_hex + // for bfloat16_t. Shortest hex will be the same as for float. + if constexpr (is_same_v) + return __floating_to_chars_hex(first, last, value.x, nullopt); + else + return __floating_to_chars_hex(first, last, value, nullopt); + } __glibcxx_assert(fmt == chars_format::fixed || fmt == chars_format::scientific @@ -1662,6 +1805,23 @@ to_chars(char* first, char* last, __float128 value, chars_format fmt, } #endif +// Entrypoints for 16-bit floats. +[[gnu::cold]] to_chars_result +__to_chars_float16_t(char* first, char* last, float value, + chars_format fmt) noexcept +{ + return __floating_to_chars_shortest(first, last, + floating_type_float16_t{ value }, fmt); +} + +[[gnu::cold]] to_chars_result +__to_chars_bfloat16_t(char* first, char* last, float value, + chars_format fmt) noexcept +{ + return __floating_to_chars_shortest(first, last, + floating_type_bfloat16_t{ value }, fmt); +} + #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT // Map the -mlong-double-64 long double overloads to the double overloads. extern "C" to_chars_result -- cgit v1.1 From 81f98afa22815e7397714caf6fa0fc815803ebaa Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 1 Nov 2022 13:41:57 +0100 Subject: libstdc++: std::from_chars std::{,b}float16_t support The following patch adds std::from_chars support, similarly to the previous std::to_chars patch through APIs that use float instead of the 16-bit floating point formats as container. The patch uses the fast_float library and doesn't need any changes to it, like the previous patch it introduces wrapper classes around float that represent the float holding float16_t or bfloat16_t value, and specializes binary_format etc. from fast_float for these classes. The new test verifies exhaustively to_chars and from_chars afterward results in the original value (except for nans) in all the fmt cases. 2022-11-01 Jakub Jelinek * include/std/charconv (__from_chars_float16_t, __from_chars_bfloat16_t): Declare. (from_chars): Add _Float16 and __gnu_cxx::__bfloat16_t overloads. * config/abi/pre/gnu.ver (GLIBCXX_3.4.31): Export _ZSt22__from_chars_float16_tPKcS0_RfSt12chars_format and _ZSt23__from_chars_bfloat16_tPKcS0_RfSt12chars_format. * src/c++17/floating_from_chars.cc (fast_float::floating_type_float16_t, fast_float::floating_type_bfloat16_t): New classes. (fast_float::binary_format, fast_float::binary_format): New specializations. (fast_float::to_float, fast_float::to_float, fast_float::to_extended, fast_float::to_extended): Likewise. (fast_float::from_chars_16): New template function. (__floating_from_chars_hex): Allow instantiation with fast_float::floating_type_{,b}float16_t. (from_chars): Formatting fixes for float/double/long double overloads. (__from_chars_float16_t, __from_chars_bfloat16_t): New functions. * testsuite/20_util/to_chars/float16_c++23.cc: New test. --- libstdc++-v3/config/abi/pre/gnu.ver | 2 + libstdc++-v3/include/std/charconv | 42 +++ libstdc++-v3/src/c++17/floating_from_chars.cc | 400 +++++++++++++++++++-- .../testsuite/20_util/to_chars/float16_c++23.cc | 76 ++++ 4 files changed, 491 insertions(+), 29 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/to_chars/float16_c++23.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver index 729e0cf..1c714fb 100644 --- a/libstdc++-v3/config/abi/pre/gnu.ver +++ b/libstdc++-v3/config/abi/pre/gnu.ver @@ -2448,6 +2448,8 @@ GLIBCXX_3.4.31 { _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE15_M_replace_cold*; _ZSt20__to_chars_float16_tPcS_fSt12chars_format; _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format; + _ZSt22__from_chars_float16_tPKcS0_RfSt12chars_format; + _ZSt23__from_chars_bfloat16_tPKcS0_RfSt12chars_format; } GLIBCXX_3.4.30; # Symbols in the support library (libsupc++) have their own tag. diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv index e391a27..e9bf953 100644 --- a/libstdc++-v3/include/std/charconv +++ b/libstdc++-v3/include/std/charconv @@ -673,6 +673,32 @@ namespace __detail from_chars(const char* __first, const char* __last, long double& __value, chars_format __fmt = chars_format::general) noexcept; + // Library routines for 16-bit extended floating point formats + // using float as interchange format. + from_chars_result + __from_chars_float16_t(const char* __first, const char* __last, + float& __value, + chars_format __fmt = chars_format::general) noexcept; + from_chars_result + __from_chars_bfloat16_t(const char* __first, const char* __last, + float& __value, + chars_format __fmt = chars_format::general) noexcept; + +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) \ + && defined(__cpp_lib_to_chars) + inline from_chars_result + from_chars(const char* __first, const char* __last, _Float16& __value, + chars_format __fmt = chars_format::general) noexcept + { + float __val; + from_chars_result __res + = __from_chars_float16_t(__first, __last, __val, __fmt); + if (__res.ec == errc{}) + __value = __val; + return __res; + } +#endif + #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) inline from_chars_result from_chars(const char* __first, const char* __last, _Float32& __value, @@ -711,6 +737,22 @@ namespace __detail return __res; } #endif + +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) \ + && defined(__cpp_lib_to_chars) + inline from_chars_result + from_chars(const char* __first, const char* __last, + __gnu_cxx::__bfloat16_t & __value, + chars_format __fmt = chars_format::general) noexcept + { + float __val; + from_chars_result __res + = __from_chars_bfloat16_t(__first, __last, __val, __fmt); + if (__res.ec == errc{}) + __value = __val; + return __res; + } +#endif #endif #if defined __cpp_lib_to_chars diff --git a/libstdc++-v3/src/c++17/floating_from_chars.cc b/libstdc++-v3/src/c++17/floating_from_chars.cc index 5d2a931..a25ac5c 100644 --- a/libstdc++-v3/src/c++17/floating_from_chars.cc +++ b/libstdc++-v3/src/c++17/floating_from_chars.cc @@ -75,6 +75,272 @@ extern "C" __ieee128 __strtoieee128(const char*, char**); namespace { # include "fast_float/fast_float.h" + +namespace fast_float +{ + + // Wrappers around float for std::{,b}float16_t promoted to float. + struct floating_type_float16_t + { + float* x; + uint16_t bits; + }; + struct floating_type_bfloat16_t + { + float* x; + uint16_t bits; + }; + + template<> + constexpr int + binary_format::mantissa_explicit_bits() + { return 10; } + + template<> + constexpr int + binary_format::mantissa_explicit_bits() + { return 7; } + + // 10 bits of stored mantissa, pow(5,q) <= 0x4p+10 implies q <= 5 + template<> + constexpr int + binary_format::max_exponent_round_to_even() + { return 5; } + + // 7 bits of stored mantissa, pow(5,q) <= 0x4p+7 implies q <= 3 + template<> + constexpr int + binary_format::max_exponent_round_to_even() + { return 3; } + + // 10 bits of stored mantissa, pow(5,-q) < 0x1p+64 / 0x1p+11 implies q >= -22 + template<> + constexpr int + binary_format::min_exponent_round_to_even() + { return -22; } + + // 7 bits of stored mantissa, pow(5,-q) < 0x1p+64 / 0x1p+8 implies q >= -24 + template<> + constexpr int + binary_format::min_exponent_round_to_even() + { return -24; } + + template<> + constexpr int + binary_format::minimum_exponent() + { return -15; } + + template<> + constexpr int + binary_format::minimum_exponent() + { return -127; } + + template<> + constexpr int + binary_format::infinite_power() + { return 0x1F; } + + template<> + constexpr int + binary_format::infinite_power() + { return 0xFF; } + + template<> + constexpr int + binary_format::sign_index() + { return 15; } + + template<> + constexpr int + binary_format::sign_index() + { return 15; } + + template<> + constexpr int + binary_format::largest_power_of_ten() + { return 4; } + + template<> + constexpr int + binary_format::largest_power_of_ten() + { return 38; } + + template<> + constexpr int + binary_format::smallest_power_of_ten() + { return -27; } + + template<> + constexpr int + binary_format::smallest_power_of_ten() + { return -60; } + + template<> + constexpr size_t + binary_format::max_digits() + { return 22; } + + template<> + constexpr size_t + binary_format::max_digits() + { return 98; } + + // negative_digit_comp converts adjusted_mantissa to the (originally only) + // floating type and immediately back with slight tweaks (e.g. explicit + // leading bit instead of implicit for normals). + // Avoid going through the floating point type. + template<> + fastfloat_really_inline void + to_float(bool negative, adjusted_mantissa am, + floating_type_float16_t &value) + { + constexpr int mantissa_bits + = binary_format::mantissa_explicit_bits(); + value.bits = (am.mantissa + | (uint16_t(am.power2) << mantissa_bits) + | (negative ? 0x8000 : 0)); + } + + template<> + fastfloat_really_inline void + to_float(bool negative, adjusted_mantissa am, + floating_type_bfloat16_t &value) + { + constexpr int mantissa_bits + = binary_format::mantissa_explicit_bits(); + value.bits = (am.mantissa + | (uint16_t(am.power2) << mantissa_bits) + | (negative ? 0x8000 : 0)); + } + + template <> + fastfloat_really_inline adjusted_mantissa + to_extended(floating_type_float16_t value) noexcept + { + adjusted_mantissa am; + constexpr int mantissa_bits + = binary_format::mantissa_explicit_bits(); + int32_t bias + = (mantissa_bits + - binary_format::minimum_exponent()); + constexpr uint16_t exponent_mask = 0x7C00; + constexpr uint16_t mantissa_mask = 0x03FF; + constexpr uint16_t hidden_bit_mask = 0x0400; + if ((value.bits & exponent_mask) == 0) { + // denormal + am.power2 = 1 - bias; + am.mantissa = value.bits & mantissa_mask; + } else { + // normal + am.power2 = int32_t((value.bits & exponent_mask) >> mantissa_bits); + am.power2 -= bias; + am.mantissa = (value.bits & mantissa_mask) | hidden_bit_mask; + } + return am; + } + + template <> + fastfloat_really_inline adjusted_mantissa + to_extended(floating_type_bfloat16_t value) noexcept + { + adjusted_mantissa am; + constexpr int mantissa_bits + = binary_format::mantissa_explicit_bits(); + int32_t bias + = (mantissa_bits + - binary_format::minimum_exponent()); + constexpr uint16_t exponent_mask = 0x7F80; + constexpr uint16_t mantissa_mask = 0x007F; + constexpr uint16_t hidden_bit_mask = 0x0080; + if ((value.bits & exponent_mask) == 0) { + // denormal + am.power2 = 1 - bias; + am.mantissa = value.bits & mantissa_mask; + } else { + // normal + am.power2 = int32_t((value.bits & exponent_mask) >> mantissa_bits); + am.power2 -= bias; + am.mantissa = (value.bits & mantissa_mask) | hidden_bit_mask; + } + return am; + } + + // Like fast_float.h from_chars_advanced, but for 16-bit float. + template + from_chars_result + from_chars_16(const char* first, const char* last, T &value, + chars_format fmt) noexcept + { + parse_options options{fmt}; + + from_chars_result answer; + if (first == last) + { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + + parsed_number_string pns = parse_number_string(first, last, options); + if (!pns.valid) + return detail::parse_infnan(first, last, *value.x); + + answer.ec = std::errc(); + answer.ptr = pns.lastmatch; + + adjusted_mantissa am + = compute_float>(pns.exponent, pns.mantissa); + if (pns.too_many_digits && am.power2 >= 0) + { + if (am != compute_float>(pns.exponent, + pns.mantissa + 1)) + am = compute_error>(pns.exponent, pns.mantissa); + } + + // If we called compute_float>(pns.exponent, pns.mantissa) + // and we have an invalid power (am.power2 < 0), + // then we need to go the long way around again. This is very uncommon. + if (am.power2 < 0) + am = digit_comp(pns, am); + + if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) + || am.power2 == binary_format::infinite_power()) + { + // In case of over/underflow, return result_out_of_range and don't + // modify value, as per [charconv.from.chars]/1. Note that LWG 3081 wants + // to modify value in this case too. + answer.ec = std::errc::result_out_of_range; + return answer; + } + + // Transform the {,b}float16_t to float32_t before to_float. + if constexpr (std::is_same_v) + { + if (am.power2 == 0) + { + if (am.mantissa) + { + int n = (std::numeric_limits::digits + - __builtin_clz (am.mantissa)) - 1; + am.mantissa &= ~(static_cast(1) << n); + am.mantissa <<= (binary_format::mantissa_explicit_bits() + - n); + am.power2 = n + 0x67; + } + } + else + { + am.mantissa <<= 13; + am.power2 += 0x70; + } + } + else + am.mantissa <<= 16; + to_float(pns.negative, am, *value.x); + return answer; + } +} // fast_float + } // anon namespace #endif @@ -490,11 +756,14 @@ namespace from_chars_result __floating_from_chars_hex(const char* first, const char* last, T& value) { - static_assert(is_same_v || is_same_v); - - using uint_t = conditional_t, uint32_t, uint64_t>; - constexpr int mantissa_bits = is_same_v ? 23 : 52; - constexpr int exponent_bits = is_same_v ? 8 : 11; + using uint_t = conditional_t, uint32_t, + conditional_t, uint64_t, + uint16_t>>; + constexpr int mantissa_bits + = fast_float::binary_format::mantissa_explicit_bits(); + constexpr int exponent_bits + = is_same_v ? 11 + : is_same_v ? 5 : 8; constexpr int exponent_bias = (1 << (exponent_bits - 1)) - 1; __glibcxx_requires_valid_range(first, last); @@ -520,12 +789,21 @@ namespace if (starts_with_ci(first, last, "inity"sv)) first += strlen("inity"); - uint_t result = 0; - result |= sign_bit; - result <<= exponent_bits; - result |= (1ull << exponent_bits) - 1; - result <<= mantissa_bits; - memcpy(&value, &result, sizeof(result)); + if constexpr (is_same_v || is_same_v) + { + uint_t result = 0; + result |= sign_bit; + result <<= exponent_bits; + result |= (1ull << exponent_bits) - 1; + result <<= mantissa_bits; + memcpy(&value, &result, sizeof(result)); + } + else + { + // float +/-Inf. + uint32_t result = 0x7F800000 | (sign_bit ? 0x80000000U : 0); + memcpy(value.x, &result, sizeof(result)); + } return {first, errc{}}; } @@ -566,12 +844,21 @@ namespace // We make the implementation-defined decision of ignoring the // sign bit and the n-char-sequence when assembling the NaN. - uint_t result = 0; - result <<= exponent_bits; - result |= (1ull << exponent_bits) - 1; - result <<= mantissa_bits; - result |= (1ull << (mantissa_bits - 1)) | 1; - memcpy(&value, &result, sizeof(result)); + if constexpr (is_same_v || is_same_v) + { + uint_t result = 0; + result <<= exponent_bits; + result |= (1ull << exponent_bits) - 1; + result <<= mantissa_bits; + result |= (1ull << (mantissa_bits - 1)) | 1; + memcpy(&value, &result, sizeof(result)); + } + else + { + // float qNaN. + uint32_t result = 0x7FC00001; + memcpy(value.x, &result, sizeof(result)); + } return {first, errc{}}; } @@ -633,18 +920,27 @@ namespace mantissa |= uint_t(hexit) << mantissa_idx; else if (mantissa_idx >= -4) { - if constexpr (is_same_v) + if constexpr (is_same_v + || is_same_v) { __glibcxx_assert(mantissa_idx == -1); mantissa |= hexit >> 1; midpoint_bit = (hexit & 0b0001) != 0; } - else + else if constexpr (is_same_v) { __glibcxx_assert(mantissa_idx == -4); midpoint_bit = (hexit & 0b1000) != 0; nonzero_tail = (hexit & 0b0111) != 0; } + else + { + __glibcxx_assert(mantissa_idx == -2); + mantissa |= hexit >> 2; + midpoint_bit = (hexit & 0b0010) != 0; + nonzero_tail = (hexit & 0b0001) != 0; + } } else nonzero_tail |= (hexit != 0x0); @@ -808,7 +1104,34 @@ namespace __glibcxx_assert(((mantissa & (1ull << mantissa_bits)) != 0) == (biased_exponent != 0)); } - memcpy(&value, &result, sizeof(result)); + if constexpr (is_same_v || is_same_v) + memcpy(&value, &result, sizeof(result)); + else if constexpr (is_same_v) + { + uint32_t res = uint32_t{result} << 16; + memcpy(value.x, &res, sizeof(res)); + } + else + { + // Otherwise float16_t which needs to be converted to float32_t. + uint32_t res; + if ((result & 0x7FFF) == 0) + res = uint32_t{result} << 16; // +/-0.0f16 + else if ((result & 0x7C00) == 0) + { // denormal + unsigned n = (std::numeric_limits::digits + - __builtin_clz (result & 0x3FF) - 1); + res = uint32_t{result} & 0x3FF & ~(uint32_t{1} << n); + res <<= 23 - n; + res |= (((uint32_t{n} + 0x67) << 23) + | ((uint32_t{result} & 0x8000) << 16)); + } + else + res = (((uint32_t{result} & 0x3FF) << 13) + | ((((uint32_t{result} >> 10) & 0x1F) + 0x70) << 23) + | ((uint32_t{result} & 0x8000) << 16)); + memcpy(value.x, &res, sizeof(res)); + } return {first, errc{}}; } @@ -826,9 +1149,7 @@ from_chars(const char* first, const char* last, float& value, if (fmt == chars_format::hex) return __floating_from_chars_hex(first, last, value); else - { - return fast_float::from_chars(first, last, value, fmt); - } + return fast_float::from_chars(first, last, value, fmt); #else return from_chars_strtod(first, last, value, fmt); #endif @@ -842,9 +1163,7 @@ from_chars(const char* first, const char* last, double& value, if (fmt == chars_format::hex) return __floating_from_chars_hex(first, last, value); else - { - return fast_float::from_chars(first, last, value, fmt); - } + return fast_float::from_chars(first, last, value, fmt); #else return from_chars_strtod(first, last, value, fmt); #endif @@ -863,9 +1182,7 @@ from_chars(const char* first, const char* last, long double& value, if (fmt == chars_format::hex) result = __floating_from_chars_hex(first, last, dbl_value); else - { - result = fast_float::from_chars(first, last, dbl_value, fmt); - } + result = fast_float::from_chars(first, last, dbl_value, fmt); if (result.ec == errc{}) value = dbl_value; return result; @@ -874,6 +1191,31 @@ from_chars(const char* first, const char* last, long double& value, #endif } +#if USE_LIB_FAST_FLOAT +// Entrypoints for 16-bit floats. +[[gnu::cold]] from_chars_result +__from_chars_float16_t(const char* first, const char* last, float& value, + chars_format fmt) noexcept +{ + struct fast_float::floating_type_float16_t val{ &value, 0 }; + if (fmt == chars_format::hex) + return __floating_from_chars_hex(first, last, val); + else + return fast_float::from_chars_16(first, last, val, fmt); +} + +[[gnu::cold]] from_chars_result +__from_chars_bfloat16_t(const char* first, const char* last, float& value, + chars_format fmt) noexcept +{ + struct fast_float::floating_type_bfloat16_t val{ &value, 0 }; + if (fmt == chars_format::hex) + return __floating_from_chars_hex(first, last, val); + else + return fast_float::from_chars_16(first, last, val, fmt); +} +#endif + #ifdef _GLIBCXX_LONG_DOUBLE_COMPAT // Make std::from_chars for 64-bit long double an alias for the overload // for double. diff --git a/libstdc++-v3/testsuite/20_util/to_chars/float16_c++23.cc b/libstdc++-v3/testsuite/20_util/to_chars/float16_c++23.cc new file mode 100644 index 0000000..db93537 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/to_chars/float16_c++23.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. +// +// 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. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2b" } +// { dg-do run { target c++23 } } +// { dg-require-effective-target ieee_floats } +// { dg-require-effective-target size32plus } +// { dg-add-options ieee } + +#include +#include +#include +#include +#include + +template +void +test(std::chars_format fmt = std::chars_format{}) +{ + char str1[128], str2[128], str3[128]; + union U { unsigned short s; T f; } u, v; + for (int i = 0; i <= (unsigned short) ~0; ++i) + { + u.s = i; + auto [ptr1, ec1] = std::to_chars(str1, str1 + sizeof(str1), u.f, fmt); + auto [ptr2, ec2] = std::to_chars(str2, str2 + sizeof(str2), std::float32_t(u.f), fmt); + VERIFY( ec1 == std::errc() && ec2 == std::errc()); +// std::cout << i << ' ' << std::string_view (str1, ptr1) +// << '\t' << std::string_view (str2, ptr2) << '\n'; + if (fmt == std::chars_format::fixed) + { + auto [ptr3, ec3] = std::to_chars(str3, str3 + (ptr1 - str1), u.f, fmt); + VERIFY( ec3 == std::errc() && ptr3 - str3 == ptr1 - str1 ); + auto [ptr4, ec4] = std::to_chars(str3, str3 + (ptr1 - str1 - 1), u.f, fmt); + VERIFY( ec4 != std::errc() ); + } + auto [ptr5, ec5] = std::from_chars(str1, ptr1, v.f, + fmt == std::chars_format{} + ? std::chars_format::general : fmt); + VERIFY( ec5 == std::errc() && ptr5 == ptr1 ); + VERIFY( u.s == v.s || (std::isnan(u.f) && std::isnan(v.f)) ); + } +} + +int +main() +{ +#ifdef __STDCPP_FLOAT16_T__ + test(); + test(std::chars_format::fixed); + test(std::chars_format::scientific); + test(std::chars_format::general); + test(std::chars_format::hex); +#endif +#ifdef __STDCPP_BFLOAT16_T__ + test(); + test(std::chars_format::fixed); + test(std::chars_format::scientific); + test(std::chars_format::general); + test(std::chars_format::hex); +#endif +} -- cgit v1.1 From 74e904bdcac3abdd0453daf3b6195d17e44b4cee Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 2 Nov 2022 00:17:38 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index a4d9275..dd12669 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,69 @@ +2022-11-01 Jakub Jelinek + + * include/std/charconv (__from_chars_float16_t, + __from_chars_bfloat16_t): Declare. + (from_chars): Add _Float16 and __gnu_cxx::__bfloat16_t overloads. + * config/abi/pre/gnu.ver (GLIBCXX_3.4.31): Export + _ZSt22__from_chars_float16_tPKcS0_RfSt12chars_format and + _ZSt23__from_chars_bfloat16_tPKcS0_RfSt12chars_format. + * src/c++17/floating_from_chars.cc + (fast_float::floating_type_float16_t, + fast_float::floating_type_bfloat16_t): New classes. + (fast_float::binary_format, + fast_float::binary_format): New + specializations. + (fast_float::to_float, + fast_float::to_float, + fast_float::to_extended, + fast_float::to_extended): Likewise. + (fast_float::from_chars_16): New template function. + (__floating_from_chars_hex): Allow instantiation with + fast_float::floating_type_{,b}float16_t. + (from_chars): Formatting fixes for float/double/long double overloads. + (__from_chars_float16_t, __from_chars_bfloat16_t): New functions. + * testsuite/20_util/to_chars/float16_c++23.cc: New test. + +2022-11-01 Jakub Jelinek + + * include/std/charconv (__to_chars_float16_t, __to_chars_bfloat16_t): + Declare. + (to_chars): Add _Float16 and __gnu_cxx::__bfloat16_t overloads. + * config/abi/pre/gnu.ver (GLIBCXX_3.4.31): Export + _ZSt20__to_chars_float16_tPcS_fSt12chars_format and + _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format. + * src/c++17/floating_to_chars.cc (floating_type_float16_t, + floating_type_bfloat16_t): New types. + (floating_type_traits, + floating_type_traits, + get_ieee_repr, + get_ieee_repr, + __handle_special_value, + __handle_special_value): New specializations. + (floating_to_shortest_scientific): Handle floating_type_float16_t + and floating_type_bfloat16_t like IEEE quad. + (__floating_to_chars_shortest): For floating_type_bfloat16_t call + __floating_to_chars_hex rather than + __floating_to_chars_hex to avoid + instantiating the latter. + (__to_chars_float16_t, __to_chars_bfloat16_t): New functions. + +2022-11-01 Jakub Jelinek + + * include/std/charconv (from_chars, to_chars): Add _Float{32,64,128} + overloads for cases where those types match {float,double,long double}. + * include/std/istream (basic_istream::operator>>): Add + _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. + * include/std/ostream (basic_ostream::operator<<): Add + _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. + * testsuite/20_util/from_chars/8.cc: New test. + * testsuite/26_numerics/headers/cmath/nextafter_c++23.cc (test): + Formatting fixes. + * testsuite/26_numerics/headers/cmath/functions_std_c++23.cc: Add + dg-options "-std=gnu++2b". + (test_functions, main): Formatting fixes. + * testsuite/26_numerics/headers/cmath/c99_classification_macros_c++23.cc: + Add dg-options "-std=gnu++2b". + 2022-10-31 Jakub Jelinek * include/std/complex (complex::complex converting ctor): For C++23 -- cgit v1.1 From b65e391da94476fbc5c8947c81af61aa74941dc8 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 2 Nov 2022 10:06:24 +0100 Subject: libstdc++: Shortest denormal hex std::to_chars On Fri, Oct 28, 2022 at 12:52:44PM -0400, Patrick Palka wrote: > > The following patch on top of > > https://gcc.gnu.org/pipermail/libstdc++/2022-October/054849.html > > adds std::{,b}float16_t support for std::to_chars. > > When precision is specified (or for std::bfloat16_t for hex mode even if not), > > I believe we can just use the std::to_chars float (when float is mode > > compatible with std::float32_t) overloads, both formats are proper subsets > > of std::float32_t. > > Unfortunately when precision is not specified and we are supposed to emit > > shortest string, the std::{,b}float16_t strings are usually much shorter. > > E.g. 1.e7p-14f16 shortest fixed representation is > > 0.0001161 and shortest scientific representation is > > 1.161e-04 while 1.e7p-14f32 (same number promoted to std::float32_t) > > 0.00011610985 and > > 1.1610985e-04. > > Similarly for 1.38p-112bf16, > > 0.000000000000000000000000000000000235 > > 2.35e-34 vs. 1.38p-112f32 > > 0.00000000000000000000000000000000023472271 > > 2.3472271e-34 > > For std::float16_t there are differences even in the shortest hex, say: > > 0.01p-14 vs. 1p-22 > > but only for denormal std::float16_t values (where all std::float16_t > > denormals converted to std::float32_t are normal), __FLT16_MIN__ and > > everything larger in absolute value than that is the same. Unless > > that is a bug and we should try to discover shorter representations > > even for denormals... > > IIRC for hex formatting of denormals I opted to be consistent with how > glibc printf formats them, instead of outputting the truly shortest > form. > > I wouldn't be against using the float32 overloads even for shortest hex > formatting of float16. The output is shorter but equivalent so it > shouldn't cause any problems. The following patch changes the behavior of the shortest hex denormals, such that they are printed like normals (so for has_implicit_leading_bit with 1p-149 instead of 0.000002p-126 etc., otherwise (Intel extended) with the leading digit before dot being [89abcdef]). I think for all the supported format it is never longer, it can be equal length e.g. for 0.fffffep-126 vs. 1.fffffcp-127 but fortunately no largest subnormal in any format has the unbiased exponent like -9, -99, -999, -9999 because then it would be longer and often it is shorter, sometimes much shorter. For the cases with precision it keeps the handling as is. While for !has_implicit_leading_bit we for normals or with this patch even denormals have really shortest representation, for other formats we sometimes do not, but this patch doesn't deal with that (we always use 1.NNN while we could use 1.NNN up to f.NNN and by that shortening by the last hexit if the last hexit doesn't have least significant bit set and unbiased exponent is not -9, -99, -999 or -9999. 2022-11-02 Jakub Jelinek * src/c++17/floating_to_chars.cc (__floating_to_chars_hex): Drop const from unbiased_exponent. Canonicalize denormals such that they have the leading bit set by shifting effective mantissa up and decreasing unbiased_exponent. (__floating_to_chars_shortest): Don't instantiate __floating_to_chars_hex for float16_t either and use float instead. * testsuite/20_util/to_chars/float.cc (float_to_chars_test_cases): Adjust testcases for shortest hex denormals. * testsuite/20_util/to_chars/double.cc (double_to_chars_test_cases): Likewise. --- libstdc++-v3/src/c++17/floating_to_chars.cc | 21 +++++++++++++++++---- libstdc++-v3/testsuite/20_util/to_chars/double.cc | 4 ++-- libstdc++-v3/testsuite/20_util/to_chars/float.cc | 4 ++-- 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/src/c++17/floating_to_chars.cc b/libstdc++-v3/src/c++17/floating_to_chars.cc index 43e1ff3..a253ee4 100644 --- a/libstdc++-v3/src/c++17/floating_to_chars.cc +++ b/libstdc++-v3/src/c++17/floating_to_chars.cc @@ -844,9 +844,9 @@ template const bool is_normal_number = (biased_exponent != 0); // Calculate the unbiased exponent. - const int32_t unbiased_exponent = (is_normal_number - ? biased_exponent - exponent_bias - : 1 - exponent_bias); + int32_t unbiased_exponent = (is_normal_number + ? biased_exponent - exponent_bias + : 1 - exponent_bias); // Shift the mantissa so that its bitwidth is a multiple of 4. constexpr unsigned rounded_mantissa_bits = (mantissa_bits + 3) / 4 * 4; @@ -863,6 +863,16 @@ template __glibcxx_assert(effective_mantissa & (mantissa_t{1} << (mantissa_bits - 1u))); } + else if (!precision.has_value() && effective_mantissa) + { + // 1.8p-23 is shorter than 0.00cp-14, so if precision is + // omitted, try to canonicalize denormals such that they + // have the leading bit set. + int width = __bit_width(effective_mantissa); + int shift = rounded_mantissa_bits - width + has_implicit_leading_bit; + unbiased_exponent -= shift; + effective_mantissa <<= shift; + } // Compute the shortest precision needed to print this value exactly, // disregarding trailing zeros. @@ -1061,7 +1071,10 @@ template // std::bfloat16_t has the same exponent range as std::float32_t // and so we can avoid instantiation of __floating_to_chars_hex // for bfloat16_t. Shortest hex will be the same as for float. - if constexpr (is_same_v) + // When we print shortest form even for denormals, we can do it + // for std::float16_t as well. + if constexpr (is_same_v + || is_same_v) return __floating_to_chars_hex(first, last, value.x, nullopt); else return __floating_to_chars_hex(first, last, value, nullopt); diff --git a/libstdc++-v3/testsuite/20_util/to_chars/double.cc b/libstdc++-v3/testsuite/20_util/to_chars/double.cc index 9a965d2..ac9a430 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/double.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/double.cc @@ -2821,8 +2821,8 @@ inline constexpr double_to_chars_testcase double_to_chars_test_cases[] = { // Test hexfloat corner cases. {0x1.728p+0, chars_format::hex, "1.728p+0"}, // instead of "2.e5p-1" - {0x0.0000000000001p-1022, chars_format::hex, "0.0000000000001p-1022"}, // instead of "1p-1074", min subnormal - {0x0.fffffffffffffp-1022, chars_format::hex, "0.fffffffffffffp-1022"}, // max subnormal + {0x0.0000000000001p-1022, chars_format::hex, "1p-1074"}, // min subnormal + {0x0.fffffffffffffp-1022, chars_format::hex, "1.ffffffffffffep-1023"}, // max subnormal {0x1p-1022, chars_format::hex, "1p-1022"}, // min normal {0x1.fffffffffffffp+1023, chars_format::hex, "1.fffffffffffffp+1023"}, // max normal diff --git a/libstdc++-v3/testsuite/20_util/to_chars/float.cc b/libstdc++-v3/testsuite/20_util/to_chars/float.cc index bcbd78f..5a5de63 100644 --- a/libstdc++-v3/testsuite/20_util/to_chars/float.cc +++ b/libstdc++-v3/testsuite/20_util/to_chars/float.cc @@ -521,8 +521,8 @@ inline constexpr float_to_chars_testcase float_to_chars_test_cases[] = { // Test hexfloat corner cases. {0x1.728p+0f, chars_format::hex, "1.728p+0"}, // instead of "2.e5p-1" - {0x0.000002p-126f, chars_format::hex, "0.000002p-126"}, // instead of "1p-149", min subnormal - {0x0.fffffep-126f, chars_format::hex, "0.fffffep-126"}, // max subnormal + {0x0.000002p-126f, chars_format::hex, "1p-149"}, // min subnormal + {0x0.fffffep-126f, chars_format::hex, "1.fffffcp-127"}, // max subnormal {0x1p-126f, chars_format::hex, "1p-126"}, // min normal {0x1.fffffep+127f, chars_format::hex, "1.fffffep+127"}, // max normal -- cgit v1.1 From 0c86a667486362e8bc6a92e5d36acaac4242c59f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 2 Nov 2022 13:35:53 +0100 Subject: libstdc++: _Bfloat16 for Jon pointed out that we have TODO: _Bfloat16 in . Right now _S_fp_fmt() returns _Binary16 for _Float16, __fp16 as well as __bf16 and it actually works because we don't have a special handling of _Binary16. So, either we could just document that, but I'm a little bit afraid if HPPA or MIPS don't start supporting _Float16 and/or __bf16. If they do, we have the #if defined __hppa__ || (defined __mips__ && !defined __mips_nan2008) // IEEE 754-1985 allowed the meaning of the quiet/signaling // bit to be reversed. Flip that to give desired ordering. if (__builtin_isnan(__x) && __builtin_isnan(__y)) { using _Int = decltype(__ix); constexpr int __nantype = __fmt == _Binary32 ? 22 : __fmt == _Binary64 ? 51 : __fmt == _Binary128 ? 111 : -1; constexpr _Int __bit = _Int(1) << __nantype; __ix ^= __bit; __iy ^= __bit; } #endif code, the only one where we actually care whether something is _Binary{32,64,128} (elsewhere we just care about the x86 and m68k 80bits or double double or just floating point type's sizeof) and we'd need to handle there _Binary16 and/or _Bfloat16. So this patch uses different enum for it even when it isn't needed right now, after all _Binary16 isn't needed either and we could just use _Binary32... 2022-11-02 Jakub Jelinek * libsupc++/compare (_Strong_order::_Fp_fmt): Add _Bfloat16. (_Strong_order::_Bfloat16): New static data member. (_Strong_order::_S_fp_fmt): Return _Bfloat16 for std::bfloat16_t. --- libstdc++-v3/libsupc++/compare | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index 066867e..e25f4ef 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -672,7 +672,7 @@ namespace std _GLIBCXX_VISIBILITY(default) _X86_80bit, // x86 80-bit extended precision _M68k_80bit, // m68k 80-bit extended precision _Dbldbl, // IBM 128-bit double-double - // TODO: _Bfloat16, + _Bfloat16, // std::bfloat16_t }; #ifndef __cpp_using_enum @@ -684,6 +684,7 @@ namespace std _GLIBCXX_VISIBILITY(default) static constexpr _Fp_fmt _X86_80bit = _Fp_fmt::_X86_80bit; static constexpr _Fp_fmt _M68k_80bit = _Fp_fmt::_M68k_80bit; static constexpr _Fp_fmt _Dbldbl = _Fp_fmt::_Dbldbl; + static constexpr _Fp_fmt _Bfloat16 = _Fp_fmt::_Bfloat16; #endif // Identify the format used by a floating-point type. @@ -714,6 +715,10 @@ namespace std _GLIBCXX_VISIBILITY(default) if constexpr (__is_same(_Tp, __float80)) return _X86_80bit; #endif +#ifdef __STDCPP_BFLOAT16_T__ + if constexpr (__is_same(_Tp, decltype(0.0bf16))) + return _Bfloat16; +#endif constexpr int __width = sizeof(_Tp) * __CHAR_BIT__; -- cgit v1.1 From cf35818a390e7cb4b1a4fa70c243ede59d6cbbac Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 1 Nov 2022 11:17:35 +0000 Subject: libstdc++: Ignore -Wignored-qualifiers warning in The warning is wrong here, the qualifier serves a purpose and is not ignored (c.f. PR c++/107492). libstdc++-v3/ChangeLog: * include/std/variant (__variant::_Multi_array::__untag_result): Use pragma to suppress warning. --- libstdc++-v3/include/std/variant | 3 +++ 1 file changed, 3 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index c234b54..ba8492b 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -831,10 +831,13 @@ namespace __variant : false_type { using element_type = _Tp; }; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wignored-qualifiers" template struct __untag_result : false_type { using element_type = void(*)(_Args...); }; +#pragma GCC diagnostic pop template struct __untag_result<__variant_cookie(*)(_Args...)> -- cgit v1.1 From f4874691812bc20e3d8e3302db439c27f30c472c Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 1 Nov 2022 13:47:24 +0000 Subject: libstdc++: Remove unnecessary variant member in std::expected Hui Xie pointed out that we don't need a dummy member in the union, because all constructors always initialize either _M_val or _M_unex. We still need the _M_void member of the expected specialization, because the constructor has to initialize something when not using the _M_unex member. libstdc++-v3/ChangeLog: * include/std/expected (expected::_M_invalid): Remove. --- libstdc++-v3/include/std/expected | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected index 3ee13aa..e491ce4 100644 --- a/libstdc++-v3/include/std/expected +++ b/libstdc++-v3/include/std/expected @@ -359,7 +359,7 @@ namespace __expected requires is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Er> && (!is_trivially_copy_constructible_v<_Tp> || !is_trivially_copy_constructible_v<_Er>) - : _M_invalid(), _M_has_value(__x._M_has_value) + : _M_has_value(__x._M_has_value) { if (_M_has_value) std::construct_at(__builtin_addressof(_M_val), __x._M_val); @@ -376,7 +376,7 @@ namespace __expected requires is_move_constructible_v<_Tp> && is_move_constructible_v<_Er> && (!is_trivially_move_constructible_v<_Tp> || !is_trivially_move_constructible_v<_Er>) - : _M_invalid(), _M_has_value(__x._M_has_value) + : _M_has_value(__x._M_has_value) { if (_M_has_value) std::construct_at(__builtin_addressof(_M_val), @@ -394,7 +394,7 @@ namespace __expected expected(const expected<_Up, _Gr>& __x) noexcept(__and_v, is_nothrow_constructible<_Er, const _Gr&>>) - : _M_invalid(), _M_has_value(__x._M_has_value) + : _M_has_value(__x._M_has_value) { if (_M_has_value) std::construct_at(__builtin_addressof(_M_val), __x._M_val); @@ -410,7 +410,7 @@ namespace __expected expected(expected<_Up, _Gr>&& __x) noexcept(__and_v, is_nothrow_constructible<_Er, _Gr>>) - : _M_invalid(), _M_has_value(__x._M_has_value) + : _M_has_value(__x._M_has_value) { if (_M_has_value) std::construct_at(__builtin_addressof(_M_val), @@ -890,7 +890,6 @@ namespace __expected } union { - struct { } _M_invalid; _Tp _M_val; _Er _M_unex; }; -- cgit v1.1 From 6d9dbdf51f9afe86a57fb28bc55065fa4500a72b Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Wed, 2 Nov 2022 08:56:59 -0400 Subject: libstdc++: Improve ERANGE behavior for fallback FP std::from_chars The fallback implementation of floating-point std::from_chars (used for formats other than binary32/64) just calls the C library's strtod family of functions. In case of overflow, the behavior of these functions is rigidly specified: If the correct value overflows and default rounding is in effect, plus or minus HUGE_VAL, HUGE_VALF, or HUGE_VALL is returned (according to the return type and sign of the value), and the value of the macro ERANGE is stored in errno. But in case of underflow, implementations are given more leeway: If the result underflows the functions return a value whose magnitude is no greater than the smallest normalized positive number in the return type; whether errno acquires the value ERANGE is implementation-defined. Thus the fallback implementation can (and does) portably detect overflow, but it can't portably detect underflow. However, glibc (and presumably other high-quality C library implementations) will reliably set errno to ERANGE in case of underflow as well, and it'll also return the nearest denormal number to the correct value (zero in case of true underflow), which allows callers to succesfully parse denormal numbers. So since we can't be perfect here, this patch takes the best effort approach of assuming a high quality C library implementation with respect to this underflow behavior, and refines our implementation to try to distiguish between a denormal result and true underflow by inspecting strtod's return value. libstdc++-v3/ChangeLog: * src/c++17/floating_from_chars.cc (from_chars_impl): In the ERANGE case, distinguish between a denormal result and true underflow by checking if the return value is 0. --- libstdc++-v3/src/c++17/floating_from_chars.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/src/c++17/floating_from_chars.cc b/libstdc++-v3/src/c++17/floating_from_chars.cc index a25ac5c..939c751 100644 --- a/libstdc++-v3/src/c++17/floating_from_chars.cc +++ b/libstdc++-v3/src/c++17/floating_from_chars.cc @@ -637,8 +637,13 @@ namespace { if (__builtin_isinf(tmpval)) // overflow ec = errc::result_out_of_range; - else // underflow (LWG 3081 wants to set value = tmpval here) + else if (tmpval == 0) // underflow (LWG 3081 wants to set value = tmpval here) ec = errc::result_out_of_range; + else // denormal value + { + value = tmpval; + ec = errc(); + } } else if (n) { -- cgit v1.1 From 41602c85ac2414edfbca5c4b0ba520d47f0189ce Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 2 Nov 2022 12:52:34 +0000 Subject: libstdc++: Remove more redundant union members We don't need these 'unused' members because they're never used, and a union with a single variant member is fine. libstdc++-v3/ChangeLog: * libsupc++/eh_globals.cc (constant_init::unused): Remove. * src/c++11/system_error.cc (constant_init::unused): Remove. * src/c++17/memory_resource.cc (constant_init::unused): Remove. --- libstdc++-v3/libsupc++/eh_globals.cc | 1 - libstdc++-v3/src/c++11/system_error.cc | 1 - libstdc++-v3/src/c++17/memory_resource.cc | 1 - 3 files changed, 3 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/libsupc++/eh_globals.cc b/libstdc++-v3/libsupc++/eh_globals.cc index 0aadb69..12abfc1 100644 --- a/libstdc++-v3/libsupc++/eh_globals.cc +++ b/libstdc++-v3/libsupc++/eh_globals.cc @@ -73,7 +73,6 @@ namespace struct constant_init { union { - unsigned char unused; __cxa_eh_globals obj; }; constexpr constant_init() : obj() { } diff --git a/libstdc++-v3/src/c++11/system_error.cc b/libstdc++-v3/src/c++11/system_error.cc index 8c13642..5707e6b 100644 --- a/libstdc++-v3/src/c++11/system_error.cc +++ b/libstdc++-v3/src/c++11/system_error.cc @@ -49,7 +49,6 @@ namespace struct constant_init { union { - unsigned char unused; T obj; }; constexpr constant_init() : obj() { } diff --git a/libstdc++-v3/src/c++17/memory_resource.cc b/libstdc++-v3/src/c++17/memory_resource.cc index 8bc55a6..651d074 100644 --- a/libstdc++-v3/src/c++17/memory_resource.cc +++ b/libstdc++-v3/src/c++17/memory_resource.cc @@ -82,7 +82,6 @@ namespace pmr struct constant_init { union { - unsigned char unused; T obj; }; constexpr constant_init() : obj() { } -- cgit v1.1 From 58035eeece7894d1936db6bf0dd4f8eedd07a479 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 3 Nov 2022 00:17:32 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index dd12669..65dfc32 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,43 @@ +2022-11-02 Jonathan Wakely + + * libsupc++/eh_globals.cc (constant_init::unused): Remove. + * src/c++11/system_error.cc (constant_init::unused): Remove. + * src/c++17/memory_resource.cc (constant_init::unused): Remove. + +2022-11-02 Patrick Palka + + * src/c++17/floating_from_chars.cc (from_chars_impl): In the + ERANGE case, distinguish between a denormal result and true + underflow by checking if the return value is 0. + +2022-11-02 Jonathan Wakely + + * include/std/expected (expected::_M_invalid): Remove. + +2022-11-02 Jonathan Wakely + + * include/std/variant (__variant::_Multi_array::__untag_result): + Use pragma to suppress warning. + +2022-11-02 Jakub Jelinek + + * libsupc++/compare (_Strong_order::_Fp_fmt): Add _Bfloat16. + (_Strong_order::_Bfloat16): New static data member. + (_Strong_order::_S_fp_fmt): Return _Bfloat16 for std::bfloat16_t. + +2022-11-02 Jakub Jelinek + + * src/c++17/floating_to_chars.cc (__floating_to_chars_hex): Drop const + from unbiased_exponent. Canonicalize denormals such that they have + the leading bit set by shifting effective mantissa up and decreasing + unbiased_exponent. + (__floating_to_chars_shortest): Don't instantiate + __floating_to_chars_hex for float16_t either and use float instead. + * testsuite/20_util/to_chars/float.cc (float_to_chars_test_cases): + Adjust testcases for shortest hex denormals. + * testsuite/20_util/to_chars/double.cc (double_to_chars_test_cases): + Likewise. + 2022-11-01 Jakub Jelinek * include/std/charconv (__from_chars_float16_t, -- cgit v1.1 From 2ff0e62275b1c322a8b65f38f8336f37d31c30e4 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 3 Nov 2022 09:17:57 +0000 Subject: libstdc++: Add missing move in ranges::copy This is needed to support a move-only output iterator when the input iterators are specializations of __normal_iterator. libstdc++-v3/ChangeLog: * include/bits/ranges_algobase.h (__detail::__copy_or_move): Move output iterator. * testsuite/25_algorithms/copy/constrained.cc: Check copying to move-only output iterator. --- libstdc++-v3/include/bits/ranges_algobase.h | 2 +- .../testsuite/25_algorithms/copy/constrained.cc | 24 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index f6f0b9c..443ad52 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -239,7 +239,7 @@ namespace ranges { auto [__in,__out] = ranges::__copy_or_move<_IsMove>(__first.base(), __last.base(), - __result); + std::move(__result)); return {decltype(__first){__in}, std::move(__out)}; } else if constexpr (__is_normal_iterator<_Out>) diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc index 98f038a..444dfa7 100644 --- a/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc @@ -226,6 +226,29 @@ test06() VERIFY( ranges::equal(v, (int[]){1,2,3,0}) ); } +void +test07() +{ + struct move_only_output_iterator + { + using value_type = int; + using difference_type = short; + using iterator_category = std::output_iterator_tag; + + move_only_output_iterator() = default; + move_only_output_iterator(move_only_output_iterator&&) = default; + move_only_output_iterator& operator=(move_only_output_iterator&&) = default; + + move_only_output_iterator& operator*() { return *this; } + move_only_output_iterator& operator++() { return *this; } + move_only_output_iterator operator++(int) { return std::move(*this); } + + void operator=(int) { } + }; + + ranges::copy(std::vector{1,2,3}, move_only_output_iterator{}); +} + int main() { @@ -235,4 +258,5 @@ main() test04(); static_assert(test05()); test06(); + test07(); } -- cgit v1.1 From d29260ce806a3aa415f3642fe5720901dad78531 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 4 Nov 2022 00:17:58 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 65dfc32..61fe714 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2022-11-03 Jonathan Wakely + + * include/bits/ranges_algobase.h (__detail::__copy_or_move): + Move output iterator. + * testsuite/25_algorithms/copy/constrained.cc: Check copying to + move-only output iterator. + 2022-11-02 Jonathan Wakely * libsupc++/eh_globals.cc (constant_init::unused): Remove. -- cgit v1.1 From f505f37a8e5a7646af4038b5c46f72d8a05dc7f0 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 3 Nov 2022 11:44:47 +0000 Subject: libstdc++: Define _GNU_SOURCE for secure_getenv on Cygwin [PR107511] As in r12-6867-ge20486d508afdf we need to define _GNU_SOURCE explicitly for Cygwin, because configure finds it in libc but it isn't declared unless we request it. libstdc++-v3/ChangeLog: PR libstdc++/107511 * libsupc++/eh_alloc.cc (_GNU_SOURCE): Define. --- libstdc++-v3/libsupc++/eh_alloc.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/libsupc++/eh_alloc.cc b/libstdc++-v3/libsupc++/eh_alloc.cc index e93f14c..83d15f3 100644 --- a/libstdc++-v3/libsupc++/eh_alloc.cc +++ b/libstdc++-v3/libsupc++/eh_alloc.cc @@ -25,6 +25,11 @@ // This is derived from the C++ ABI for IA-64. Where we diverge // for cross-architecture compatibility are noted with "@@@". +#ifndef _GNU_SOURCE +// Cygwin needs this for secure_getenv +# define _GNU_SOURCE 1 +#endif + #include // std::exception #include // std::terminate #include // std::malloc, std::free, std::strtoul -- cgit v1.1 From 418999fe382c608facf57f96b53a9cb12d2fdd20 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 3 Nov 2022 11:48:57 +0000 Subject: libstdc++: Simplify lifetime of eh_globals variable [PR107500] Since this is a trivial type, we probably don't need to do anything to ensure it's still accessible after other static dtors. libstdc++-v3/ChangeLog: PR libstdc++/107500 * libsupc++/eh_globals.cc (eh_globals): Remove immortalizing wrapper. (__cxxabiv1::__cxa_get_globals_fast): Adjust. (__cxxabiv1::__cxa_get_globals): Adjust. --- libstdc++-v3/libsupc++/eh_globals.cc | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/libsupc++/eh_globals.cc b/libstdc++-v3/libsupc++/eh_globals.cc index 12abfc1..74e8a45 100644 --- a/libstdc++-v3/libsupc++/eh_globals.cc +++ b/libstdc++-v3/libsupc++/eh_globals.cc @@ -70,18 +70,8 @@ __cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW namespace { - struct constant_init - { - union { - __cxa_eh_globals obj; - }; - constexpr constant_init() : obj() { } - - ~constant_init() { /* do nothing, union member is not destroyed */ } - }; - // Single-threaded fallback buffer. - __constinit constant_init eh_globals; + __constinit __cxa_eh_globals eh_globals; } #if __GTHREADS @@ -142,7 +132,7 @@ __cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW if (init._S_init) g = static_cast<__cxa_eh_globals*>(__gthread_getspecific(init._M_key)); else - g = &eh_globals.obj; + g = &eh_globals; return g; } @@ -167,7 +157,7 @@ __cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW } } else - g = &eh_globals.obj; + g = &eh_globals; return g; } @@ -175,11 +165,11 @@ __cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW extern "C" __cxa_eh_globals* __cxxabiv1::__cxa_get_globals_fast() _GLIBCXX_NOTHROW -{ return &eh_globals.obj; } +{ return &eh_globals; } extern "C" __cxa_eh_globals* __cxxabiv1::__cxa_get_globals() _GLIBCXX_NOTHROW -{ return &eh_globals.obj; } +{ return &eh_globals; } #endif -- cgit v1.1 From 7c6008e75df80607f8104e665e0448a0a9cbf85a Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 4 Nov 2022 15:05:41 +0000 Subject: libstdc++: Do not use SFINAE for propagate_const conversions [PR107525] As the PR notes, the current conversion operators are defined as function templates so that we can use SFINAE. But this changes how they are considered for overload resolution. This moves those operators into base classes that can be specialized so the operators are obsent unless the constraints are satisfied. libstdc++-v3/ChangeLog: PR libstdc++/107525 * include/experimental/propagate_const (operator element_type*()): Move into base class that can be partially specilized to iompose constraints. (operator const element_type*()): Likewise. * testsuite/experimental/propagate_const/observers/107525.cc: New test. --- libstdc++-v3/include/experimental/propagate_const | 88 ++++++++++++++++------ .../propagate_const/observers/107525.cc | 47 ++++++++++++ 2 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 libstdc++-v3/testsuite/experimental/propagate_const/observers/107525.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/experimental/propagate_const b/libstdc++-v3/include/experimental/propagate_const index 258ef6f..12b0f27 100644 --- a/libstdc++-v3/include/experimental/propagate_const +++ b/libstdc++-v3/include/experimental/propagate_const @@ -50,6 +50,48 @@ namespace experimental { inline namespace fundamentals_v2 { + template + using __propagate_const_elem_type + = remove_reference_t())>; + + template, + bool = is_convertible::value> + struct __propagate_const_conversion_c + { }; + + template + struct __propagate_const_conversion_c<_Tp, _Elem, true> + { + constexpr operator const _Elem*() const; + }; + + template, + bool = is_convertible<_Tp, _Elem*>::value> + struct __propagate_const_conversion_nc + { }; + + template + struct __propagate_const_conversion_nc<_Tp, _Elem, true> + { + constexpr operator _Elem*(); + }; + + // Base class of propagate_const when T is a class type. + template + struct __propagate_const_conversions + : __propagate_const_conversion_c<_Tp>, __propagate_const_conversion_nc<_Tp> + { }; + + // Base class of propagate_const when T is a pointer type. + template + struct __propagate_const_conversions<_Tp*> + { + constexpr operator const _Tp*() const noexcept; + constexpr operator _Tp*() noexcept; + }; + /** * @defgroup propagate_const Const-propagating wrapper * @ingroup libfund-ts @@ -63,10 +105,10 @@ inline namespace fundamentals_v2 /// Const-propagating wrapper. template - class propagate_const + class propagate_const : public __propagate_const_conversions<_Tp> { public: - typedef remove_reference_t())> element_type; + using element_type = __propagate_const_elem_type<_Tp>; private: template @@ -186,16 +228,6 @@ inline namespace fundamentals_v2 return get(); } - template , - is_convertible<_Up, - const element_type*> - >::value, bool>::type = true> - constexpr operator const element_type*() const - { - return get(); - } - constexpr const element_type& operator*() const { return *get(); @@ -212,16 +244,6 @@ inline namespace fundamentals_v2 return get(); } - template , - is_convertible<_Up, - const element_type*> - >::value, bool>::type = true> - constexpr operator element_type*() - { - return get(); - } - constexpr element_type& operator*() { return *get(); @@ -430,6 +452,28 @@ inline namespace fundamentals_v2 return __pt._M_t; } + template + constexpr + __propagate_const_conversions<_Tp*>::operator const _Tp*() const noexcept + { return static_cast*>(this)->get(); } + + template + constexpr + __propagate_const_conversions<_Tp*>::operator _Tp*() noexcept + { return static_cast*>(this)->get(); } + + template + constexpr + __propagate_const_conversion_c<_Tp, _Elem, true>:: + operator const _Elem*() const + { return static_cast*>(this)->get(); } + + template + constexpr + __propagate_const_conversion_nc<_Tp, _Elem, true>:: + operator _Elem*() + { return static_cast*>(this)->get(); } + /// @} group propagate_const } // namespace fundamentals_v2 } // namespace experimental diff --git a/libstdc++-v3/testsuite/experimental/propagate_const/observers/107525.cc b/libstdc++-v3/testsuite/experimental/propagate_const/observers/107525.cc new file mode 100644 index 0000000..e7ecff7 --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/propagate_const/observers/107525.cc @@ -0,0 +1,47 @@ +// { dg-do run { target c++14 } } + +#include +#include + +using std::experimental::propagate_const; + +void +test_base_conversion() +{ + struct Base { }; + struct Derived : Base { }; + + static_assert(std::is_convertible, Base*>::value, + "PR libstdc++/107525 - SFINAE breaks conversion operators"); + static_assert(std::is_convertible, const Base*>::value, + "PR libstdc++/107525 - SFINAE breaks conversion operators"); +} + +void +test_const_conversion() +{ + struct X + { + int* p = nullptr; + + int& operator*() const { return *p; } + int* operator->() const { return p; } + int* get() const { return p; } + + operator int*() { return p; } + operator const int*() const = delete; + }; + + static_assert(!std::is_convertible_v, + "Cannot convert const X to const int*"); + // So should not be able to convert const propagate_const to const int*. + static_assert(!std::is_convertible_v, const int*>, + "So should not be able to convert const propagate_const to " + "const int* (although this is not what LFTSv3 says)"); +} + +int main() +{ + test_base_conversion(); + test_const_conversion(); +} -- cgit v1.1 From b83f01d0057578ebc1785f858fbfd46cdc210560 Mon Sep 17 00:00:00 2001 From: Jakob Hasse <0xjakob@users.noreply.github.com> Date: Tue, 26 Apr 2022 12:03:47 +0800 Subject: libstdc++: fix pointer type exception catch (no RTTI) [PR105387] __pbase_type_info::__do_catch(), used to catch pointer type exceptions, did not check if the type info object to compare against is a pointer type info object before doing a static down-cast to a pointer type info object. If RTTI is disabled, this leads to the following situation: Since a pointer type info object has additional fields, they would end up being undefined if the actual type info object was not a pointer type info object. A simple check has been added before the down-cast happens. Note that a consequence of this check is that exceptions of type pointer-to-member cannot be caught anymore. In case RTTI is enabled, this does not seem to be a problem because RTTI-based checks would run before and prevent running into the bad down-cast. Hence, the fix is disabled if RTTI is enabled and exceptions of type pointer-to-member can still be caught. libstdc++-v3/ChangeLog: PR libstdc++/105387 * libsupc++/pbase_type_info.cc (__do_catch) [!__cpp_rtti]: Add check that the thrown type is actually a pointer. * testsuite/18_support/105387.cc: New test. * testsuite/18_support/105387_memptr.cc: New test. Signed-off-by: Jakob Hasse --- libstdc++-v3/libsupc++/pbase_type_info.cc | 7 ++- libstdc++-v3/testsuite/18_support/105387.cc | 63 ++++++++++++++++++++++ libstdc++-v3/testsuite/18_support/105387_memptr.cc | 25 +++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/18_support/105387.cc create mode 100644 libstdc++-v3/testsuite/18_support/105387_memptr.cc (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/libsupc++/pbase_type_info.cc b/libstdc++-v3/libsupc++/pbase_type_info.cc index 7e5720b..934e049 100644 --- a/libstdc++-v3/libsupc++/pbase_type_info.cc +++ b/libstdc++-v3/libsupc++/pbase_type_info.cc @@ -74,7 +74,12 @@ __do_catch (const type_info *thr_type, // Therefore there must at least be a qualification conversion involved // But for that to be valid, our outer pointers must be const qualified. return false; - + +#if !__cpp_rtti + if (!thr_type->__is_pointer_p ()) + return false; +#endif + const __pbase_type_info *thrown_type = static_cast (thr_type); diff --git a/libstdc++-v3/testsuite/18_support/105387.cc b/libstdc++-v3/testsuite/18_support/105387.cc new file mode 100644 index 0000000..c4a2345 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/105387.cc @@ -0,0 +1,63 @@ +// { dg-do run } + +#include +#include +#include + +// Test cases for PR libstdc++/105387 + +// This test is to trigger undefined behavior if the bug 105387 is present +// in the code. Note, however, given that the bug is present, this test runs +// into undefined behavior which can also mean that it passes. +// It has been observed to fail quite reliably on x86_64-linux-gnu but only +// fail sporadically on Xtensa, depending on the code placement. +void portable_test() +{ + bool exception_thrown = false; + try { + throw std::runtime_error("test"); + } catch (const char *e) { + VERIFY(false); + } catch (const std::exception &e) { + exception_thrown = true; + } + VERIFY(exception_thrown); +} + +// This test relies on the types defined in the files typeinfo and cxxabi.h +// It is therefore less portable then the test case above but should be +// guaranteed to fail if the implementation has the bug 105387. +// +// This test case checks that __pbase_type_info::__do_catch() behaves +// correctly when called with a non-pointer type info object as argument. +// In particular, __pbase_type_info::__do_catch() should not cast +// the given type object into a pointer type and try to access the +// extended fields. + +void non_portable_test() +{ + // Create a zero-initialized buffer for allocation of the type object + unsigned char buffer [sizeof(__cxxabiv1::__fundamental_type_info) * 2] = {}; + + // Use placement-new to create the fundamental type info object in the + // first half of the buffer. Whenever that type info object will be + // casted to a pointer type info object, the extended fields of the + // pointer type info object will be in the second half of the buffer + // and hence be guaranteed zero. + __cxxabiv1::__fundamental_type_info *p_fund_info + = new(buffer) __cxxabiv1::__fundamental_type_info("fund_type"); + + __cxxabiv1::__pointer_type_info ptr_info("ptr_type", 0, p_fund_info); + + // __do_catch is declared protected in __pointer_type_info, but public in + // type_info, so we upcast it here + std::type_info *abstract_ptr_info = static_cast(&ptr_info); + VERIFY(abstract_ptr_info->__do_catch(p_fund_info, 0, 1) == false); +} + +int main() +{ + portable_test(); + non_portable_test(); + return 0; +} diff --git a/libstdc++-v3/testsuite/18_support/105387_memptr.cc b/libstdc++-v3/testsuite/18_support/105387_memptr.cc new file mode 100644 index 0000000..f5612f4 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/105387_memptr.cc @@ -0,0 +1,25 @@ +#include + +// Test related to PR libstdc++/105387 +// Check that pointer-to-member type exceptions can still be caught with -frtti. +// { dg-require-effective-target rtti } + +void test_catch_ptr_to_member() +{ + bool exception_thrown = false; + struct X { int i; }; + try { + throw &X::i; + } + catch (const int X::*) { + exception_thrown = true; + } + + VERIFY(exception_thrown); +} + +int main() +{ + test_catch_ptr_to_member(); + return 0; +} -- cgit v1.1 From 05788e9b951199e0947cf70d62feaf9d051a4b46 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 6 Nov 2022 11:05:22 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 61fe714..cda4f18 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,33 @@ +2022-11-05 Jakob Hasse <0xjakob@users.noreply.github.com> + + PR libstdc++/105387 + * libsupc++/pbase_type_info.cc (__do_catch) [!__cpp_rtti]: Add + check that the thrown type is actually a pointer. + * testsuite/18_support/105387.cc: New test. + * testsuite/18_support/105387_memptr.cc: New test. + +2022-11-05 Jonathan Wakely + + PR libstdc++/107525 + * include/experimental/propagate_const (operator element_type*()): + Move into base class that can be partially specilized to iompose + constraints. + (operator const element_type*()): Likewise. + * testsuite/experimental/propagate_const/observers/107525.cc: New test. + +2022-11-04 Jonathan Wakely + + PR libstdc++/107500 + * libsupc++/eh_globals.cc (eh_globals): Remove immortalizing + wrapper. + (__cxxabiv1::__cxa_get_globals_fast): Adjust. + (__cxxabiv1::__cxa_get_globals): Adjust. + +2022-11-04 Jonathan Wakely + + PR libstdc++/107511 + * libsupc++/eh_alloc.cc (_GNU_SOURCE): Define. + 2022-11-03 Jonathan Wakely * include/bits/ranges_algobase.h (__detail::__copy_or_move): -- cgit v1.1 From 4e4e3ffd10f53ef71696bc728ab40258751a2df4 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Sun, 6 Nov 2022 11:16:00 -0500 Subject: libstdc++: Move stream initialization into compiled library [PR44952] This patch moves the static object for constructing the standard streams out from and into the compiled library on systems that support init priorities. This'll mean no longer introduces a separate global constructor in each TU that includes it. We can do this only if the init_priority attribute is supported because we need a way to ensure the stream initialization runs first before any user global initializer, particularly when linking with a static libstdc++.a. PR libstdc++/44952 PR libstdc++/39796 PR libstdc++/98108 libstdc++-v3/ChangeLog: * include/std/iostream (__ioinit): No longer define here if the init_priority attribute is usable. * src/c++98/ios_init.cc (__ioinit): Define here instead if init_priority is usable, via ... * src/c++98/ios_base_init.h: ... this new file. --- libstdc++-v3/include/std/iostream | 4 ++++ libstdc++-v3/src/c++98/ios_base_init.h | 12 ++++++++++++ libstdc++-v3/src/c++98/ios_init.cc | 2 ++ 3 files changed, 18 insertions(+) create mode 100644 libstdc++-v3/src/c++98/ios_base_init.h (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/std/iostream b/libstdc++-v3/include/std/iostream index 70318a4..ff78e1c 100644 --- a/libstdc++-v3/include/std/iostream +++ b/libstdc++-v3/include/std/iostream @@ -73,7 +73,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ///@} // For construction of filebuffers for cout, cin, cerr, clog et. al. + // When the init_priority attribute is usable, we do this initialization + // in the compiled library instead (src/c++98/ios_init.cc). +#if !__has_attribute(__init_priority__) static ios_base::Init __ioinit; +#endif _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/src/c++98/ios_base_init.h b/libstdc++-v3/src/c++98/ios_base_init.h new file mode 100644 index 0000000..1c71038 --- /dev/null +++ b/libstdc++-v3/src/c++98/ios_base_init.h @@ -0,0 +1,12 @@ +// This is only in a header so we can use the system_header pragma, +// to suppress the warning caused by using a reserved init_priority. +#pragma GCC system_header + +// If the target supports init priorities, set up a static object in the +// compiled library to perform the initialization once and +// sufficiently early (so that it happens before any other global +// constructor when statically linking with libstdc++.a), instead of +// doing so in (each TU that includes) . +#if __has_attribute(init_priority) +static ios_base::Init __ioinit __attribute__((init_priority(90))); +#endif diff --git a/libstdc++-v3/src/c++98/ios_init.cc b/libstdc++-v3/src/c++98/ios_init.cc index 1b5132f..4016fca 100644 --- a/libstdc++-v3/src/c++98/ios_init.cc +++ b/libstdc++-v3/src/c++98/ios_init.cc @@ -75,6 +75,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION extern wostream wclog; #endif +#include "ios_base_init.h" + ios_base::Init::Init() { if (__gnu_cxx::__exchange_and_add_dispatch(&_S_refcount, 1) == 0) -- cgit v1.1 From e3b10249119fb4258fb83d21d805a04f30b63152 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Sun, 6 Nov 2022 11:30:47 -0500 Subject: libstdc++: Declare const global variables inline The changes inside the regex_constants and execution namespaces seem to be (the only) unimplemented parts of P0607R0 "Inline Variable for the Standard Library"; the rest of the changes are to implementation details. libstdc++-v3/ChangeLog: * include/bits/atomic_wait.h (_detail::__platform_wait_alignment): Declare inline. Remove redundant static specifier. (__detail::__atomic_spin_count_relax): Declare inline. (__detail::__atomic_spin_count): Likewise. * include/bits/regex_automaton.h (__detail::_S_invalid_state_id): Declare inline for C++17. Declare constexpr. Remove redundant const and static specifiers. * include/bits/regex_error.h (regex_constants::error_collate): Declare inline for C++17 as per P0607R0. (regex_constants::error_ctype): Likewise. (regex_constants::error_escape): Likewise. (regex_constants::error_backref): Likewise. (regex_constants::error_brack): Likewise. (regex_constants::error_paren): Likewise. (regex_constants::error_brace): Likewise. (regex_constants::error_badbrace): Likewise. (regex_constants::error_range): Likewise. (regex_constants::error_space): Likewise. (regex_constants::error_badrepeat): Likewise. (regex_constants::error_complexity): Likewise. (regex_constants::error_stack): Likewise. * include/ext/concurrence.h (__gnu_cxx::__default_lock_policy): Likewise. Remove redundant static specifier. * include/pstl/execution_defs.h (execution::seq): Declare inline for C++17 as per P0607R0. (execution::par): Likewise. (execution::par_unseq): Likewise. (execution::unseq): Likewise. --- libstdc++-v3/include/bits/atomic_wait.h | 8 ++++---- libstdc++-v3/include/bits/regex_automaton.h | 2 +- libstdc++-v3/include/bits/regex_error.h | 26 +++++++++++++------------- libstdc++-v3/include/ext/concurrence.h | 2 +- libstdc++-v3/include/pstl/execution_defs.h | 8 ++++---- 5 files changed, 23 insertions(+), 23 deletions(-) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h index 76ed740..bd1ed56 100644 --- a/libstdc++-v3/include/bits/atomic_wait.h +++ b/libstdc++-v3/include/bits/atomic_wait.h @@ -58,14 +58,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef _GLIBCXX_HAVE_LINUX_FUTEX #define _GLIBCXX_HAVE_PLATFORM_WAIT 1 using __platform_wait_t = int; - static constexpr size_t __platform_wait_alignment = 4; + inline constexpr size_t __platform_wait_alignment = 4; #else // define _GLIBCX_HAVE_PLATFORM_WAIT and implement __platform_wait() // and __platform_notify() if there is a more efficient primitive supported // by the platform (e.g. __ulock_wait()/__ulock_wake()) which is better than // a mutex/condvar based wait. using __platform_wait_t = uint64_t; - static constexpr size_t __platform_wait_alignment + inline constexpr size_t __platform_wait_alignment = __alignof__(__platform_wait_t); #endif } // namespace __detail @@ -142,8 +142,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif } - constexpr auto __atomic_spin_count_relax = 12; - constexpr auto __atomic_spin_count = 16; + inline constexpr auto __atomic_spin_count_relax = 12; + inline constexpr auto __atomic_spin_count = 16; struct __default_spin_policy { diff --git a/libstdc++-v3/include/bits/regex_automaton.h b/libstdc++-v3/include/bits/regex_automaton.h index f95eb7d..44bde42 100644 --- a/libstdc++-v3/include/bits/regex_automaton.h +++ b/libstdc++-v3/include/bits/regex_automaton.h @@ -46,7 +46,7 @@ namespace __detail */ typedef long _StateIdT; - static const _StateIdT _S_invalid_state_id = -1; + _GLIBCXX17_INLINE constexpr _StateIdT _S_invalid_state_id = -1; template using _Matcher = std::function; diff --git a/libstdc++-v3/include/bits/regex_error.h b/libstdc++-v3/include/bits/regex_error.h index 74a1428..ab20765 100644 --- a/libstdc++-v3/include/bits/regex_error.h +++ b/libstdc++-v3/include/bits/regex_error.h @@ -66,60 +66,60 @@ namespace regex_constants }; /** The expression contained an invalid collating element name. */ - constexpr error_type error_collate(_S_error_collate); + _GLIBCXX17_INLINE constexpr error_type error_collate(_S_error_collate); /** The expression contained an invalid character class name. */ - constexpr error_type error_ctype(_S_error_ctype); + _GLIBCXX17_INLINE constexpr error_type error_ctype(_S_error_ctype); /** * The expression contained an invalid escaped character, or a trailing * escape. */ - constexpr error_type error_escape(_S_error_escape); + _GLIBCXX17_INLINE constexpr error_type error_escape(_S_error_escape); /** The expression contained an invalid back reference. */ - constexpr error_type error_backref(_S_error_backref); + _GLIBCXX17_INLINE constexpr error_type error_backref(_S_error_backref); /** The expression contained mismatched [ and ]. */ - constexpr error_type error_brack(_S_error_brack); + _GLIBCXX17_INLINE constexpr error_type error_brack(_S_error_brack); /** The expression contained mismatched ( and ). */ - constexpr error_type error_paren(_S_error_paren); + _GLIBCXX17_INLINE constexpr error_type error_paren(_S_error_paren); /** The expression contained mismatched { and } */ - constexpr error_type error_brace(_S_error_brace); + _GLIBCXX17_INLINE constexpr error_type error_brace(_S_error_brace); /** The expression contained an invalid range in a {} expression. */ - constexpr error_type error_badbrace(_S_error_badbrace); + _GLIBCXX17_INLINE constexpr error_type error_badbrace(_S_error_badbrace); /** * The expression contained an invalid character range, * such as [b-a] in most encodings. */ - constexpr error_type error_range(_S_error_range); + _GLIBCXX17_INLINE constexpr error_type error_range(_S_error_range); /** * There was insufficient memory to convert the expression into a * finite state machine. */ - constexpr error_type error_space(_S_error_space); + _GLIBCXX17_INLINE constexpr error_type error_space(_S_error_space); /** * One of *?+{ was not preceded by a valid regular expression. */ - constexpr error_type error_badrepeat(_S_error_badrepeat); + _GLIBCXX17_INLINE constexpr error_type error_badrepeat(_S_error_badrepeat); /** * The complexity of an attempted match against a regular expression * exceeded a pre-set level. */ - constexpr error_type error_complexity(_S_error_complexity); + _GLIBCXX17_INLINE constexpr error_type error_complexity(_S_error_complexity); /** * There was insufficient memory to determine whether the * regular expression could match the specified character sequence. */ - constexpr error_type error_stack(_S_error_stack); + _GLIBCXX17_INLINE constexpr error_type error_stack(_S_error_stack); ///@} } // namespace regex_constants diff --git a/libstdc++-v3/include/ext/concurrence.h b/libstdc++-v3/include/ext/concurrence.h index aea861b..7fd8149 100644 --- a/libstdc++-v3/include/ext/concurrence.h +++ b/libstdc++-v3/include/ext/concurrence.h @@ -50,7 +50,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Compile time constant that indicates prefered locking policy in // the current configuration. - static const _Lock_policy __default_lock_policy = + _GLIBCXX17_INLINE const _Lock_policy __default_lock_policy = #ifndef __GTHREADS _S_single; #elif defined _GLIBCXX_HAVE_ATOMIC_LOCK_POLICY diff --git a/libstdc++-v3/include/pstl/execution_defs.h b/libstdc++-v3/include/pstl/execution_defs.h index 13b0029..3eca558 100644 --- a/libstdc++-v3/include/pstl/execution_defs.h +++ b/libstdc++-v3/include/pstl/execution_defs.h @@ -107,10 +107,10 @@ class unsequenced_policy }; // 2.8, Execution policy objects -constexpr sequenced_policy seq{}; -constexpr parallel_policy par{}; -constexpr parallel_unsequenced_policy par_unseq{}; -constexpr unsequenced_policy unseq{}; +_GLIBCXX17_INLINE constexpr sequenced_policy seq{}; +_GLIBCXX17_INLINE constexpr parallel_policy par{}; +_GLIBCXX17_INLINE constexpr parallel_unsequenced_policy par_unseq{}; +_GLIBCXX17_INLINE constexpr unsequenced_policy unseq{}; // 2.3, Execution policy type trait template -- cgit v1.1 From 3c67c15d839a8237912311a0f974fef48580edff Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 7 Nov 2022 00:16:42 +0000 Subject: Daily bump. --- libstdc++-v3/ChangeLog | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'libstdc++-v3') diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index cda4f18..fe27057 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,45 @@ +2022-11-06 Patrick Palka + + * include/bits/atomic_wait.h (_detail::__platform_wait_alignment): + Declare inline. Remove redundant static specifier. + (__detail::__atomic_spin_count_relax): Declare inline. + (__detail::__atomic_spin_count): Likewise. + * include/bits/regex_automaton.h (__detail::_S_invalid_state_id): + Declare inline for C++17. Declare constexpr. Remove + redundant const and static specifiers. + * include/bits/regex_error.h (regex_constants::error_collate): + Declare inline for C++17 as per P0607R0. + (regex_constants::error_ctype): Likewise. + (regex_constants::error_escape): Likewise. + (regex_constants::error_backref): Likewise. + (regex_constants::error_brack): Likewise. + (regex_constants::error_paren): Likewise. + (regex_constants::error_brace): Likewise. + (regex_constants::error_badbrace): Likewise. + (regex_constants::error_range): Likewise. + (regex_constants::error_space): Likewise. + (regex_constants::error_badrepeat): Likewise. + (regex_constants::error_complexity): Likewise. + (regex_constants::error_stack): Likewise. + * include/ext/concurrence.h (__gnu_cxx::__default_lock_policy): + Likewise. Remove redundant static specifier. + * include/pstl/execution_defs.h (execution::seq): Declare inline + for C++17 as per P0607R0. + (execution::par): Likewise. + (execution::par_unseq): Likewise. + (execution::unseq): Likewise. + +2022-11-06 Patrick Palka + + PR libstdc++/44952 + PR libstdc++/39796 + PR libstdc++/98108 + * include/std/iostream (__ioinit): No longer define here if + the init_priority attribute is usable. + * src/c++98/ios_init.cc (__ioinit): Define here instead if + init_priority is usable, via ... + * src/c++98/ios_base_init.h: ... this new file. + 2022-11-05 Jakob Hasse <0xjakob@users.noreply.github.com> PR libstdc++/105387 -- cgit v1.1