]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix std::format output of %C for negative years
authorJonathan Wakely <jwakely@redhat.com>
Mon, 11 Dec 2023 15:33:59 +0000 (15:33 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Wed, 13 Dec 2023 09:20:27 +0000 (09:20 +0000)
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.

(cherry picked from commit a01462ae8bafa86e7df47a252917ba6899d587cf)

libstdc++-v3/include/bits/chrono_io.h
libstdc++-v3/testsuite/std/time/year/io.cc

index c95301361d877f1d168b7fe7316222c271b4e8d7..c422435f7f31dc3a3bedda0f86e2f9e8b8397677 100644 (file)
@@ -826,9 +826,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);
index 89ab7b1e61e16b46ad6a5fcaf201c9fdb831187f..b50d9d89c614ccaf2c80b9b07f9d8b5155c0d0fe 100644 (file)
@@ -44,8 +44,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" );