aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2023-12-11 15:33:59 +0000
committerJonathan Wakely <jwakely@redhat.com>2023-12-12 22:33:32 +0000
commita01462ae8bafa86e7df47a252917ba6899d587cf (patch)
tree82f8a46d4a2062aa0218c745b696479596e48ec5
parent988dd6384c88a110952833dfe7c8344b9af95fa4 (diff)
downloadgcc-a01462ae8bafa86e7df47a252917ba6899d587cf.zip
gcc-a01462ae8bafa86e7df47a252917ba6899d587cf.tar.gz
gcc-a01462ae8bafa86e7df47a252917ba6899d587cf.tar.bz2
libstdc++: Fix std::format output of %C for negative years
During discussion of LWG 4022 I noticed that we do not correctly implement floored division for the century. We were just truncating towards zero, rather than applying the floor function. For negative values that rounds the wrong way. libstdc++-v3/ChangeLog: * include/bits/chrono_io.h (__formatter_chrono::_M_C_y_Y): Fix rounding for negative centuries. * testsuite/std/time/year/io.cc: Check %C for negative years.
-rw-r--r--libstdc++-v3/include/bits/chrono_io.h9
-rw-r--r--libstdc++-v3/testsuite/std/time/year/io.cc7
2 files changed, 12 insertions, 4 deletions
diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h
index 16e8fc5..b63b859 100644
--- a/libstdc++-v3/include/bits/chrono_io.h
+++ b/libstdc++-v3/include/bits/chrono_io.h
@@ -820,9 +820,14 @@ namespace __format
if (__conv == 'Y' || __conv == 'C')
{
- if (__is_neg)
- __s.assign(1, _S_plus_minus[1]);
int __ci = __yi / 100;
+ if (__is_neg) [[unlikely]]
+ {
+ __s.assign(1, _S_plus_minus[1]);
+ // For floored division -123//100 is -2 and -100//100 is -1
+ if ((__ci * 100) != __yi)
+ ++__ci;
+ }
if (__ci >= 100) [[unlikely]]
{
__s += std::format(_S_empty_spec, __ci / 100);
diff --git a/libstdc++-v3/testsuite/std/time/year/io.cc b/libstdc++-v3/testsuite/std/time/year/io.cc
index 6157afa..a6683ae 100644
--- a/libstdc++-v3/testsuite/std/time/year/io.cc
+++ b/libstdc++-v3/testsuite/std/time/year/io.cc
@@ -43,8 +43,11 @@ test_format()
s = std::format("{}", --year::min()); // formatted via ostream
VERIFY( s == "-32768 is not a valid year" );
- s = std::format("{:%y} {:%y}", 1976y, -1976y);
- VERIFY( s == "76 76" ); // LWG 3831
+ s = std::format("{:%C %y} {:%C %y}", 1976y, -1976y);
+ VERIFY( s == "19 76 -20 76" ); // LWG 3831
+
+ s = std::format("{:%C %y} {:%C %y} {:%C %y}", -9y, -900y, -555y);
+ VERIFY( s == "-01 09 -09 00 -06 55" ); // LWG 4022
s = std::format("{0:%EC}{0:%Ey} = {0:%EY}", 1642y);
VERIFY( s == "1642 = 1642" );