On Tue, 11 Mar 2025 at 12:22, Tomasz Kamiński wrote:
>
> Floating points types _Float16, _Float32, _Float64, and bfloat16,
> can be formatted only if std::to_chars overloads for such types
> where provided. Currently this is only the case for architectures

Spelling: "were provided"

With that fixed, OK for trunk, thanks for noticing this.

I think we also want this on the gcc-14 and gcc-13 branches, but after
it's sat on trunk for a while.

> 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.
> ---
> Tested on x86_64-linux. OK for trunk?
>
>  libstdc++-v3/include/std/format | 32 ++++++++------------------------
>  1 file changed, 8 insertions(+), 24 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
> index e7e0d2d142b..1809f040077 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;
> --
> 2.48.1
>

Reply via email to