[libcxx-commits] [PATCH] D145306: [libc++][format] Fix floating point formatting.

Mark de Wever via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Sat Mar 4 06:32:00 PST 2023


Mordante created this revision.
Mordante added reviewers: ldionne, vitaut.
Herald added a project: All.
Mordante requested review of this revision.
Herald added a project: libc++.
Herald added a subscriber: libcxx-commits.
Herald added a reviewer: libc++.

Fixes llvm.org/PR58714 reported by @jwakely and a similar issue
reported privately by @vitaut.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145306

Files:
  libcxx/include/__format/formatter_floating_point.h
  libcxx/test/std/utilities/format/format.functions/format_tests.h


Index: libcxx/test/std/utilities/format/format.functions/format_tests.h
===================================================================
--- libcxx/test/std/utilities/format/format.functions/format_tests.h
+++ libcxx/test/std/utilities/format/format.functions/format_tests.h
@@ -2367,6 +2367,7 @@
 
   // *** alternate form **
   // When precision is zero there's no decimal point except when the alternate form is specified.
+  // Note unlike the g and G option the trailing zeros are still removed.
   check(SV("answer is '0'"), SV("answer is '{:.0}'"), F(0));
   check(SV("answer is '0.'"), SV("answer is '{:#.0}'"), F(0));
 
@@ -2449,6 +2450,57 @@
   // See locale-specific_form.pass.cpp
 }
 
+template <class F, class CharT, class TestFunction>
+void format_test_floating_point_PR58714(TestFunction check) {
+  check(SV("+1234"), SV("{:+}"), F(1234.0));
+  check(SV("+1.348p+10"), SV("{:+a}"), F(1234.0));
+  check(SV("+1.234000e+03"), SV("{:+e}"), F(1234.0));
+  check(SV("+1234.000000"), SV("{:+f}"), F(1234.0));
+  check(SV("+1234"), SV("{:+g}"), F(1234.0));
+
+  check(SV("1234."), SV("{:#}"), F(1234.0));
+  check(SV("1.348p+10"), SV("{:#a}"), F(1234.0));
+  check(SV("1.234000e+03"), SV("{:#e}"), F(1234.0));
+  check(SV("1234.000000"), SV("{:#f}"), F(1234.0));
+  check(SV("1234.00"), SV("{:#g}"), F(1234.0));
+
+  check(SV("4.e+30"), SV("{:#}"), F(4.0e+30));
+  check(SV("1.p+102"), SV("{:#a}"), F(0x4.0p+100));
+  check(SV("4.000000e+30"), SV("{:#e}"), F(4.0e+30));
+  check(SV("5070602400912917605986812821504.000000"), SV("{:#f}"), F(0x4.0p+100));
+  check(SV("4.00000e+30"), SV("{:#g}"), F(4.0e+30));
+
+  check(SV("1234."), SV("{:#.6}"), F(1234.0)); // # does not restore zeros
+  check(SV("1.348000p+10"), SV("{:#.6a}"), F(1234.0));
+  check(SV("1.234000e+03"), SV("{:#.6e}"), F(1234.0));
+  check(SV("1234.000000"), SV("{:#.6f}"), F(1234.0));
+  check(SV("1234.00"), SV("{:#.6g}"), F(1234.0));
+
+  check(SV("-1234."), SV("{:#}"), F(-1234.0));
+  check(SV("-1.348p+10"), SV("{:#a}"), F(-1234.0));
+  check(SV("-1.234000e+03"), SV("{:#e}"), F(-1234.0));
+  check(SV("-1234.000000"), SV("{:#f}"), F(-1234.0));
+  check(SV("-1234.00"), SV("{:#g}"), F(-1234.0));
+
+  check(SV("-1234."), SV("{:#.6}"), F(-1234.0)); // # does not restore zeros
+  check(SV("-1.348000p+10"), SV("{:#.6a}"), F(-1234.0));
+  check(SV("-1.234000e+03"), SV("{:#.6e}"), F(-1234.0));
+  check(SV("-1234.000000"), SV("{:#.6f}"), F(-1234.0));
+  check(SV("-1234.00"), SV("{:#.6g}"), F(-1234.0));
+
+  check(SV("+1234."), SV("{:+#}"), F(1234.0));
+  check(SV("+1.348p+10"), SV("{:+#a}"), F(1234.0));
+  check(SV("+1.234000e+03"), SV("{:+#e}"), F(1234.0));
+  check(SV("+1234.000000"), SV("{:+#f}"), F(1234.0));
+  check(SV("+1234.00"), SV("{:+#g}"), F(1234.0));
+
+  check(SV("+1234."), SV("{:+#.6}"), F(1234.0)); // # does not restore zeros
+  check(SV("+1.348000p+10"), SV("{:+#.6a}"), F(1234.0));
+  check(SV("+1.234000e+03"), SV("{:+#.6e}"), F(1234.0));
+  check(SV("+1234.000000"), SV("{:+#.6f}"), F(1234.0));
+  check(SV("+1234.00"), SV("{:+#.6g}"), F(1234.0));
+}
+
 template <class F, class CharT, class TestFunction, class ExceptionTest>
 void format_test_floating_point(TestFunction check, ExceptionTest check_exception) {
   format_test_floating_point_hex_lower_case<F, CharT>(check);
@@ -2468,6 +2520,8 @@
   format_test_floating_point_default<F, CharT>(check);
   format_test_floating_point_default_precision<F, CharT>(check);
 
+  format_test_floating_point_PR58714<F, CharT>(check);
+
   // *** type ***
   for (const auto& fmt : invalid_types<CharT>("aAeEfFgG"))
     check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, F(1));
Index: libcxx/include/__format/formatter_floating_point.h
===================================================================
--- libcxx/include/__format/formatter_floating_point.h
+++ libcxx/include/__format/formatter_floating_point.h
@@ -404,7 +404,6 @@
       // In fixed mode the algorithm truncates trailing spaces and possibly the
       // radix point. There's no good guess for the position of the radix point
       // therefore scan the output after the first digit.
-
       __result.__radix_point = _VSTD::find(__first, __result.__last, '.');
     }
   }
@@ -665,7 +664,7 @@
       if (__result.__exponent == __result.__last)
         // if P > X >= -4, the conversion is with style f or F and precision P - 1 - X.
         // By including the radix point it calculates P - (1 + X)
-        __p -= __result.__radix_point - __buffer.begin();
+        __p -= __result.__radix_point - __result.__integral;
       else
         // otherwise, the conversion is with style e or E and precision P - 1.
         --__p;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D145306.502374.patch
Type: text/x-patch
Size: 4705 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20230304/0db24f40/attachment.bin>


More information about the libcxx-commits mailing list