[gcc r16-293] libstdc++: Fix _Padding_sink in case when predicted width is between padwidth and maxwidth [PR109162
Tomasz Kaminski
tkaminsk@gcc.gnu.org
Wed Apr 30 05:13:59 GMT 2025
https://gcc.gnu.org/g:2ca5725e104d432317a44ad45183a4f555da3b82
commit r16-293-g2ca5725e104d432317a44ad45183a4f555da3b82
Author: Tomasz Kamiński <tkaminsk@redhat.com>
Date: Fri Apr 25 20:10:52 2025 +0200
libstdc++: Fix _Padding_sink in case when predicted width is between padwidth and maxwidth [PR109162]
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.
Diff:
---
libstdc++-v3/include/std/format | 7 ++++---
libstdc++-v3/testsuite/std/format/debug.cc | 9 +++++++++
libstdc++-v3/testsuite/std/format/ranges/sequence.cc | 9 +++++++++
3 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index 69d8d189db62..054ce3504408 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -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
diff --git a/libstdc++-v3/testsuite/std/format/debug.cc b/libstdc++-v3/testsuite/std/format/debug.cc
index d3402f80f4b6..6165a2954963 100644
--- a/libstdc++-v3/testsuite/std/format/debug.cc
+++ b/libstdc++-v3/testsuite/std/format/debug.cc
@@ -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) );
diff --git a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
index 75fe4c19a523..32242860f10e 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/sequence.cc
@@ -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) );
More information about the Libstdc++-cvs
mailing list