]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix _Padding_sink in case when predicted width is between padwidth and...
authorTomasz Kamiński <tkaminsk@redhat.com>
Fri, 25 Apr 2025 18:10:52 +0000 (20:10 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Wed, 30 Apr 2025 04:13:11 +0000 (06:13 +0200)
The _Padding_sink was behaving incorrectly, when the predicted width (based on
code units count) was higher than _M_maxwidth, but lower than _M_padwidth.
In this case _M_update() returned without calling _M_force_update() and computing
field width for Unicode encoding, because _M_buffering() returned 'true'.
As a consequence we switched to _M_ignoring() mode, while storing a sequence
with more code units but smaller field width than _M_maxwidth.

We now call _M_force_update() if predicted width is greater or equal to either
_M_padwidth or _M_maxwidth.

This happened for existing test case on 32bit architecture.

PR libstdc++/109162

libstdc++-v3/ChangeLog:

* include/std/format (_Padding_sink::_M_update): Fixed condition for
calling _M_force_update.
* testsuite/std/format/debug.cc: Add test that reproduces this issue
on 64bit architecture.
* testsuite/std/format/ranges/sequence.cc: Another edge value test.

libstdc++-v3/include/std/format
libstdc++-v3/testsuite/std/format/debug.cc
libstdc++-v3/testsuite/std/format/ranges/sequence.cc

index 69d8d189db628f0f83cbae6a52a331c6603147f6..054ce3504408952543b7b6e0a43b65d794326876 100644 (file)
@@ -3697,9 +3697,10 @@ namespace __format
       _M_update(size_t __new)
       {
        _M_printwidth += __new;
-       if (_M_buffering())
-         return true;
-       return _M_force_update();
+       // Compute estimated width, to see if is not reduced.
+       if (_M_printwidth >= _M_padwidth || _M_printwidth >= _M_maxwidth)
+         return _M_force_update();
+       return true;
       }
 
       void
index d3402f80f4b646f0c8ce0440b686d1bfb900acd5..6165a295496381659cdf1b1c1808eeb43f008cb0 100644 (file)
@@ -596,6 +596,10 @@ void test_padding()
   VERIFY( strip_prefix(resv, 48, '*') );
   VERIFY( resv == inv );
 
+  resv = res = std::format("{:*>300.200s}", in);
+  VERIFY( strip_prefix(resv, 108, '*') );
+  VERIFY( resv == inv );
+
   resv = res = std::format("{:*>240.200s}", in);
   VERIFY( strip_prefix(resv, 48, '*') );
   VERIFY( resv == inv );
@@ -678,6 +682,11 @@ void test_padding()
   VERIFY( strip_quotes(resv) );
   VERIFY( resv == inv );
 
+  resv = res = std::format("{:*>300.200?}", in);
+  VERIFY( strip_prefix(resv, 106, '*') );
+  VERIFY( strip_quotes(resv) );
+  VERIFY( resv == inv );
+
   resv = res = std::format("{:*>240.200?}", in);
   VERIFY( strip_prefix(resv, 46, '*') );
   VERIFY( strip_quotes(resv) );
index 75fe4c19a523339032acdec7a1081918ed70def8..32242860f10e44dbf6a1a022492a79d8d6e619a0 100644 (file)
@@ -295,6 +295,15 @@ void test_padding()
   resv = res = std::format("{:*>10n:}", vs);
   VERIFY( check_elems(resv, false) );
 
+  resv = res = std::format("{:*>256}", vs);
+  VERIFY( strip_prefix(resv, 48, '*') );
+  VERIFY( strip_squares(resv) );
+  VERIFY( check_elems(resv, true) );
+
+  resv = res = std::format("{:*>256n}", vs);
+  VERIFY( strip_prefix(resv, 50, '*') );
+  VERIFY( check_elems(resv, true) );
+
   resv = res = std::format("{:*>240}", vs);
   VERIFY( strip_prefix(resv, 32, '*') );
   VERIFY( strip_squares(resv) );