From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by sourceware.org (Postfix) with ESMTP id 3AD5F397283C for ; Wed, 10 Mar 2021 15:28:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 3AD5F397283C Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-576-8ljJ5cy-OXeMr5CIMFwipA-1; Wed, 10 Mar 2021 10:28:38 -0500 X-MC-Unique: 8ljJ5cy-OXeMr5CIMFwipA-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id A016851EF; Wed, 10 Mar 2021 15:28:37 +0000 (UTC) Received: from localhost (unknown [10.33.37.30]) by smtp.corp.redhat.com (Postfix) with ESMTP id 358FD60240; Wed, 10 Mar 2021 15:28:36 +0000 (UTC) Date: Wed, 10 Mar 2021 15:28:36 +0000 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Implement LWG 3530 for concept-constrained comparisons Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: multipart/mixed; boundary="gB4Di72VpvlpPoNz" Content-Disposition: inline X-Spam-Status: No, score=-14.3 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) 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-List-Received-Date: Wed, 10 Mar 2021 15:28:43 -0000 --gB4Di72VpvlpPoNz Content-Type: text/plain; charset=us-ascii Content-Disposition: inline The proposed resolution for this library issue simplifies the constraints for compare_three_way, ranges::equal_to, ranges::less etc. so that they do not work with types which are convertible to pointers but which fail to meet the usual syntactic requirements for the comparisons. This affects the example in PR libstdc++/93628 but doesn't fix the problem described in that report. libstdc++-v3/ChangeLog: * include/bits/ranges_cmp.h (__eq_builtin_ptr_cmp): Remove. (ranges::equal_to, ranges::not_equal_to): Do not constrain with __eq_builtin_ptr_cmp. (ranges::less, ranges::greater, ranges::less_equal) (ranges::greater_equal): Do not constrain with __less_builtin_ptr_cmp. * libsupc++/compare (compare_three_way): Do not constrain with __3way_builtin_ptr_cmp. * testsuite/18_support/comparisons/object/builtin-ptr-three-way.cc: Moved to... * testsuite/18_support/comparisons/object/lwg3530.cc: ...here. * testsuite/20_util/function_objects/range.cmp/lwg3530.cc: New test. Tested powerpc64le-linux. Committed to trunk. --gB4Di72VpvlpPoNz Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="patch.txt" commit dddd011113b6ceede733d7ae33eca695c06b181b Author: Jonathan Wakely Date: Wed Mar 10 15:27:06 2021 libstdc++: Implement LWG 3530 for concept-constrained comparisons The proposed resolution for this library issue simplifies the constraints for compare_three_way, ranges::equal_to, ranges::less etc. so that they do not work with types which are convertible to pointers but which fail to meet the usual syntactic requirements for the comparisons. This affects the example in PR libstdc++/93628 but doesn't fix the problem described in that report. libstdc++-v3/ChangeLog: * include/bits/ranges_cmp.h (__eq_builtin_ptr_cmp): Remove. (ranges::equal_to, ranges::not_equal_to): Do not constrain with __eq_builtin_ptr_cmp. (ranges::less, ranges::greater, ranges::less_equal) (ranges::greater_equal): Do not constrain with __less_builtin_ptr_cmp. * libsupc++/compare (compare_three_way): Do not constrain with __3way_builtin_ptr_cmp. * testsuite/18_support/comparisons/object/builtin-ptr-three-way.cc: Moved to... * testsuite/18_support/comparisons/object/lwg3530.cc: ...here. * testsuite/20_util/function_objects/range.cmp/lwg3530.cc: New test. diff --git a/libstdc++-v3/include/bits/ranges_cmp.h b/libstdc++-v3/include/bits/ranges_cmp.h index d6880714966..3f71d31e5a6 100644 --- a/libstdc++-v3/include/bits/ranges_cmp.h +++ b/libstdc++-v3/include/bits/ranges_cmp.h @@ -62,19 +62,9 @@ namespace ranges { namespace __detail { - // BUILTIN-PTR-CMP(T, ==, U) - template - concept __eq_builtin_ptr_cmp - = requires (_Tp&& __t, _Up&& __u) { { __t == __u } -> same_as; } - && convertible_to<_Tp, const volatile void*> - && convertible_to<_Up, const volatile void*> - && (! requires(_Tp&& __t, _Up&& __u) - { operator==(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } - && - ! requires(_Tp&& __t, _Up&& __u) - { std::forward<_Tp>(__t).operator==(std::forward<_Up>(__u)); }); - // BUILTIN-PTR-CMP(T, <, U) + // This determines whether t < u results in a call to a built-in operator< + // comparing pointers. It doesn't work for function pointers (PR 93628). template concept __less_builtin_ptr_cmp = requires (_Tp&& __t, _Up&& __u) { { __t < __u } -> same_as; } @@ -88,12 +78,14 @@ namespace ranges // [range.cmp] Concept-constrained comparisons + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3530 BUILTIN-PTR-MEOW should not opt the type out of syntactic checks + /// ranges::equal_to function object type. struct equal_to { template requires equality_comparable_with<_Tp, _Up> - || __detail::__eq_builtin_ptr_cmp<_Tp, _Up> constexpr bool operator()(_Tp&& __t, _Up&& __u) const noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) @@ -107,7 +99,6 @@ namespace ranges { template requires equality_comparable_with<_Tp, _Up> - || __detail::__eq_builtin_ptr_cmp<_Tp, _Up> constexpr bool operator()(_Tp&& __t, _Up&& __u) const noexcept(noexcept(std::declval<_Up>() == std::declval<_Tp>())) @@ -121,7 +112,6 @@ namespace ranges { template requires totally_ordered_with<_Tp, _Up> - || __detail::__less_builtin_ptr_cmp<_Tp, _Up> constexpr bool operator()(_Tp&& __t, _Up&& __u) const noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) @@ -150,7 +140,6 @@ namespace ranges { template requires totally_ordered_with<_Tp, _Up> - || __detail::__less_builtin_ptr_cmp<_Up, _Tp> constexpr bool operator()(_Tp&& __t, _Up&& __u) const noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) @@ -164,7 +153,6 @@ namespace ranges { template requires totally_ordered_with<_Tp, _Up> - || __detail::__less_builtin_ptr_cmp<_Tp, _Up> constexpr bool operator()(_Tp&& __t, _Up&& __u) const noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) @@ -178,7 +166,6 @@ namespace ranges { template requires totally_ordered_with<_Tp, _Up> - || __detail::__less_builtin_ptr_cmp<_Up, _Tp> constexpr bool operator()(_Tp&& __t, _Up&& __u) const noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index 7025f597db8..82d00889272 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -479,6 +479,9 @@ namespace std namespace __detail { // BUILTIN-PTR-THREE-WAY(T, U) + // This determines whether t <=> u results in a call to a built-in + // operator<=> comparing pointers. It doesn't work for function pointers + // (PR 93628). template concept __3way_builtin_ptr_cmp = requires(_Tp&& __t, _Up&& __u) @@ -491,12 +494,14 @@ namespace std { static_cast<_Tp&&>(__t).operator<=>(static_cast<_Up&&>(__u)); }; } // namespace __detail + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3530 BUILTIN-PTR-MEOW should not opt the type out of syntactic checks + // [cmp.object], typename compare_three_way struct compare_three_way { template requires three_way_comparable_with<_Tp, _Up> - || __detail::__3way_builtin_ptr_cmp<_Tp, _Up> constexpr auto operator()(_Tp&& __t, _Up&& __u) const noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>())) diff --git a/libstdc++-v3/testsuite/18_support/comparisons/object/builtin-ptr-three-way.cc b/libstdc++-v3/testsuite/18_support/comparisons/object/lwg3530.cc similarity index 79% rename from libstdc++-v3/testsuite/18_support/comparisons/object/builtin-ptr-three-way.cc rename to libstdc++-v3/testsuite/18_support/comparisons/object/lwg3530.cc index 823aa1af9b5..103fe4c9130 100644 --- a/libstdc++-v3/testsuite/18_support/comparisons/object/builtin-ptr-three-way.cc +++ b/libstdc++-v3/testsuite/18_support/comparisons/object/lwg3530.cc @@ -20,6 +20,11 @@ #include +template + concept comparable = requires (const C& cmp, const T& t, const U& u) { + cmp(t, u); + }; + void test01() { @@ -39,7 +44,9 @@ test01() long l; // But <=> is valid and resolves to a builtin operator comparing pointers: - auto c = &l <=> x; - // So std::compare_three_way should be usable: - auto c2 = std::compare_three_way()(&l, x); + [[maybe_unused]] auto c = &l <=> x; + + // But LWG 3530 says std::compare_three_way should not be usable: + static_assert( ! comparable ); + static_assert( ! comparable ); } diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/lwg3530.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/lwg3530.cc new file mode 100644 index 00000000000..cd9664678cf --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/lwg3530.cc @@ -0,0 +1,47 @@ +// Copyright (C) 2021 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++20" } +// { dg-do compile { target c++20 } } + +#include + +struct S { + constexpr operator int*() const { return nullptr; } +}; + +void operator!=(S const&, S const&) {} +void operator>=(S const&, S const&) {} + +// S can be compared via conversion to int* +static_assert(S{} == S{}); +static_assert(S{} <= S{}); +// But concept not satisfied because operator!= returns void +static_assert(!std::equality_comparable_with); +// But concept not satisfied because operator>= returns void +static_assert(!std::totally_ordered); + +template + concept comparable = requires (const C& cmp, const T& t) { cmp(t, t); }; + +// LWG 3530 says [range.cmp] comparisons should not work for S +static_assert( ! comparable ); +static_assert( ! comparable ); +static_assert( ! comparable ); +static_assert( ! comparable ); +static_assert( ! comparable ); +static_assert( ! comparable ); --gB4Di72VpvlpPoNz--