https://gcc.gnu.org/g:445128c12cf22081223f7385196ee3889ef4c4b2

commit r15-7995-g445128c12cf22081223f7385196ee3889ef4c4b2
Author: Tomasz Kamiński <tkami...@redhat.com>
Date:   Tue Mar 11 11:59:36 2025 +0100

    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 <jwak...@redhat.com>
    Signed-off-by: Tomasz Kamiński <tkami...@redhat.com>

Diff:
---
 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 0d6cc7f6bef4..6cfc84cd01b7 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;

Reply via email to