From patchwork Tue Nov 15 14:31:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 20401 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:6687:0:0:0:0:0 with SMTP id l7csp2762512wru; Tue, 15 Nov 2022 06:33:09 -0800 (PST) X-Google-Smtp-Source: AA0mqf6/CzGjkK2SRUJPX+E5nHDAYUOb1E8BIcmy0wamKRJH/lqy3L1KRQ4476LDh6MybeWg6IW+ X-Received: by 2002:a17:907:1382:b0:7ad:b286:72da with SMTP id vs2-20020a170907138200b007adb28672damr14293144ejb.152.1668522788865; Tue, 15 Nov 2022 06:33:08 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668522788; cv=none; d=google.com; s=arc-20160816; b=0EBGZIgM35+Z5iT929N0x4XNbh6oG8CqABNaFxpEi2I+mLtYcPArBtmcI1ZanfSRey lA4XbEwq46jaOlpYhFq72TxjwgLKYT/fScG2I70T8/qDaFLs548p44tNmxacVnU7laEt 2wON3vHcYPpqlC3a1zzBviz89zE2KRH0nRHpM34HI8AubPV/5peXVhy2u7rVaf2JbEy/ XD6TBWJYvNwtXz4RtNAn0iBEmaOXNxgPDP+i45GyP/X5p5vrBqodWnoTu91KWPb3xIf0 urT4rcc5dWolhg8SxF/mb1r+P/uTqrOfn9dpqvN8+TytCN+9RYUMVtiwbAXdMtqK+Ec/ nPmA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-transfer-encoding:mime-version:message-id:date:subject:to :dmarc-filter:delivered-to:dkim-signature:dkim-filter; bh=v8ptF4Lr9rdkXLYeakxLw4+OWWtjdr57asEtzGqfh6I=; b=quNVCfNYFmMTeVAAyC8mlZfVPV1lkX0HK4pyNMKfG+GrRfxBuL1HJ6XGb2f2PoSYDc 1TLVmetgkSGB9S/Mvf6fZPnAJn2nIqS+6btxuW+OwBcG4QSa1RRBvbNDrLDiao4PyhCN P9SLRbP9CpIA8OqeuwhPBOZhJquwbJrfbLxm6QT5KI1K6RV1rOnJXmMFY+GIhpEKdaz4 bvWhqxeCXV/v6/6YwkY7BsbMLewIq7bKukSGdmuARKawWA1jhQn0Mo8kqmfwp7MpUoBB JiZrc6hRsPVrizfDCXS9n2IeYXEP6krTLS80TWdv0ZZF16ABxMhG0+S/JMoBmwXCABik R0RA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=Mo3CQkAQ; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id x24-20020a1709064a9800b007808f3f4cbcsi8952482eju.239.2022.11.15.06.33.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Nov 2022 06:33:08 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=Mo3CQkAQ; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D364A389EC5B for ; Tue, 15 Nov 2022 14:32:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D364A389EC5B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1668522739; bh=v8ptF4Lr9rdkXLYeakxLw4+OWWtjdr57asEtzGqfh6I=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=Mo3CQkAQI/Sd86FFIfulrGuVqeK7tRRnLwNHyuNpvD9M+RLEhVj12PLl8V5kxrUYA i6zAbFCeYDOrUGtfYdwSUr60AyiPolz24P8ff0l3jyOpDexSHsPhDDvHA2LadS83bg 0kG0sQJnYlE5pdz9ZuJ2dQWB1domp8acCEcLpCMY= 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.129.124]) by sourceware.org (Postfix) with ESMTPS id 75B583896C09 for ; Tue, 15 Nov 2022 14:31:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 75B583896C09 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-463-0L7XurPBMGO8YuzNnXDtMA-1; Tue, 15 Nov 2022 09:31:23 -0500 X-MC-Unique: 0L7XurPBMGO8YuzNnXDtMA-1 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id B419A8582B9; Tue, 15 Nov 2022 14:31:22 +0000 (UTC) Received: from localhost (unknown [10.33.36.199]) by smtp.corp.redhat.com (Postfix) with ESMTP id 7947A39D6A; Tue, 15 Nov 2022 14:31:22 +0000 (UTC) To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Fix detection of std::format support for __float128 [PR107693] Date: Tue, 15 Nov 2022 14:31:19 +0000 Message-Id: <20221115143119.1155190-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.5 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_H2, SPF_HELO_NONE, SPF_NONE, TXREP 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.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1749572951421457408?= X-GMAIL-MSGID: =?utf-8?q?1749572951421457408?= Tested x86_64-linux and x86_64-w64-mingw32. Pushed to trunk. -- >8 -- std::format gives linker errors on targets that define __float128 but do not support using it with std::to_chars. This improves the handling of 128-bit flaoting-point types so they are disabled if unsupportable. libstdc++-v3/ChangeLog: PR libstdc++/107693 * include/std/format (_GLIBCXX_FORMAT_F128): Define to 2 when basic_format_arg needs to use its _M_f128 member. (__extended_floating_point, __floating_point): Replace with ... (__formattable_floating_point): New concept. * testsuite/std/format/functions/format.cc: Check whether __float128 is supported. Also test _Float128. --- libstdc++-v3/include/std/format | 77 ++++++++++--------- .../testsuite/std/format/functions/format.cc | 20 ++++- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 1796362ceef..c79c8f2ce31 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -1213,40 +1213,35 @@ namespace __format _Spec<_CharT> _M_spec{}; }; + // Decide how 128-bit floating-point types should be formatted (or not). + // When supported, the typedef __format::__float128_t is the type that + // format arguments should be converted to for storage in basic_format_arg. + // Define the macro _GLIBCXX_FORMAT_F128 to say they're supported. + // _GLIBCXX_FORMAT_F128=1 means __float128, _Float128 etc. will be formatted + // by converting them to long double (or __ieee128 for powerpc64le). + // _GLIBCXX_FORMAT_F128=2 means basic_format_arg needs to enable explicit + // support for _Float128, rather than formatting it as another type. +#undef _GLIBCXX_FORMAT_F128 + #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT -# define _GLIBCXX_FORMAT_F128 1 + + // Format 128-bit floating-point types using __ieee128. using __float128_t = __ieee128; -#elif defined _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128 # define _GLIBCXX_FORMAT_F128 1 + +#elif defined _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128 + + // Format 128-bit floating-point types using long double. using __float128_t = long double; -#elif __FLT128_DIG__ -# define _GLIBCXX_FORMAT_F128 2 +# define _GLIBCXX_FORMAT_F128 1 + +#elif __FLT128_DIG__ && defined(__GLIBC_PREREQ) // see floating_to_chars.cc + + // Format 128-bit floating-point types using _Float128. using __float128_t = _Float128; -#else -# undef _GLIBCXX_FORMAT_F128 -#endif +# define _GLIBCXX_FORMAT_F128 2 -#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT - template - concept __extended_floating_point = __is_same(_Tp, _Float128) - || __is_same(_Tp, __ibm128) - || __is_same(_Tp, __ieee128); -#elif _GLIBCXX_FORMAT_F128 - template - concept __extended_floating_point = __is_same(_Tp, __float128_t); -#else - template - concept __extended_floating_point = false; -#endif - - template - concept __floating_point = std::floating_point<_Tp> - || __extended_floating_point<_Tp>; - - using std::to_chars; - -#if _GLIBCXX_FORMAT_F128 == 2 \ - && (__cplusplus == 202002L || !defined(_GLIBCXX_HAVE_FLOAT128_MATH)) +# if __cplusplus == 202002L || !defined(_GLIBCXX_HAVE_FLOAT128_MATH) // These overloads exist in the library, but are not declared for C++20. // Make them available as std::__format::to_chars. to_chars_result @@ -1260,8 +1255,16 @@ namespace __format to_chars_result to_chars(char*, char*, _Float128, chars_format, int) noexcept __asm("_ZSt8to_charsPcS_DF128_St12chars_formati"); +# endif #endif + using std::to_chars; + + // We can format a floating-point type iff it is usable with to_chars. + template + concept __formattable_float = requires (_Tp __t, char* __p) + { __format::to_chars(__p, __p, __t, chars_format::scientific, 6); }; + template<__char _CharT> struct __formatter_fp { @@ -1984,7 +1987,7 @@ namespace __format #endif /// Format a floating-point value. - template<__format::__floating_point _Tp, __format::__char _CharT> + template<__format::__formattable_float _Tp, __format::__char _CharT> struct formatter<_Tp, _CharT> { formatter() = default; @@ -2607,7 +2610,7 @@ namespace __format #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT __ieee128 _M_f128; __ibm128 _M_ibm128; -#elif _GLIBCXX_FORMAT_F128 +#elif _GLIBCXX_FORMAT_F128 == 2 __float128_t _M_f128; #endif }; @@ -2663,7 +2666,7 @@ namespace __format else if constexpr (is_same_v<_Tp, unsigned __int128>) return __u._M_u128; #endif -#if _GLIBCXX_FORMAT_F128 +#if _GLIBCXX_FORMAT_F128 == 2 else if constexpr (is_same_v<_Tp, __float128_t>) return __u._M_f128; #endif @@ -2843,13 +2846,15 @@ namespace __format return type_identity<_Float64>(); # endif #endif -#ifdef __FLT128_DIG__ +#if _GLIBCXX_FORMAT_F128 +# if __FLT128_DIG__ else if constexpr (is_same_v<_Td, _Float128>) return type_identity<__format::__float128_t>(); -#endif -#if _GLIBCXX_USE_FLOAT128 +# endif +# if __SIZEOF_FLOAT128__ else if constexpr (is_same_v<_Td, __float128>) return type_identity<__format::__float128_t>(); +# endif #endif else if constexpr (__is_specialization_of<_Td, basic_string_view>) return type_identity>(); @@ -2926,7 +2931,7 @@ namespace __format else if constexpr (is_same_v<_Tp, _Float64>) return _Arg_f64; #endif -#if _GLIBCXX_FORMAT_F128 +#if _GLIBCXX_FORMAT_F128 == 2 else if constexpr (is_same_v<_Tp, __format::__float128_t>) return _Arg_f128; #endif @@ -3015,7 +3020,7 @@ namespace __format #endif // TODO _Arg_f16 etc. -#if _GLIBCXX_FORMAT_F128 +#if _GLIBCXX_FORMAT_F128 == 2 case _Arg_f128: return std::forward<_Visitor>(__vis)(_M_val._M_f128); #endif diff --git a/libstdc++-v3/testsuite/std/format/functions/format.cc b/libstdc++-v3/testsuite/std/format/functions/format.cc index e9e61694f7d..165ef41b4b3 100644 --- a/libstdc++-v3/testsuite/std/format/functions/format.cc +++ b/libstdc++-v3/testsuite/std/format/functions/format.cc @@ -5,6 +5,7 @@ #include #include #include +#include #include void @@ -289,12 +290,27 @@ test_p1652r1() // printf corner cases in std::format VERIFY( s == "3.31" ); } +template +bool format_float() +{ + auto s = std::format("{:#} != {:<+7.3f}", (T)-0.0, (T)0.5); + return s == "-0. != +0.500 "; +} + void test_float128() { #ifdef __SIZEOF_FLOAT128__ - auto s = std::format("{:#} != {:<+7.3f}", (__float128)-0.0, (__float128)0.5); - VERIFY( s == "-0. != +0.500 " ); + if constexpr (std::formattable<__float128, char>) + VERIFY( format_float<__float128>() ); + else + std::puts("Cannot format __float128 on this target"); +#endif +#if __FLT128_DIG__ + if constexpr (std::formattable<_Float128, char>) + VERIFY( format_float<_Float128>() ); + else + std::puts("Cannot format _Float128 on this target"); #endif }