commit 57b9e2227c7b14f04f2593ec41e177631b6f3fc2 Author: Jonathan Wakely Date: Wed Mar 16 16:46:07 2022 libstdc++: Prefer our own __floating_from_chars_hex if supported This adjust the floating-point overloads of std::from_chars so that they prefer to use __floating_from_chars_hex if possible, instead of using strtof/strtod/strtold. This avoids changing the per-thread C locale and allocating memory for a null-terminated string when we can use the hex-specific function instead. libstdc++-v3/ChangeLog: * src/c++17/floating_from_chars.cc (from_chars): Always use __floating_from_chars_hex for hex format if possible. diff --git a/libstdc++-v3/src/c++17/floating_from_chars.cc b/libstdc++-v3/src/c++17/floating_from_chars.cc index 4aa2483bc28..ce30752ee95 100644 --- a/libstdc++-v3/src/c++17/floating_from_chars.cc +++ b/libstdc++-v3/src/c++17/floating_from_chars.cc @@ -821,13 +821,12 @@ from_chars_result from_chars(const char* first, const char* last, float& value, chars_format fmt) noexcept { -#if USE_LIB_FAST_FLOAT +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 if (fmt == chars_format::hex) return __floating_from_chars_hex(first, last, value); - else - { - return fast_float::from_chars(first, last, value, fmt); - } +#endif +#if USE_LIB_FAST_FLOAT + return fast_float::from_chars(first, last, value, fmt); #else return from_chars_strtod(first, last, value, fmt); #endif @@ -837,13 +836,12 @@ from_chars_result from_chars(const char* first, const char* last, double& value, chars_format fmt) noexcept { -#if USE_LIB_FAST_FLOAT +#if _GLIBCXX_FLOAT_IS_IEEE_BINARY32 && _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 if (fmt == chars_format::hex) return __floating_from_chars_hex(first, last, value); - else - { - return fast_float::from_chars(first, last, value, fmt); - } +#endif +#if USE_LIB_FAST_FLOAT + return fast_float::from_chars(first, last, value, fmt); #else return from_chars_strtod(first, last, value, fmt); #endif @@ -853,18 +851,12 @@ from_chars_result from_chars(const char* first, const char* last, long double& value, chars_format fmt) noexcept { -#if ! USE_STRTOD_FOR_FROM_CHARS +#if ! USE_STRTOD_FOR_FROM_CHARS || __LDBL_MANT_DIG__ == __DBL_MANT_DIG__ // Either long double is the same as double, or we can't use strtold. // In the latter case, this might give an incorrect result (e.g. values // out of range of double give an error, even if they fit in long double). double dbl_value; - from_chars_result result; - 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); - } + from_chars_result result = std::from_chars(first, last, dbl_value, fmt); if (result.ec == errc{}) value = dbl_value; return result; @@ -888,7 +880,8 @@ from_chars_result from_chars(const char* first, const char* last, __ieee128& value, chars_format fmt) noexcept { - // fast_float doesn't support IEEE binary128 format, but we can use strtold. + // fast_float doesn't support IEEE binary128 format, and neither does our + // __floating_from_chars_hex, but we can use __strtoieee128 on this target. return from_chars_strtod(first, last, value, fmt); } #endif