From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id E69AD3858C2F; Wed, 13 Dec 2023 09:39:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E69AD3858C2F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1702460399; bh=7IKaNUuiGrvP+WYYkmQE5hUIEKoVQ6BUiFxOXz+B8W0=; h=From:To:Subject:Date:From; b=WB92EHMVuuCZfFUntcsIG1OUKbBb3DSlLchgzot08CPaaIcc1G8aybGs58o7QQzjI QytOVD4OHlPMsrEuo9i/wDCN6a/cLCIo0emci8jIL/DJJw+gJR72rFa1jH5sFc/Ka0 opM5GvgZClhB/Aao1sCsT76X5z9QHn5f3pWrVYQo= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r13-8151] libstdc++: Fix std::format output of %C for negative years X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/releases/gcc-13 X-Git-Oldrev: f5951e7a770aa6abbfc0136e08cd3822528f0efe X-Git-Newrev: 1a0aafdc2cf94c53e6451ac76fbc875cb56408df Message-Id: <20231213093959.E69AD3858C2F@sourceware.org> Date: Wed, 13 Dec 2023 09:39:59 +0000 (GMT) List-Id: https://gcc.gnu.org/g:1a0aafdc2cf94c53e6451ac76fbc875cb56408df commit r13-8151-g1a0aafdc2cf94c53e6451ac76fbc875cb56408df Author: Jonathan Wakely Date: Mon Dec 11 15:33:59 2023 +0000 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. (cherry picked from commit a01462ae8bafa86e7df47a252917ba6899d587cf) Diff: --- libstdc++-v3/include/bits/chrono_io.h | 9 +++++++-- libstdc++-v3/testsuite/std/time/year/io.cc | 7 +++++-- 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 c95301361d8..c422435f7f3 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -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); diff --git a/libstdc++-v3/testsuite/std/time/year/io.cc b/libstdc++-v3/testsuite/std/time/year/io.cc index 89ab7b1e61e..b50d9d89c61 100644 --- a/libstdc++-v3/testsuite/std/time/year/io.cc +++ b/libstdc++-v3/testsuite/std/time/year/io.cc @@ -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" );