Skip to content

Commit c7d3410

Browse files
mordantetstellar
authored andcommitted
[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 5eaba4a)
1 parent 0e54039 commit c7d3410

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

libcxx/include/__format/formatter_floating_point.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,6 @@ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_
404404
// In fixed mode the algorithm truncates trailing spaces and possibly the
405405
// radix point. There's no good guess for the position of the radix point
406406
// therefore scan the output after the first digit.
407-
408407
__result.__radix_point = _VSTD::find(__first, __result.__last, '.');
409408
}
410409
}
@@ -665,7 +664,7 @@ __format_floating_point(_Tp __value, auto& __ctx, __format_spec::__parsed_specif
665664
if (__result.__exponent == __result.__last)
666665
// if P > X >= -4, the conversion is with style f or F and precision P - 1 - X.
667666
// By including the radix point it calculates P - (1 + X)
668-
__p -= __result.__radix_point - __buffer.begin();
667+
__p -= __result.__radix_point - __result.__integral;
669668
else
670669
// otherwise, the conversion is with style e or E and precision P - 1.
671670
--__p;

libcxx/test/std/utilities/format/format.functions/format_tests.h

+54
Original file line numberDiff line numberDiff line change
@@ -2367,6 +2367,7 @@ void format_test_floating_point_default_precision(TestFunction check) {
23672367

23682368
// *** alternate form **
23692369
// When precision is zero there's no decimal point except when the alternate form is specified.
2370+
// Note unlike the g and G option the trailing zeros are still removed.
23702371
check(SV("answer is '0'"), SV("answer is '{:.0}'"), F(0));
23712372
check(SV("answer is '0.'"), SV("answer is '{:#.0}'"), F(0));
23722373

@@ -2449,6 +2450,57 @@ void format_test_floating_point_default_precision(TestFunction check) {
24492450
// See locale-specific_form.pass.cpp
24502451
}
24512452

2453+
template <class F, class CharT, class TestFunction>
2454+
void format_test_floating_point_PR58714(TestFunction check) {
2455+
check(SV("+1234"), SV("{:+}"), F(1234.0));
2456+
check(SV("+1.348p+10"), SV("{:+a}"), F(1234.0));
2457+
check(SV("+1.234000e+03"), SV("{:+e}"), F(1234.0));
2458+
check(SV("+1234.000000"), SV("{:+f}"), F(1234.0));
2459+
check(SV("+1234"), SV("{:+g}"), F(1234.0));
2460+
2461+
check(SV("1234."), SV("{:#}"), F(1234.0));
2462+
check(SV("1.348p+10"), SV("{:#a}"), F(1234.0));
2463+
check(SV("1.234000e+03"), SV("{:#e}"), F(1234.0));
2464+
check(SV("1234.000000"), SV("{:#f}"), F(1234.0));
2465+
check(SV("1234.00"), SV("{:#g}"), F(1234.0));
2466+
2467+
check(SV("4.e+30"), SV("{:#}"), F(4.0e+30));
2468+
check(SV("1.p+102"), SV("{:#a}"), F(0x4.0p+100));
2469+
check(SV("4.000000e+30"), SV("{:#e}"), F(4.0e+30));
2470+
check(SV("5070602400912917605986812821504.000000"), SV("{:#f}"), F(0x4.0p+100));
2471+
check(SV("4.00000e+30"), SV("{:#g}"), F(4.0e+30));
2472+
2473+
check(SV("1234."), SV("{:#.6}"), F(1234.0)); // # does not restore zeros
2474+
check(SV("1.348000p+10"), SV("{:#.6a}"), F(1234.0));
2475+
check(SV("1.234000e+03"), SV("{:#.6e}"), F(1234.0));
2476+
check(SV("1234.000000"), SV("{:#.6f}"), F(1234.0));
2477+
check(SV("1234.00"), SV("{:#.6g}"), F(1234.0));
2478+
2479+
check(SV("-1234."), SV("{:#}"), F(-1234.0));
2480+
check(SV("-1.348p+10"), SV("{:#a}"), F(-1234.0));
2481+
check(SV("-1.234000e+03"), SV("{:#e}"), F(-1234.0));
2482+
check(SV("-1234.000000"), SV("{:#f}"), F(-1234.0));
2483+
check(SV("-1234.00"), SV("{:#g}"), F(-1234.0));
2484+
2485+
check(SV("-1234."), SV("{:#.6}"), F(-1234.0)); // # does not restore zeros
2486+
check(SV("-1.348000p+10"), SV("{:#.6a}"), F(-1234.0));
2487+
check(SV("-1.234000e+03"), SV("{:#.6e}"), F(-1234.0));
2488+
check(SV("-1234.000000"), SV("{:#.6f}"), F(-1234.0));
2489+
check(SV("-1234.00"), SV("{:#.6g}"), F(-1234.0));
2490+
2491+
check(SV("+1234."), SV("{:+#}"), F(1234.0));
2492+
check(SV("+1.348p+10"), SV("{:+#a}"), F(1234.0));
2493+
check(SV("+1.234000e+03"), SV("{:+#e}"), F(1234.0));
2494+
check(SV("+1234.000000"), SV("{:+#f}"), F(1234.0));
2495+
check(SV("+1234.00"), SV("{:+#g}"), F(1234.0));
2496+
2497+
check(SV("+1234."), SV("{:+#.6}"), F(1234.0)); // # does not restore zeros
2498+
check(SV("+1.348000p+10"), SV("{:+#.6a}"), F(1234.0));
2499+
check(SV("+1.234000e+03"), SV("{:+#.6e}"), F(1234.0));
2500+
check(SV("+1234.000000"), SV("{:+#.6f}"), F(1234.0));
2501+
check(SV("+1234.00"), SV("{:+#.6g}"), F(1234.0));
2502+
}
2503+
24522504
template <class F, class CharT, class TestFunction, class ExceptionTest>
24532505
void format_test_floating_point(TestFunction check, ExceptionTest check_exception) {
24542506
format_test_floating_point_hex_lower_case<F, CharT>(check);
@@ -2468,6 +2520,8 @@ void format_test_floating_point(TestFunction check, ExceptionTest check_exceptio
24682520
format_test_floating_point_default<F, CharT>(check);
24692521
format_test_floating_point_default_precision<F, CharT>(check);
24702522

2523+
format_test_floating_point_PR58714<F, CharT>(check);
2524+
24712525
// *** type ***
24722526
for (const auto& fmt : invalid_types<CharT>("aAeEfFgG"))
24732527
check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, F(1));

0 commit comments

Comments
 (0)