From patchwork Tue Dec 12 22:46:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1875384 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=Q4u1W5JM; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4SqYdv2QF7z20LX for ; Wed, 13 Dec 2023 09:47:15 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5F389385417D for ; Tue, 12 Dec 2023 22:47:13 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 1F0AC385703F for ; Tue, 12 Dec 2023 22:46:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1F0AC385703F Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1F0AC385703F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702421220; cv=none; b=ZPpsWhP+iHbWNqu1Yo4Dl/UUNoD2+4oTfguWqYGS9FkNmuH2sqNaCZyD6/BMpD4EpsPKR0cbzLvbp5T4B+COGEUU3BGl6S763JaE45Qzq7waKSCUxi72qEjAFCjyArMAtYrMS8crwvcSvR3GUG/f6nNUIIy9+fRnEsVxjigdkIY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1702421220; c=relaxed/simple; bh=F+V/1AI0umHJcIZcb7Rqw+8j3Ct17qgYQ94ajhvpI0k=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Ejc1HxGx4ieSLf6FbH1C5yH0eveXExWRxPBkRi0h9ym9T8t9/GuMK0mAKGagFdjCPROFt7IradFneG/Nrpwd+M2VBroIrlT/GIF1NntyFwz2oIK8WjGV+hJRT65MH2PXi5H85W2EsR7etp3tNq8B6UPXVsg7aQP9uSrTjn0b650= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702421218; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=1TkLLinqiIlRy9Is7PVnqQv+W2Av6TjMth1+lqotw68=; b=Q4u1W5JMOPvPW2Jx6LN/wLbhwbcIei3KE9jsrWoKuzoadeg3zLAcvP9cnFfvhhfW9SIgwq e8C3LcLXeYjSA4p1JvzqbG6JrySy/jnrlITD8j9PN9xeLLp/t95+/F/d5HEtOO4emS/a3v 0ushH8a3KGa3NPfCS72O4waSvve99zI= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-182-2w_wo6MDOI6WxjBWF04LGQ-1; Tue, 12 Dec 2023 17:46:55 -0500 X-MC-Unique: 2w_wo6MDOI6WxjBWF04LGQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 81714881C82; Tue, 12 Dec 2023 22:46:55 +0000 (UTC) Received: from localhost (unknown [10.42.28.145]) by smtp.corp.redhat.com (Postfix) with ESMTP id 36FAA1C060AF; Tue, 12 Dec 2023 22:46:55 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix std::format output of %C for negative years Date: Tue, 12 Dec 2023 22:46:47 +0000 Message-ID: <20231212224654.1518338-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Tested x86_64-linux. Pushed to trunk. -- >8-- 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. --- 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 16e8fc58dff..b63b8592eba 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 6157afae253..a6683ae20df 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" );