https://gcc.gnu.org/g:974d59aec69b35bd4f7f8464a3bcfc55e849ed1f
commit r15-9818-g974d59aec69b35bd4f7f8464a3bcfc55e849ed1f Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Jun 4 18:22:28 2025 +0100 libstdc++: Fix std::format thousands separators when sign present [PR120548] The leading sign character should be skipped when deciding whether to insert thousands separators into a floating-point format. libstdc++-v3/ChangeLog: PR libstdc++/120548 * include/std/format (__formatter_fp::_M_localize): Do not include a leading sign character in the string to be grouped. * testsuite/std/format/functions/format.cc: Check grouping when sign is present in the output. Reviewed-by: Tomasz KamiĆski <tkami...@redhat.com> (cherry picked from commit 2c3559839d70df6311da18fd93237050405580c3) Diff: --- libstdc++-v3/include/std/format | 11 +++++++++-- libstdc++-v3/testsuite/std/format/functions/format.cc | 10 ++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 8beef93c7809..d25df1224ffc 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -2362,9 +2362,16 @@ namespace __format const size_t __r = __str.size() - __e; // Length of remainder. auto __overwrite = [&](_CharT* __p, size_t) { // Apply grouping to the digits before the radix or exponent. - auto __end = std::__add_grouping(__p, __np.thousands_sep(), + int __off = 0; + if (auto __c = __str.front(); __c == '-' || __c == '+' || __c == ' ') + { + *__p = __c; + __off = 1; + } + auto __end = std::__add_grouping(__p + __off, __np.thousands_sep(), __grp.data(), __grp.size(), - __str.data(), __str.data() + __e); + __str.data() + __off, + __str.data() + __e); if (__r) // If there's a fractional part or exponent { if (__d != __str.npos) diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc index 93c33b456e64..6f6f1f15b35b 100644 --- a/libstdc++-v3/testsuite/std/format/functions/format.cc +++ b/libstdc++-v3/testsuite/std/format/functions/format.cc @@ -260,6 +260,16 @@ test_locale() s = std::format(eloc, "{0:Le} {0:Lf} {0:Lg}", -nan); VERIFY( s == "-nan -nan -nan" ); + // PR libstdc++/120548 format confuses a negative sign for a thousands digit + s = std::format(bloc, "{:L}", -123.45); + VERIFY( s == "-123.45" ); + s = std::format(bloc, "{:-L}", -876543.21); + VERIFY( s == "-876,543.21" ); + s = std::format(bloc, "{:+L}", 333.22); + VERIFY( s == "+333.22" ); + s = std::format(bloc, "{: L}", 999.44); + VERIFY( s == " 999.44" ); + // Restore std::locale::global(cloc); }