From patchwork Wed Jul 19 22:43:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 122867 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c923:0:b0:3e4:2afc:c1 with SMTP id j3csp2751448vqt; Wed, 19 Jul 2023 15:44:57 -0700 (PDT) X-Google-Smtp-Source: APBJJlEf3XTqas7s81cnL6mQlPDdStYNV/fXlJUfQOqeycUhgUN7NLnjFI0+tVhQIAsbmMz1J67V X-Received: by 2002:a17:906:7a5a:b0:993:d53b:9805 with SMTP id i26-20020a1709067a5a00b00993d53b9805mr793284ejo.11.1689806697065; Wed, 19 Jul 2023 15:44:57 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1689806697; cv=none; d=google.com; s=arc-20160816; b=aSIldFb9COTTi93P1Kkfr7Ki8M3qv/TPG+ELx4hztoLlQaF6hcn3cPl1ChtOqtkfW5 qw4reMbmwIu0q1VwILqQUdn58t5w+I0tSY0pjlrt+BBpK/SJOf5O29c6NwUYKU/BAeWY Iuv2y45len1Oeg6O9mxKKPnI661giQNFKTAb6F8pLKcjhZGXzs0v+212HZLlZsGg7hx5 JIOigIUIKvfmcnfsj4Kgy3MxrOWqWLYUH6uFrExeF2YSERtyLgL9w8zoIBNOpVFoKEnI g09pdgsnDPWNnCtXBxZC/jHuCuA+igA6v+Hzm3PEZNH7NQ3dh5upEpwJIKShl+z5YluZ MoUQ== 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=Ah0tyGVmCEt6GPaJLYUJtbYYyHJIi7kNEIyT4Y4JDiA=; fh=sC8lnOfyH6gL5FYlMbZ1VDz6qVPMj/3ViLJWKNUCUgQ=; b=08n31FOcAOdpRJfNSgzu/doBe/22euaOyN3qzwm+zo32x4/tUdjF4uxAy83iyHD847 mvjOr6V8MbhdoXTUFgRZr5I+o712DUxBMsJzsQVJ0dg0pzQZZj2sEAkKBGM9Q9+b6rmU LZNIRPY7/spcf6GTK8BzNuKXUis3dQvbONlji7zaCMh2F/R2bQHiqBoluctaOpxH/kyH 8PCQMRCJdpwA0tHbnYYbjVBzas/IElULvu7M0njC8vPEqKsXU0TDCBKDgOQkbmiA6tQU MO+xv0c6EGG0uz5ZOvI3ICiW1OGtWNJtAYIA+w8dw/4DSQv2vNetip0/0w9wJj/qg664 oSGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=dY7kmzdU; 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 (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id ke26-20020a17090798fa00b00986631b58d2si3526348ejc.837.2023.07.19.15.44.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Jul 2023 15:44:57 -0700 (PDT) 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=dY7kmzdU; 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 A09AF385C6F4 for ; Wed, 19 Jul 2023 22:44:12 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A09AF385C6F4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1689806652; bh=Ah0tyGVmCEt6GPaJLYUJtbYYyHJIi7kNEIyT4Y4JDiA=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=dY7kmzdUbBpSoBPnu4WqBGcPaevUxrKt8kORl/g7oXeuF5ndHd9VvA7be1I/KCaKM /M1cXLFLuQQpOhHrpjhbalYe0Rqgib5j4zHmzO6sOuVTcGlsfQmTBF2FPfT38TmRKX Pt1g2Cz78qbfoTXNgI1Hw1RnDUm/+iRu49U460Ig= 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 7E83F385C6DF for ; Wed, 19 Jul 2023 22:43:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7E83F385C6DF 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-86-rgyX0FakNc-ZK27QvFBjWQ-1; Wed, 19 Jul 2023 18:43:19 -0400 X-MC-Unique: rgyX0FakNc-ZK27QvFBjWQ-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 774198F1840; Wed, 19 Jul 2023 22:43:19 +0000 (UTC) Received: from localhost (unknown [10.42.28.140]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3ACC31121314; Wed, 19 Jul 2023 22:43:19 +0000 (UTC) To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Check for std::ratio in arithmetic and comparisons [PR110593] Date: Wed, 19 Jul 2023 23:43:05 +0100 Message-ID: <20230719224318.2599563-1-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.3 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.3 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_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham 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: INBOX X-GMAIL-THRID: 1771890747420909387 X-GMAIL-MSGID: 1771890747420909387 Tested x86_64-linux. Pushed to trunk. -- >8 -- The standard says that it should be ill-formed to use std::ratio_equal etc. with types which are not specializations of std::ratio. This implements that requirement. We don't need to add assertions to every one of the class templates, because many of them are implemented in terms of other ones. For example, ratio_divide and ratio_subtract can rely on the assertions in ratio_multiply and ratio_add respectively. libstdc++-v3/ChangeLog: PR libstdc++/110593 * include/bits/chrono.h (duration): Improve static assert messages. (__is_ratio): Move to ... * include/std/ratio (__is_ratio): ... here. (__is_ratio_v): New variable template and partial specialization. (__are_both_ratios): New function template. (__ratio_multiply, ratio_equal, ratio_less, __ratio_add): Add static assertion. * testsuite/20_util/ratio/requirements/type_constraints.cc: New test. * testsuite/20_util/duration/requirements/typedefs_neg1.cc: Adjust expected error. * testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise. --- libstdc++-v3/include/bits/chrono.h | 19 ++----- libstdc++-v3/include/std/ratio | 53 +++++++++++++++++-- .../duration/requirements/typedefs_neg1.cc | 2 +- .../duration/requirements/typedefs_neg2.cc | 2 +- .../ratio/requirements/type_constraints.cc | 34 ++++++++++++ 5 files changed, 87 insertions(+), 23 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/ratio/requirements/type_constraints.cc diff --git a/libstdc++-v3/include/bits/chrono.h b/libstdc++-v3/include/bits/chrono.h index 81b92d724f7..e9490767c56 100644 --- a/libstdc++-v3/include/bits/chrono.h +++ b/libstdc++-v3/include/bits/chrono.h @@ -505,26 +505,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return numeric_limits<_Rep>::lowest(); } }; - /// @cond undocumented - - template - struct __is_ratio - : std::false_type - { }; - - template - struct __is_ratio> - : std::true_type - { }; - - /// @endcond - template class duration { - static_assert(!__is_duration<_Rep>::value, "rep cannot be a duration"); + static_assert(!__is_duration<_Rep>::value, + "rep cannot be a std::chrono::duration"); static_assert(__is_ratio<_Period>::value, - "period must be a specialization of ratio"); + "period must be a specialization of std::ratio"); static_assert(_Period::num > 0, "period must be positive"); template diff --git a/libstdc++-v3/include/std/ratio b/libstdc++-v3/include/std/ratio index 183f1aeda11..1d285bf916f 100644 --- a/libstdc++-v3/include/std/ratio +++ b/libstdc++-v3/include/std/ratio @@ -289,9 +289,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented + template + struct __is_ratio + : std::false_type + { }; + + template + struct __is_ratio> + : std::true_type + { }; + +#if __cpp_variable_templates + template + constexpr bool __is_ratio_v = false; + template + constexpr bool __is_ratio_v> = true; +#endif + + template + constexpr bool + __are_both_ratios() noexcept + { +#if __cpp_variable_templates && __cpp_if_constexpr + if constexpr (__is_ratio_v<_R1>) + if constexpr (__is_ratio_v<_R2>) + return true; + return false; +#else + return __and_<__is_ratio<_R1>, __is_ratio<_R2>>::value; +#endif + } + template struct __ratio_multiply { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + private: static const intmax_t __gcd1 = __static_gcd<_R1::num, _R2::den>::value; @@ -356,7 +390,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct ratio_equal : integral_constant - { }; + { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + }; /// ratio_not_equal template @@ -402,7 +439,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct ratio_less : __ratio_less_impl<_R1, _R2>::type - { }; + { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + }; /// ratio_less_equal template @@ -430,13 +470,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline constexpr bool ratio_less_v = ratio_less<_R1, _R2>::value; template - inline constexpr bool ratio_less_equal_v = - ratio_less_equal<_R1, _R2>::value; + inline constexpr bool ratio_less_equal_v + = ratio_less_equal<_R1, _R2>::value; template inline constexpr bool ratio_greater_v = ratio_greater<_R1, _R2>::value; template inline constexpr bool ratio_greater_equal_v - = ratio_greater_equal<_R1, _R2>::value; + = ratio_greater_equal<_R1, _R2>::value; #endif // C++17 /// @cond undocumented @@ -513,6 +553,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __ratio_add { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + typedef typename __ratio_add_impl<_R1, _R2>::type type; static constexpr intmax_t num = type::num; static constexpr intmax_t den = type::den; diff --git a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc index 49c9fe77168..1a1188b2a2f 100644 --- a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc +++ b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc @@ -29,4 +29,4 @@ void test01() test_type d; // { dg-error "required from here" } } -// { dg-error "rep cannot be a duration" "" { target *-*-* } 0 } +// { dg-error "rep cannot be a std::chrono::duration" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc index 23c5d479b1f..cbdb7af0c65 100644 --- a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc +++ b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc @@ -30,7 +30,7 @@ void test01() test_type d; // { dg-error "required from here" } } -// { dg-error "must be a specialization of ratio" "" { target *-*-* } 0 } +// { dg-error "must be a specialization of std::ratio" "" { target *-*-* } 0 } // { dg-prune-output "'num' is not a member of 'int'" } // { dg-prune-output "'den' is not a member of 'int'" } // { dg-prune-output "'int' is not a class, struct, or union type" } diff --git a/libstdc++-v3/testsuite/20_util/ratio/requirements/type_constraints.cc b/libstdc++-v3/testsuite/20_util/ratio/requirements/type_constraints.cc new file mode 100644 index 00000000000..ebf09bc8f07 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/requirements/type_constraints.cc @@ -0,0 +1,34 @@ +// { dg-do compile { target c++11 } } + +// C++11 20.10.1 [ratio.general] +// if the template argument types R1 and R2 are not specializations of the +// ratio template, the program is ill-formed. + +#include + +using namespace std; + +// A type that looks like std::ratio but isn't. +template struct Ratty { static constexpr int num = 1, den = 1; }; + +using T1 = ratio_add, Ratty<1>>::type; // { dg-error "here" } +using T2 = ratio_subtract, Ratty<3>>::type; // { dg-error "here" } +using T3 = ratio_multiply, Ratty<3>>::type; // { dg-error "here" } +using T4 = ratio_divide, Ratty<4>>::type; // { dg-error "here" } +using T5 = ratio_equal, Ratty<5>>::type; // { dg-error "here" } +using T6 = ratio_not_equal, Ratty<6>>::type; // { dg-error "here" } +using T7 = ratio_less, Ratty<7>>::type; // { dg-error "here" } +using T8 = ratio_less_equal, Ratty<8>>::type; // { dg-error "here" } +using T9 = ratio_greater, Ratty<9>>::type; // { dg-error "here" } +using T10 = ratio_greater_equal, Ratty<10>>::type; // { dg-error "here" } + +#if __cplusplus >= 201703L +bool B11 = ratio_equal_v, Ratty<11>>; // { dg-error "here" "" { target c++17 } } +bool B12 = ratio_not_equal_v, Ratty<12>>; // { dg-error "here" "" { target c++17 } } +bool B13 = ratio_less_v, Ratty<13>>; // { dg-error "here" "" { target c++17 } } +bool B14 = ratio_less_equal_v, Ratty<14>>; // { dg-error "here" "" { target c++17 } } +bool B15 = ratio_greater_v, Ratty<15>>; // { dg-error "here" "" { target c++17 } } +bool B16 = ratio_greater_equal_v, Ratty<16>>; // { dg-error "here" "" { target c++17 } } +#endif + +// { dg-error "static assertion failed" "" { target *-*-* } 0 }