[libc-commits] [libc] [libc] Fix strfromf handling inf/nan. (PR #225805)

Alex Strelnikov via libc-commits libc-commits at lists.llvm.org
Fri Sep 25 07:41:52 PDT 2026


https://github.com/strel-12 updated https://github.com/llvm/llvm-project/pull/225805

>From c46e4e91650f058a64eb791b4f55b6d5ba3cb826 Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Wed, 23 Sep 2026 14:11:20 +0000
Subject: [PATCH 1/4] Fix str_from_util handling inf/nan, and enable
 strfromf128.

---
 .../printf_core/float_dec_converter.h         |  85 +++++++----
 .../printf_core/float_dec_converter_limited.h |  50 ++++---
 .../printf_core/float_hex_converter.h         | 136 ++++++++++--------
 .../printf_core/float_inf_nan_converter.h     |  32 +----
 libc/src/stdlib/str_from_util.h               |  82 +++++------
 libc/src/stdlib/strfromd.cpp                  |  10 +-
 libc/src/stdlib/strfromf.cpp                  |  10 +-
 libc/src/stdlib/strfroml.cpp                  |  16 +--
 libc/test/src/stdlib/strfromf_test.cpp        |   3 -
 9 files changed, 211 insertions(+), 213 deletions(-)

diff --git a/libc/src/__support/printf_core/float_dec_converter.h b/libc/src/__support/printf_core/float_dec_converter.h
index 89ea766e72f0a..974765a9667fe 100644
--- a/libc/src/__support/printf_core/float_dec_converter.h
+++ b/libc/src/__support/printf_core/float_dec_converter.h
@@ -489,9 +489,10 @@ FloatWriter(Writer<mode>, bool, const PaddingWriter<mode>) -> FloatWriter<mode>;
 // https://doi.org/10.1145/3360595
 template <typename T, OverflowMode mode,
           cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE int convert_float_decimal_typed(Writer<mode> *writer,
-                                            const FormatSection &to_conv,
-                                            fputil::FPBits<T> float_bits) {
+LIBC_INLINE int
+convert_finite_float_decimal_typed(Writer<mode> *writer,
+                                   const FormatSection &to_conv,
+                                   fputil::FPBits<T> float_bits) {
   // signed because later we use -FRACTION_LEN
   constexpr int32_t FRACTION_LEN = fputil::FPBits<T>::FRACTION_LEN;
   int exponent = float_bits.get_explicit_exponent();
@@ -599,9 +600,10 @@ LIBC_INLINE int convert_float_decimal_typed(Writer<mode> *writer,
 
 template <typename T, OverflowMode mode,
           cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE int convert_float_dec_exp_typed(Writer<mode> *writer,
-                                            const FormatSection &to_conv,
-                                            fputil::FPBits<T> float_bits) {
+LIBC_INLINE int
+convert_finite_float_dec_exp_typed(Writer<mode> *writer,
+                                   const FormatSection &to_conv,
+                                   fputil::FPBits<T> float_bits) {
   // signed because later we use -FRACTION_LEN
   constexpr int32_t FRACTION_LEN = fputil::FPBits<T>::FRACTION_LEN;
   int exponent = float_bits.get_explicit_exponent();
@@ -760,9 +762,10 @@ LIBC_INLINE int convert_float_dec_exp_typed(Writer<mode> *writer,
 
 template <typename T, OverflowMode mode,
           cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE int convert_float_dec_auto_typed(Writer<mode> *writer,
-                                             const FormatSection &to_conv,
-                                             fputil::FPBits<T> float_bits) {
+LIBC_INLINE int
+convert_finite_float_dec_auto_typed(Writer<mode> *writer,
+                                    const FormatSection &to_conv,
+                                    fputil::FPBits<T> float_bits) {
   // signed because later we use -FRACTION_LEN
   constexpr int32_t FRACTION_LEN = fputil::FPBits<T>::FRACTION_LEN;
   int exponent = float_bits.get_explicit_exponent();
@@ -818,7 +821,7 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer<mode> *writer,
     } else {
       new_conv.precision = 0;
     }
-    return convert_float_decimal_typed<T>(writer, new_conv, float_bits);
+    return convert_finite_float_decimal_typed<T>(writer, new_conv, float_bits);
   }
 
   const size_t block_width = IntegerToString<intmax_t>(digits).size();
@@ -1100,7 +1103,7 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer<mode> *writer,
                                : trimmed_precision;
     }
 
-    return convert_float_decimal_typed<T>(writer, new_conv, float_bits);
+    return convert_finite_float_decimal_typed<T>(writer, new_conv, float_bits);
   } else {
     // otherwise, the conversion is with style e (or E) and precision equals
     // P - 1
@@ -1120,7 +1123,7 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer<mode> *writer,
                                ? conv_precision
                                : trimmed_precision;
     }
-    return convert_float_dec_exp_typed<T>(writer, new_conv, float_bits);
+    return convert_finite_float_dec_exp_typed<T>(writer, new_conv, float_bits);
   }
 }
 
@@ -1129,13 +1132,17 @@ LIBC_INLINE int convert_float_dec_auto_typed(Writer<mode> *writer,
 template <OverflowMode mode>
 LIBC_INLINE int convert_float_decimal(Writer<mode> *writer,
                                       const FormatSection &to_conv) {
+  InfNanFPBitsProperties inf_nan_properties;
 #if defined(LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128)
   if (to_conv.length_modifier == LengthModifier::Q) {
     fputil::FPBits<float128>::StorageType float_raw = to_conv.conv_val_raw;
     fputil::FPBits<float128> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_decimal_typed<float128>(writer, to_conv, float_bits);
+      return convert_finite_float_decimal_typed<float128>(writer, to_conv,
+                                                          float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   } else
 #endif // LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128
 #ifndef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
@@ -1145,9 +1152,11 @@ LIBC_INLINE int convert_float_decimal(Writer<mode> *writer,
             to_conv.conv_val_raw);
     fputil::FPBits<long double> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_decimal_typed<long double>(writer, to_conv,
-                                                      float_bits);
+      return convert_finite_float_decimal_typed<long double>(writer, to_conv,
+                                                             float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   } else
 #endif // !LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
   {
@@ -1155,23 +1164,30 @@ LIBC_INLINE int convert_float_decimal(Writer<mode> *writer,
         static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw);
     fputil::FPBits<double> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_decimal_typed<double>(writer, to_conv, float_bits);
+      return convert_finite_float_decimal_typed<double>(writer, to_conv,
+                                                        float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   }
 
-  return convert_inf_nan(writer, to_conv);
+  return convert_inf_nan(writer, inf_nan_properties, to_conv);
 }
 
 template <OverflowMode mode>
 LIBC_INLINE int convert_float_dec_exp(Writer<mode> *writer,
                                       const FormatSection &to_conv) {
+  InfNanFPBitsProperties inf_nan_properties;
 #if defined(LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128)
   if (to_conv.length_modifier == LengthModifier::Q) {
     fputil::FPBits<float128>::StorageType float_raw = to_conv.conv_val_raw;
     fputil::FPBits<float128> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_dec_exp_typed<float128>(writer, to_conv, float_bits);
+      return convert_finite_float_dec_exp_typed<float128>(writer, to_conv,
+                                                          float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   } else
 #endif // LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128
 #ifndef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
@@ -1181,9 +1197,11 @@ LIBC_INLINE int convert_float_dec_exp(Writer<mode> *writer,
             to_conv.conv_val_raw);
     fputil::FPBits<long double> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_dec_exp_typed<long double>(writer, to_conv,
-                                                      float_bits);
+      return convert_finite_float_dec_exp_typed<long double>(writer, to_conv,
+                                                             float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   } else
 #endif // !LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
   {
@@ -1191,24 +1209,30 @@ LIBC_INLINE int convert_float_dec_exp(Writer<mode> *writer,
         static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw);
     fputil::FPBits<double> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_dec_exp_typed<double>(writer, to_conv, float_bits);
+      return convert_finite_float_dec_exp_typed<double>(writer, to_conv,
+                                                        float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   }
 
-  return convert_inf_nan(writer, to_conv);
+  return convert_inf_nan(writer, inf_nan_properties, to_conv);
 }
 
 template <OverflowMode mode>
 LIBC_INLINE int convert_float_dec_auto(Writer<mode> *writer,
                                        const FormatSection &to_conv) {
+  InfNanFPBitsProperties inf_nan_properties;
 #if defined(LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128)
   if (to_conv.length_modifier == LengthModifier::Q) {
     fputil::FPBits<float128>::StorageType float_raw = to_conv.conv_val_raw;
     fputil::FPBits<float128> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_dec_auto_typed<float128>(writer, to_conv,
-                                                    float_bits);
+      return convert_finite_float_dec_auto_typed<float128>(writer, to_conv,
+                                                           float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   } else
 #endif // LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128
 #ifndef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
@@ -1218,9 +1242,11 @@ LIBC_INLINE int convert_float_dec_auto(Writer<mode> *writer,
             to_conv.conv_val_raw);
     fputil::FPBits<long double> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_dec_auto_typed<long double>(writer, to_conv,
-                                                       float_bits);
+      return convert_finite_float_dec_auto_typed<long double>(writer, to_conv,
+                                                              float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   } else
 #endif // !LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
   {
@@ -1228,11 +1254,14 @@ LIBC_INLINE int convert_float_dec_auto(Writer<mode> *writer,
         static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw);
     fputil::FPBits<double> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_dec_auto_typed<double>(writer, to_conv, float_bits);
+      return convert_finite_float_dec_auto_typed<double>(writer, to_conv,
+                                                         float_bits);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   }
 
-  return convert_inf_nan(writer, to_conv);
+  return convert_inf_nan(writer, inf_nan_properties, to_conv);
 }
 
 } // namespace printf_core
diff --git a/libc/src/__support/printf_core/float_dec_converter_limited.h b/libc/src/__support/printf_core/float_dec_converter_limited.h
index 7aa886db37a3d..36bdba67e9f31 100644
--- a/libc/src/__support/printf_core/float_dec_converter_limited.h
+++ b/libc/src/__support/printf_core/float_dec_converter_limited.h
@@ -375,11 +375,11 @@ DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
 }
 
 template <OverflowMode mode>
-LIBC_INLINE int convert_float_inner(Writer<mode> *writer,
-                                    const FormatSection &to_conv,
-                                    int32_t fraction_len, int exponent,
-                                    AnyFloatStorageType mantissa, Sign sign,
-                                    ConversionType ctype) {
+LIBC_INLINE int convert_finite_float_inner(Writer<mode> *writer,
+                                           const FormatSection &to_conv,
+                                           int32_t fraction_len, int exponent,
+                                           AnyFloatStorageType mantissa,
+                                           Sign sign, ConversionType ctype) {
   constexpr char DECIMAL_POINT = '.';
   // If to_conv doesn't specify a precision, the precision defaults to 6.
   unsigned precision = to_conv.precision < 0 ? 6 : to_conv.precision;
@@ -621,26 +621,30 @@ LIBC_INLINE int convert_float_inner(Writer<mode> *writer,
 template <typename T, OverflowMode mode,
           cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
 LIBC_INLINE int
-convert_float_typed(Writer<mode> *writer, const FormatSection &to_conv,
-                    fputil::FPBits<T> float_bits, ConversionType ctype) {
-  return convert_float_inner(writer, to_conv, float_bits.FRACTION_LEN,
-                             float_bits.get_explicit_exponent(),
-                             float_bits.get_explicit_mantissa(),
-                             float_bits.sign(), ctype);
+convert_finite_float_typed(Writer<mode> *writer, const FormatSection &to_conv,
+                           fputil::FPBits<T> float_bits, ConversionType ctype) {
+  return convert_finite_float_inner(writer, to_conv, float_bits.FRACTION_LEN,
+                                    float_bits.get_explicit_exponent(),
+                                    float_bits.get_explicit_mantissa(),
+                                    float_bits.sign(), ctype);
 }
 
 template <OverflowMode mode>
 LIBC_INLINE int convert_float_outer(Writer<mode> *writer,
                                     const FormatSection &to_conv,
                                     ConversionType ctype) {
+  InfNanFPBitsProperties inf_nan_properties;
 #if defined(LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128)
   if (to_conv.length_modifier == LengthModifier::Q) {
     fputil::FPBits<float128> float_bits(
         static_cast<fputil::FPBits<float128>::StorageType>(
             to_conv.conv_val_raw));
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_typed<float128>(writer, to_conv, float_bits, ctype);
+      return convert_finite_float_typed<float128>(writer, to_conv, float_bits,
+                                                  ctype);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   } else
 #endif // LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128
 #ifndef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
@@ -649,9 +653,11 @@ LIBC_INLINE int convert_float_outer(Writer<mode> *writer,
         static_cast<fputil::FPBits<long double>::StorageType>(
             to_conv.conv_val_raw));
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_typed<long double>(writer, to_conv, float_bits,
-                                              ctype);
+      return convert_finite_float_typed<long double>(writer, to_conv,
+                                                     float_bits, ctype);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   } else
 #endif // !LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
   {
@@ -659,11 +665,14 @@ LIBC_INLINE int convert_float_outer(Writer<mode> *writer,
         static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw);
     fputil::FPBits<double> float_bits(float_raw);
     if (!float_bits.is_inf_or_nan()) {
-      return convert_float_typed<double>(writer, to_conv, float_bits, ctype);
+      return convert_finite_float_typed<double>(writer, to_conv, float_bits,
+                                                ctype);
     }
+    inf_nan_properties = {.is_negative = float_bits.is_neg(),
+                          .mantissa_is_zero = float_bits.get_mantissa() == 0};
   }
 
-  return convert_inf_nan(writer, to_conv);
+  return convert_inf_nan(writer, inf_nan_properties, to_conv);
 }
 
 template <typename T, OverflowMode mode,
@@ -671,7 +680,8 @@ template <typename T, OverflowMode mode,
 LIBC_INLINE int convert_float_decimal_typed(Writer<mode> *writer,
                                             const FormatSection &to_conv,
                                             fputil::FPBits<T> float_bits) {
-  return convert_float_typed<T>(writer, to_conv, float_bits, ConversionType::F);
+  return convert_finite_float_typed<T>(writer, to_conv, float_bits,
+                                       ConversionType::F);
 }
 
 template <typename T, OverflowMode mode,
@@ -679,7 +689,8 @@ template <typename T, OverflowMode mode,
 LIBC_INLINE int convert_float_dec_exp_typed(Writer<mode> *writer,
                                             const FormatSection &to_conv,
                                             fputil::FPBits<T> float_bits) {
-  return convert_float_typed<T>(writer, to_conv, float_bits, ConversionType::E);
+  return convert_finite_float_typed<T>(writer, to_conv, float_bits,
+                                       ConversionType::E);
 }
 
 template <typename T, OverflowMode mode,
@@ -687,7 +698,8 @@ template <typename T, OverflowMode mode,
 LIBC_INLINE int convert_float_dec_auto_typed(Writer<mode> *writer,
                                              const FormatSection &to_conv,
                                              fputil::FPBits<T> float_bits) {
-  return convert_float_typed<T>(writer, to_conv, float_bits, ConversionType::G);
+  return convert_finite_float_typed<T>(writer, to_conv, float_bits,
+                                       ConversionType::G);
 }
 
 template <OverflowMode mode>
diff --git a/libc/src/__support/printf_core/float_hex_converter.h b/libc/src/__support/printf_core/float_hex_converter.h
index 15f3d9f05a127..ee751901dda1e 100644
--- a/libc/src/__support/printf_core/float_hex_converter.h
+++ b/libc/src/__support/printf_core/float_hex_converter.h
@@ -26,30 +26,53 @@ namespace LIBC_NAMESPACE_DECL {
 namespace printf_core {
 
 struct FloatHexExpFPBitsProperties {
-  bool is_negative;
-  int exponent;
   AnyFloatStorageType mantissa;
-  bool is_inf_or_nan;
+  int exponent;
   uint32_t fraction_bits;
+  bool is_negative;
+  bool is_inf_or_nan;
+  bool mantissa_is_zero;
 };
 
 template <typename T>
-FloatHexExpFPBitsProperties
-get_float_hex_exp_fp_bits_properties(AnyFloatStorageType float_raw) {
-  fputil::FPBits<T> float_bits(
-      static_cast<typename fputil::FPBits<T>::StorageType>(float_raw));
+LIBC_INLINE FloatHexExpFPBitsProperties
+get_float_hex_exp_fp_bits_properties_typed(fputil::FPBits<T> float_bits) {
   return {
-      .is_negative = float_bits.is_neg(),
-      .exponent = float_bits.get_explicit_exponent(),
       .mantissa = float_bits.get_explicit_mantissa(),
-      .is_inf_or_nan = float_bits.is_inf_or_nan(),
+      .exponent = float_bits.get_explicit_exponent(),
       .fraction_bits = fputil::FPBits<T>::FRACTION_LEN,
+      .is_negative = float_bits.is_neg(),
+      .is_inf_or_nan = float_bits.is_inf_or_nan(),
+      .mantissa_is_zero = float_bits.get_mantissa() == 0,
   };
 }
 
+// Returns relevant floating point properties for conversion using
+// `to_conv.length_modifier` to infer the conversion value type.
+LIBC_INLINE FloatHexExpFPBitsProperties
+get_float_hex_exp_fp_bits_properties_lm(const FormatSection &to_conv) {
+#if defined(LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128)
+  if (to_conv.length_modifier == LengthModifier::Q)
+    return get_float_hex_exp_fp_bits_properties_typed<float128>(
+        fputil::FPBits<float128>(to_conv.conv_val_raw));
+#endif // LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128
+#ifndef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
+  if (to_conv.length_modifier == LengthModifier::L)
+    return get_float_hex_exp_fp_bits_properties_typed<long double>(
+        fputil::FPBits<long double>(
+            static_cast<fputil::FPBits<long double>::StorageType>(
+                to_conv.conv_val_raw)));
+#endif // !LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
+  return get_float_hex_exp_fp_bits_properties_typed<double>(
+      fputil::FPBits<double>(static_cast<fputil::FPBits<double>::StorageType>(
+          to_conv.conv_val_raw)));
+}
+
 template <OverflowMode mode>
-LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
-                                      const FormatSection &to_conv) {
+LIBC_INLINE int
+convert_finite_float_hex_exp(Writer<mode> *writer,
+                             FloatHexExpFPBitsProperties fp_bits_properties,
+                             const FormatSection &to_conv) {
 #if defined(LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128)
   static constexpr uint32_t MAX_POSSIBLE_FRACTION_LEN =
       fputil::FPBits<float128>::FRACTION_LEN;
@@ -67,30 +90,9 @@ LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
       fputil::FPBits<double>::EXP_LEN;
 #endif
 
-  FloatHexExpFPBitsProperties properties;
-#if defined(LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128)
-  if (to_conv.length_modifier == LengthModifier::Q) {
-    properties =
-        get_float_hex_exp_fp_bits_properties<float128>(to_conv.conv_val_raw);
-  } else
-#endif // LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128
-#ifndef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
-      if (to_conv.length_modifier == LengthModifier::L) {
-    properties =
-        get_float_hex_exp_fp_bits_properties<long double>(to_conv.conv_val_raw);
-  } else
-#endif // !LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
-  {
-    properties =
-        get_float_hex_exp_fp_bits_properties<double>(to_conv.conv_val_raw);
-  }
-
-  if (properties.is_inf_or_nan)
-    return convert_inf_nan(writer, to_conv);
-
   char sign_char = 0;
 
-  if (properties.is_negative)
+  if (fp_bits_properties.is_negative)
     sign_char = '-';
   else if ((to_conv.flags & FormatFlags::FORCE_SIGN) == FormatFlags::FORCE_SIGN)
     sign_char = '+'; // FORCE_SIGN has precedence over SPACE_PREFIX
@@ -104,9 +106,10 @@ LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
   // digits. This is primarily relevant for x86 80 bit long doubles, which have
   // 63 bit mantissas. In the case where the mantissa is 0, however, the
   // exponent should stay as 0.
-  if (properties.fraction_bits % BITS_IN_HEX_DIGIT != 0 &&
-      properties.mantissa > 0) {
-    properties.exponent -= properties.fraction_bits % BITS_IN_HEX_DIGIT;
+  if (fp_bits_properties.fraction_bits % BITS_IN_HEX_DIGIT != 0 &&
+      fp_bits_properties.mantissa > 0) {
+    fp_bits_properties.exponent -=
+        fp_bits_properties.fraction_bits % BITS_IN_HEX_DIGIT;
   }
 
   // This is the max number of digits it can take to represent the mantissa.
@@ -117,7 +120,7 @@ LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
       (MAX_POSSIBLE_FRACTION_LEN / BITS_IN_HEX_DIGIT) + 1;
   char mant_buffer[MANT_BUFF_LEN];
 
-  size_t mant_len = (properties.fraction_bits / BITS_IN_HEX_DIGIT) + 1;
+  size_t mant_len = (fp_bits_properties.fraction_bits / BITS_IN_HEX_DIGIT) + 1;
 
   // Precision only tracks the number of digits after the hexadecimal point, so
   // we have to add one to account for the digit before the hexadecimal point.
@@ -128,34 +131,37 @@ LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
         (mant_len - intended_digits) * BITS_IN_HEX_DIGIT;
 
     const AnyFloatStorageType truncated_bits =
-        properties.mantissa & ((AnyFloatStorageType(1) << shift_amount) - 1);
+        fp_bits_properties.mantissa &
+        ((AnyFloatStorageType(1) << shift_amount) - 1);
     const AnyFloatStorageType halfway_const = AnyFloatStorageType(1)
                                               << (shift_amount - 1);
 
-    properties.mantissa >>= shift_amount;
+    fp_bits_properties.mantissa >>= shift_amount;
 
 #ifdef LIBC_MATH_HAS_ASSUME_ROUND_NEAREST_ONLY
     // Round to nearest, if it's exactly halfway then round to even.
     if (truncated_bits > halfway_const)
-      ++properties.mantissa;
+      ++fp_bits_properties.mantissa;
     else if (truncated_bits == halfway_const)
-      properties.mantissa = properties.mantissa + (properties.mantissa & 1);
+      fp_bits_properties.mantissa =
+          fp_bits_properties.mantissa + (fp_bits_properties.mantissa & 1);
 #else
     switch (fputil::quick_get_round()) {
     case FE_TONEAREST:
       // Round to nearest, if it's exactly halfway then round to even.
       if (truncated_bits > halfway_const)
-        ++properties.mantissa;
+        ++fp_bits_properties.mantissa;
       else if (truncated_bits == halfway_const)
-        properties.mantissa = properties.mantissa + (properties.mantissa & 1);
+        fp_bits_properties.mantissa =
+            fp_bits_properties.mantissa + (fp_bits_properties.mantissa & 1);
       break;
     case FE_DOWNWARD:
-      if (truncated_bits > 0 && properties.is_negative)
-        ++properties.mantissa;
+      if (truncated_bits > 0 && fp_bits_properties.is_negative)
+        ++fp_bits_properties.mantissa;
       break;
     case FE_UPWARD:
-      if (truncated_bits > 0 && !properties.is_negative)
-        ++properties.mantissa;
+      if (truncated_bits > 0 && !fp_bits_properties.is_negative)
+        ++fp_bits_properties.mantissa;
       break;
     case FE_TOWARDZERO:
       break;
@@ -164,10 +170,10 @@ LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
 
     // If the rounding caused an overflow, shift the mantissa and adjust the
     // exponent to match.
-    if (properties.mantissa >=
+    if (fp_bits_properties.mantissa >=
         (AnyFloatStorageType(1) << (intended_digits * BITS_IN_HEX_DIGIT))) {
-      properties.mantissa >>= BITS_IN_HEX_DIGIT;
-      properties.exponent += BITS_IN_HEX_DIGIT;
+      fp_bits_properties.mantissa >>= BITS_IN_HEX_DIGIT;
+      fp_bits_properties.exponent += BITS_IN_HEX_DIGIT;
     }
 
     mant_len = intended_digits;
@@ -175,8 +181,8 @@ LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
 
   size_t mant_cur = mant_len;
   size_t first_non_zero = 1;
-  for (; mant_cur > 0; --mant_cur, properties.mantissa >>= 4) {
-    char mant_mod_16 = static_cast<char>(properties.mantissa % 16);
+  for (; mant_cur > 0; --mant_cur, fp_bits_properties.mantissa >>= 4) {
+    char mant_mod_16 = static_cast<char>(fp_bits_properties.mantissa % 16);
     char new_digit = internal::int_to_b36_char(mant_mod_16);
     if (internal::isupper(to_conv.conv_name))
       new_digit = internal::toupper(new_digit);
@@ -200,15 +206,16 @@ LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
   char exp_buffer[EXP_LEN];
 
   bool exp_is_negative = false;
-  if (properties.exponent < 0) {
+  if (fp_bits_properties.exponent < 0) {
     exp_is_negative = true;
-    properties.exponent = -properties.exponent;
+    fp_bits_properties.exponent = -fp_bits_properties.exponent;
   }
 
   size_t exp_cur = EXP_LEN;
-  for (; properties.exponent > 0; --exp_cur, properties.exponent /= 10) {
+  for (; fp_bits_properties.exponent > 0;
+       --exp_cur, fp_bits_properties.exponent /= 10) {
     exp_buffer[exp_cur - 1] =
-        internal::int_to_b36_char(properties.exponent % 10);
+        internal::int_to_b36_char(fp_bits_properties.exponent % 10);
   }
   if (exp_cur == EXP_LEN) { // if nothing else was written, write a 0.
     exp_buffer[EXP_LEN - 1] = '0';
@@ -295,6 +302,21 @@ LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
   return WRITE_OK;
 }
 
+template <OverflowMode mode>
+LIBC_INLINE int convert_float_hex_exp(Writer<mode> *writer,
+                                      const FormatSection &to_conv) {
+  FloatHexExpFPBitsProperties fp_bits_properties =
+      get_float_hex_exp_fp_bits_properties_lm(to_conv);
+  if (fp_bits_properties.is_inf_or_nan)
+    return convert_inf_nan(
+        writer,
+        InfNanFPBitsProperties{.is_negative = fp_bits_properties.is_negative,
+                               .mantissa_is_zero =
+                                   fp_bits_properties.mantissa_is_zero},
+        to_conv);
+  return convert_finite_float_hex_exp(writer, fp_bits_properties, to_conv);
+}
+
 } // namespace printf_core
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/__support/printf_core/float_inf_nan_converter.h b/libc/src/__support/printf_core/float_inf_nan_converter.h
index 40740c701d99f..5d306a13d5f13 100644
--- a/libc/src/__support/printf_core/float_inf_nan_converter.h
+++ b/libc/src/__support/printf_core/float_inf_nan_converter.h
@@ -27,41 +27,15 @@ struct InfNanFPBitsProperties {
   bool mantissa_is_zero;
 };
 
-template <typename T>
-InfNanFPBitsProperties
-get_inf_nan_fp_bits_properties(AnyFloatStorageType float_raw) {
-  fputil::FPBits<T> float_bits(
-      static_cast<typename fputil::FPBits<T>::StorageType>(float_raw));
-  return {
-      .is_negative = float_bits.is_neg(),
-      .mantissa_is_zero = float_bits.get_mantissa() == 0,
-  };
-}
-
 template <OverflowMode mode>
 LIBC_INLINE int convert_inf_nan(Writer<mode> *writer,
+                                InfNanFPBitsProperties fp_bits_properties,
                                 const FormatSection &to_conv) {
   // All of the letters will be defined relative to variable a, which will be
   // the appropriate case based on the case of the conversion.
-  InfNanFPBitsProperties properties;
-#if defined(LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128)
-  if (to_conv.length_modifier == LengthModifier::Q) {
-    properties = get_inf_nan_fp_bits_properties<float128>(to_conv.conv_val_raw);
-  } else
-#endif // LIBC_INTERNAL_PRINTF_CONVERT_FLOAT128
-#ifndef LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
-      if (to_conv.length_modifier == LengthModifier::L) {
-    properties =
-        get_inf_nan_fp_bits_properties<long double>(to_conv.conv_val_raw);
-  } else
-#endif // !LIBC_TYPES_LONG_DOUBLE_IS_DOUBLE_DOUBLE
-  {
-    properties = get_inf_nan_fp_bits_properties<double>(to_conv.conv_val_raw);
-  }
-
   char sign_char = 0;
 
-  if (properties.is_negative)
+  if (fp_bits_properties.is_negative)
     sign_char = '-';
   else if ((to_conv.flags & FormatFlags::FORCE_SIGN) == FormatFlags::FORCE_SIGN)
     sign_char = '+'; // FORCE_SIGN has precedence over SPACE_PREFIX
@@ -81,7 +55,7 @@ LIBC_INLINE int convert_inf_nan(Writer<mode> *writer,
 
   if (sign_char)
     RET_IF_RESULT_NEGATIVE(writer->write(sign_char));
-  if (properties.mantissa_is_zero) { // inf
+  if (fp_bits_properties.mantissa_is_zero) { // inf
     RET_IF_RESULT_NEGATIVE(
         writer->write(internal::islower(to_conv.conv_name) ? "inf" : "INF"));
   } else { // nan
diff --git a/libc/src/stdlib/str_from_util.h b/libc/src/stdlib/str_from_util.h
index 205adcff17094..60468ec441d90 100644
--- a/libc/src/stdlib/str_from_util.h
+++ b/libc/src/stdlib/str_from_util.h
@@ -17,6 +17,7 @@
 #ifndef LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H
 #define LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H
 
+#include "include/llvm-libc-types/float128.h"
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/printf_core/converter_atlas.h"
@@ -32,22 +33,12 @@ namespace internal {
 template <typename T>
 using storage_type = typename fputil::FPBits<T>::StorageType;
 
-template <typename T>
-printf_core::FormatSection parse_format_string(const char *__restrict format,
-                                               T fp) {
+template <typename T, printf_core::OverflowMode overflow_mode>
+LIBC_INLINE int strfromfloat_convert(printf_core::Writer<overflow_mode> *writer,
+                                     const char *__restrict format, T fp) {
   printf_core::FormatSection section;
   size_t cur_pos = 0;
 
-  // There is no typed conversion function to convert single precision float
-  // to hex exponential format, and the function convert_float_hex_exp()
-  // requires a double or long double value to work correctly.
-  // To work around this, we convert fp to double if it is single precision, and
-  // then use that double precision value in the %{A, a} conversion specifiers.
-  [[maybe_unused]] double new_fp;
-  bool t_is_single_prec_type = cpp::is_same<T, float>::value;
-  if (t_is_single_prec_type)
-    new_fp = (double)fp;
-
   if (format[cur_pos] == '%') {
     section.has_conv = true;
     ++cur_pos;
@@ -71,68 +62,67 @@ printf_core::FormatSection parse_format_string(const char *__restrict format,
     switch (format[cur_pos]) {
     case 'a':
     case 'A':
-      if (t_is_single_prec_type)
-        section.conv_val_raw = cpp::bit_cast<storage_type<double>>(new_fp);
-      else
-        section.conv_val_raw = cpp::bit_cast<storage_type<T>>(fp);
-      break;
     case 'e':
     case 'E':
     case 'f':
     case 'F':
     case 'g':
     case 'G':
-      section.conv_val_raw = cpp::bit_cast<storage_type<T>>(fp);
       break;
     default:
       section.has_conv = false;
-      while (format[cur_pos] != '\0')
-        ++cur_pos;
       break;
     }
-
-    if (format[cur_pos] != '\0')
-      ++cur_pos;
   } else {
     section.has_conv = false;
-    // We are looking for exactly one section, so no more '%'
-    while (format[cur_pos] != '\0')
-      ++cur_pos;
   }
 
-  section.raw_string = {format, cur_pos};
-  return section;
-}
-
-template <typename T, printf_core::OverflowMode overflow_mode>
-int strfromfloat_convert(printf_core::Writer<overflow_mode> *writer,
-                         const printf_core::FormatSection &section) {
   if (!section.has_conv)
-    return writer->write(section.raw_string);
-
-  auto res = static_cast<storage_type<T>>(section.conv_val_raw);
+    return writer->write(format);
 
-  fputil::FPBits<T> strfromfloat_bits(res);
+  fputil::FPBits<T> strfromfloat_bits(fp);
   if (strfromfloat_bits.is_inf_or_nan())
-    return convert_inf_nan(writer, section);
+    return convert_inf_nan(
+        writer,
+        printf_core::InfNanFPBitsProperties{
+            .is_negative = strfromfloat_bits.is_neg(),
+            .mantissa_is_zero = strfromfloat_bits.get_mantissa() == 0,
+        },
+        section);
 
   switch (section.conv_name) {
   case 'f':
   case 'F':
-    return convert_float_decimal_typed(writer, section, strfromfloat_bits);
+    return printf_core::convert_finite_float_decimal_typed(writer, section,
+                                                           strfromfloat_bits);
   case 'e':
   case 'E':
-    return convert_float_dec_exp_typed(writer, section, strfromfloat_bits);
+    return printf_core::convert_finite_float_dec_exp_typed(writer, section,
+                                                           strfromfloat_bits);
   case 'a':
   case 'A':
-    return convert_float_hex_exp(writer, section);
+    // There is no typed conversion function to convert single precision float
+    // to hex exponential format, and the convert_finite_float_hex_exp()
+    // requires a double or long double value to work correctly.
+    if constexpr (cpp::is_same_v<T, float>) {
+      return printf_core::convert_finite_float_hex_exp(
+          writer,
+          printf_core::get_float_hex_exp_fp_bits_properties_typed(
+              fputil::FPBits<double>(static_cast<double>(fp))),
+          section);
+    } else {
+      return printf_core::convert_finite_float_hex_exp(
+          writer,
+          printf_core::get_float_hex_exp_fp_bits_properties_typed(
+              strfromfloat_bits),
+          section);
+    }
   case 'g':
   case 'G':
-    return convert_float_dec_auto_typed(writer, section, strfromfloat_bits);
-  default:
-    return writer->write(section.raw_string);
+    return printf_core::convert_finite_float_dec_auto_typed(writer, section,
+                                                            strfromfloat_bits);
   }
-  return -1;
+  __builtin_unreachable();
 }
 
 } // namespace internal
diff --git a/libc/src/stdlib/strfromd.cpp b/libc/src/stdlib/strfromd.cpp
index 8983a0f5787d8..e54b35b22b869 100644
--- a/libc/src/stdlib/strfromd.cpp
+++ b/libc/src/stdlib/strfromd.cpp
@@ -20,17 +20,9 @@ LLVM_LIBC_FUNCTION(int, strfromd,
                     double fp)) {
   LIBC_ASSERT(s != nullptr);
 
-  printf_core::FormatSection section =
-      internal::parse_format_string(format, fp);
   printf_core::Writer writer =
       printf_core::make_drop_overflow_writer(s, (n > 0 ? n - 1 : 0));
-
-  int result = 0;
-  if (section.has_conv)
-    result = internal::strfromfloat_convert<double>(&writer, section);
-  else
-    result = writer.write(section.raw_string);
-
+  int result = internal::strfromfloat_convert(&writer, format, fp);
   if (result < 0)
     return result;
 
diff --git a/libc/src/stdlib/strfromf.cpp b/libc/src/stdlib/strfromf.cpp
index 417372d576af6..558cf9ff93750 100644
--- a/libc/src/stdlib/strfromf.cpp
+++ b/libc/src/stdlib/strfromf.cpp
@@ -20,17 +20,9 @@ LLVM_LIBC_FUNCTION(int, strfromf,
                     float fp)) {
   LIBC_ASSERT(s != nullptr);
 
-  printf_core::FormatSection section =
-      internal::parse_format_string(format, fp);
   printf_core::Writer writer =
       printf_core::make_drop_overflow_writer(s, (n > 0 ? n - 1 : 0));
-
-  int result = 0;
-  if (section.has_conv)
-    result = internal::strfromfloat_convert<float>(&writer, section);
-  else
-    result = writer.write(section.raw_string);
-
+  int result = internal::strfromfloat_convert(&writer, format, fp);
   if (result < 0)
     return result;
 
diff --git a/libc/src/stdlib/strfroml.cpp b/libc/src/stdlib/strfroml.cpp
index 2f32db0966b60..ef87d5fd7578c 100644
--- a/libc/src/stdlib/strfroml.cpp
+++ b/libc/src/stdlib/strfroml.cpp
@@ -20,21 +20,11 @@ LLVM_LIBC_FUNCTION(int, strfroml,
                     long double fp)) {
   LIBC_ASSERT(s != nullptr);
 
-  printf_core::FormatSection section =
-      internal::parse_format_string(format, fp);
-
-  // To ensure that the conversion function actually uses long double,
-  // the length modifier has to be set to LengthModifier::L
-  section.length_modifier = printf_core::LengthModifier::L;
-
   printf_core::Writer writer =
       printf_core::make_drop_overflow_writer(s, (n > 0 ? n - 1 : 0));
-
-  int result = 0;
-  if (section.has_conv)
-    result = internal::strfromfloat_convert<long double>(&writer, section);
-  else
-    result = writer.write(section.raw_string);
+  int result = internal::strfromfloat_convert(&writer, format, fp);
+  if (result < 0)
+    return result;
 
   if (result < 0)
     return result;
diff --git a/libc/test/src/stdlib/strfromf_test.cpp b/libc/test/src/stdlib/strfromf_test.cpp
index 5baeb119bf150..1c4f18731b8c4 100644
--- a/libc/test/src/stdlib/strfromf_test.cpp
+++ b/libc/test/src/stdlib/strfromf_test.cpp
@@ -88,8 +88,6 @@ TEST_F(LlvmLibcStrfromfTest, InsufficientBufferSize) {
   ASSERT_STREQ(buff, "1.05"); // Make sure that buff has not changed
 }
 
-// TODO: fix https://github.com/llvm/llvm-project/issues/217708.
-#if 0
 TEST_F(LlvmLibcStrfromfTest, InfNanValues) {
   char buff[15];
   int result;
@@ -109,7 +107,6 @@ TEST_F(LlvmLibcStrfromfTest, InfNanValues) {
   result = LIBC_NAMESPACE::strfromf(buff, 10, "%A", -nan);
   EXPECT_STREQ_LEN(result, buff, "-NAN");
 }
-#endif
 
 // https://github.com/llvm/llvm-project/issues/166795
 TEST_F(LlvmLibcStrfromfTest, ResultOverflow) {

>From 1e6e2a53e5ed2be91bcd2978e0b9a45a86268ec7 Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Wed, 23 Sep 2026 15:58:46 +0000
Subject: [PATCH 2/4] Update some missed function spellings

---
 .../printf_core/float_dec_converter_limited.h | 21 +++++++++++--------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/libc/src/__support/printf_core/float_dec_converter_limited.h b/libc/src/__support/printf_core/float_dec_converter_limited.h
index 36bdba67e9f31..afdfd68a51379 100644
--- a/libc/src/__support/printf_core/float_dec_converter_limited.h
+++ b/libc/src/__support/printf_core/float_dec_converter_limited.h
@@ -677,27 +677,30 @@ LIBC_INLINE int convert_float_outer(Writer<mode> *writer,
 
 template <typename T, OverflowMode mode,
           cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE int convert_float_decimal_typed(Writer<mode> *writer,
-                                            const FormatSection &to_conv,
-                                            fputil::FPBits<T> float_bits) {
+LIBC_INLINE int
+convert_finite_float_decimal_typed(Writer<mode> *writer,
+                                   const FormatSection &to_conv,
+                                   fputil::FPBits<T> float_bits) {
   return convert_finite_float_typed<T>(writer, to_conv, float_bits,
                                        ConversionType::F);
 }
 
 template <typename T, OverflowMode mode,
           cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE int convert_float_dec_exp_typed(Writer<mode> *writer,
-                                            const FormatSection &to_conv,
-                                            fputil::FPBits<T> float_bits) {
+LIBC_INLINE int
+convert_finite_float_dec_exp_typed(Writer<mode> *writer,
+                                   const FormatSection &to_conv,
+                                   fputil::FPBits<T> float_bits) {
   return convert_finite_float_typed<T>(writer, to_conv, float_bits,
                                        ConversionType::E);
 }
 
 template <typename T, OverflowMode mode,
           cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
-LIBC_INLINE int convert_float_dec_auto_typed(Writer<mode> *writer,
-                                             const FormatSection &to_conv,
-                                             fputil::FPBits<T> float_bits) {
+LIBC_INLINE int
+convert_finite_float_dec_auto_typed(Writer<mode> *writer,
+                                    const FormatSection &to_conv,
+                                    fputil::FPBits<T> float_bits) {
   return convert_finite_float_typed<T>(writer, to_conv, float_bits,
                                        ConversionType::G);
 }

>From f2ad12bd29e637c8ecbda4de20e63f0b0ebe61c5 Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Fri, 25 Sep 2026 14:32:38 +0000
Subject: [PATCH 3/4] Remove unnecessary header include

---
 libc/src/stdlib/str_from_util.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/libc/src/stdlib/str_from_util.h b/libc/src/stdlib/str_from_util.h
index 60468ec441d90..0c485a7cb315d 100644
--- a/libc/src/stdlib/str_from_util.h
+++ b/libc/src/stdlib/str_from_util.h
@@ -17,7 +17,6 @@
 #ifndef LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H
 #define LLVM_LIBC_SRC_STDLIB_STRFROM_UTIL_H
 
-#include "include/llvm-libc-types/float128.h"
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/printf_core/converter_atlas.h"

>From 2c8b55267656ca3f9b8a9f16bae38ce77831fa4b Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Fri, 25 Sep 2026 14:41:28 +0000
Subject: [PATCH 4/4] Value-init FormatSection to reduce brittleness of
 uniitialized members.

---
 libc/src/stdlib/str_from_util.h | 25 +++++--------------------
 1 file changed, 5 insertions(+), 20 deletions(-)

diff --git a/libc/src/stdlib/str_from_util.h b/libc/src/stdlib/str_from_util.h
index 0c485a7cb315d..1b0d45d539537 100644
--- a/libc/src/stdlib/str_from_util.h
+++ b/libc/src/stdlib/str_from_util.h
@@ -35,15 +35,13 @@ using storage_type = typename fputil::FPBits<T>::StorageType;
 template <typename T, printf_core::OverflowMode overflow_mode>
 LIBC_INLINE int strfromfloat_convert(printf_core::Writer<overflow_mode> *writer,
                                      const char *__restrict format, T fp) {
-  printf_core::FormatSection section;
+  printf_core::FormatSection section = {};
   size_t cur_pos = 0;
 
   if (format[cur_pos] == '%') {
-    section.has_conv = true;
     ++cur_pos;
 
     // handle precision
-    section.precision = -1;
     if (format[cur_pos] == '.') {
       ++cur_pos;
       section.precision = 0;
@@ -57,23 +55,10 @@ LIBC_INLINE int strfromfloat_convert(printf_core::Writer<overflow_mode> *writer,
       }
     }
 
-    section.conv_name = format[cur_pos];
-    switch (format[cur_pos]) {
-    case 'a':
-    case 'A':
-    case 'e':
-    case 'E':
-    case 'f':
-    case 'F':
-    case 'g':
-    case 'G':
-      break;
-    default:
-      section.has_conv = false;
-      break;
-    }
-  } else {
-    section.has_conv = false;
+    char n = format[cur_pos];
+    section.conv_name = n;
+    section.has_conv = n == 'f' || n == 'F' || n == 'e' || n == 'E' ||
+                       n == 'a' || n == 'A' || n == 'g' || n == 'G';
   }
 
   if (!section.has_conv)



More information about the libc-commits mailing list