diff options
author | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-03-11 11:59:36 +0100 |
---|---|---|
committer | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-03-12 13:09:20 +0100 |
commit | 445128c12cf22081223f7385196ee3889ef4c4b2 (patch) | |
tree | 6723bef366fa29186d753ccd8c216af11bfc8e69 | |
parent | 2ac842a1e82efc6e4e4d21f880c9888c523788e7 (diff) | |
download | gcc-445128c12cf22081223f7385196ee3889ef4c4b2.zip gcc-445128c12cf22081223f7385196ee3889ef4c4b2.tar.gz gcc-445128c12cf22081223f7385196ee3889ef4c4b2.tar.bz2 |
libstdc++: Correct preprocessing checks for floatX_t and bfloat_16 formatting
Floating points types _Float16, _Float32, _Float64, and bfloat16,
can be formatted only if std::to_chars overloads for such types
were provided. Currently this is only the case for architectures
where float and double are 32-bits and 64-bits IEEE floating points types.
This patch updates the preprocessing checks for formatters
for above types to check _GLIBCXX_FLOAT_IS_IEEE_BINARY32
and _GLIBCXX_DOUBLE_IS_IEEE_BINARY64. Making them non-formattable
on non-IEEE architectures.
Remove a potential UB, where we could produce basic_format_arg
with _M_type set to _Arg_fp32 or _Arg_fp64, that was later not
handled by `_M_visit`.
libstdc++-v3/ChangeLog:
* include/std/format (formatter<_Float16, _CharT>): Define only if
_GLIBCXX_FLOAT_IS_IEEE_BINARY32 macro is defined.
(formatter<_Float16, _CharT>): As above.
(formatter<__gnu_cxx::__bfloat16_t, _CharT>): As above.
(formatter<_Float64, _CharT>): Define only if
_GLIBCXX_DOUBLE_IS_IEEE_BINARY64 is defined.
(basic_format_arg::_S_to_arg_type): Normalize _Float32 and _Float64
only to float and double respectivelly.
(basic_format_arg::_S_to_enum): Remove handling of _Float32 and _Float64.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
-rw-r--r-- | libstdc++-v3/include/std/format | 32 |
1 files changed, 8 insertions, 24 deletions
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 0d6cc7f..6cfc84c 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -2276,7 +2276,7 @@ namespace __format }; #endif -#ifdef __STDCPP_FLOAT16_T__ +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) // Reuse __formatter_fp<C>::format<float, Out> for _Float16. template<__format::__char _CharT> struct formatter<_Float16, _CharT> @@ -2298,7 +2298,7 @@ namespace __format }; #endif -#if defined(__FLT32_DIG__) +#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) // Reuse __formatter_fp<C>::format<float, Out> for _Float32. template<__format::__char _CharT> struct formatter<_Float32, _CharT> @@ -2320,7 +2320,7 @@ namespace __format }; #endif -#if defined(__FLT64_DIG__) +#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) // Reuse __formatter_fp<C>::format<double, Out> for _Float64. template<__format::__char _CharT> struct formatter<_Float64, _CharT> @@ -2364,7 +2364,7 @@ namespace __format }; #endif -#ifdef __STDCPP_BFLOAT16_T__ +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) // Reuse __formatter_fp<C>::format<float, Out> for bfloat16_t. template<__format::__char _CharT> struct formatter<__gnu_cxx::__bfloat16_t, _CharT> @@ -3443,22 +3443,16 @@ namespace __format return type_identity<float>(); #endif -#ifdef __FLT32_DIG__ +#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) else if constexpr (is_same_v<_Td, _Float32>) -# ifdef _GLIBCXX_FLOAT_IS_IEEE_BINARY32 return type_identity<float>(); -# else - return type_identity<_Float32>(); -# endif #endif -#ifdef __FLT64_DIG__ + +#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) else if constexpr (is_same_v<_Td, _Float64>) -# ifdef _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 return type_identity<double>(); -# else - return type_identity<_Float64>(); -# endif #endif + #if _GLIBCXX_FORMAT_F128 # if __FLT128_DIG__ else if constexpr (is_same_v<_Td, _Float128>) @@ -3538,16 +3532,6 @@ namespace __format return _Arg_u128; #endif - // N.B. some of these types will never actually be used here, - // because they get normalized to a standard floating-point type. -#if defined __FLT32_DIG__ && ! _GLIBCXX_FLOAT_IS_IEEE_BINARY32 - else if constexpr (is_same_v<_Tp, _Float32>) - return _Arg_f32; -#endif -#if defined __FLT64_DIG__ && ! _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 - else if constexpr (is_same_v<_Tp, _Float64>) - return _Arg_f64; -#endif #if _GLIBCXX_FORMAT_F128 == 2 else if constexpr (is_same_v<_Tp, __format::__float128_t>) return _Arg_f128; |