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 ++- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'libstdc++-v3/include') 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) -- 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/include/Makefile.in | 1 - 1 file changed, 1 deletion(-) (limited to 'libstdc++-v3/include') 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 \ -- 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/include') 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/include') 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 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/include/c_global/cmath | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'libstdc++-v3/include') 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 -- 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 +++++++++++++++++++++++++++- 2 files changed, 684 insertions(+), 2 deletions(-) (limited to 'libstdc++-v3/include') 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) -- 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 ++++++++++++++++++++ 3 files changed, 219 insertions(+) (limited to 'libstdc++-v3/include') 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. -- 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/include/std/charconv | 44 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'libstdc++-v3/include') 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 -- 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/include/std/charconv | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'libstdc++-v3/include') 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 -- 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/include') 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/include') 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 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'libstdc++-v3/include') 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>) -- 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 +++++++++++++++++------ 1 file changed, 66 insertions(+), 22 deletions(-) (limited to 'libstdc++-v3/include') 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 -- 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 ++++ 1 file changed, 4 insertions(+) (limited to 'libstdc++-v3/include') 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 -- 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/include') 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