diff options
author | Mark de Wever <koraq@xs4all.nl> | 2022-11-05 18:33:25 +0100 |
---|---|---|
committer | Tom Stellard <tstellar@redhat.com> | 2023-03-08 05:38:08 -0800 |
commit | c7d3410533dcee16a8837b36400cc36dbc7bbae2 (patch) | |
tree | c11d7e2d649b20ce7e056da888dd132ce6a38a49 /libcxx | |
parent | 0e540397b083ae8d88c9057f801af30a974e2a4c (diff) | |
download | llvm-c7d3410533dcee16a8837b36400cc36dbc7bbae2.zip llvm-c7d3410533dcee16a8837b36400cc36dbc7bbae2.tar.gz llvm-c7d3410533dcee16a8837b36400cc36dbc7bbae2.tar.bz2 |
[libc++][format] Fix floating point formatting.
Fixes llvm.org/PR58714 reported by @jwakely and a similar issue
reported privately by @vitaut.
Reviewed By: ldionne, #libc
Differential Revision: https://reviews.llvm.org/D145306
(cherry picked from commit 5eaba4a9b1899ce16785b05854bddd39d54b0266)
Diffstat (limited to 'libcxx')
-rw-r--r-- | libcxx/include/__format/formatter_floating_point.h | 3 | ||||
-rw-r--r-- | libcxx/test/std/utilities/format/format.functions/format_tests.h | 54 |
2 files changed, 55 insertions, 2 deletions
diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h index a544b53..ca06572 100644 --- a/libcxx/include/__format/formatter_floating_point.h +++ b/libcxx/include/__format/formatter_floating_point.h @@ -404,7 +404,6 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_ // 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 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif 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; diff --git a/libcxx/test/std/utilities/format/format.functions/format_tests.h b/libcxx/test/std/utilities/format/format.functions/format_tests.h index 763cf45..f5f6a60 100644 --- a/libcxx/test/std/utilities/format/format.functions/format_tests.h +++ b/libcxx/test/std/utilities/format/format.functions/format_tests.h @@ -2367,6 +2367,7 @@ void format_test_floating_point_default_precision(TestFunction check) { // *** 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 @@ void format_test_floating_point_default_precision(TestFunction check) { // 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 @@ void format_test_floating_point(TestFunction check, ExceptionTest check_exceptio 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)); |