From patchwork Fri May 1 12:03:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1281217 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=qjq9Iz8c; dkim-atps=neutral Received: from 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 49D9rG3kssz9sTF for ; Fri, 1 May 2020 22:03:24 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 015393972430; Fri, 1 May 2020 12:03:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 015393972430 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1588334599; bh=qmiTli7AQmcdgOHbAFnAcgwTAF2MDwrxLgqBGEzMy8Y=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=qjq9Iz8cQ5ih6dHVWUx2F4cFEj27vqclKdKfwTP2nEeMJe575j574x3ILfY/a9Xiw HvKTkKK6DhikVbbxPU1wH58LDh8gVUz38SX24wlD7sYYBU2ylc/I9qBDwnSULJAwF5 +mHWZmInJfR/4eNQqg9gT7bpqZ2BYUwYBSR0krGE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [205.139.110.61]) by sourceware.org (Postfix) with ESMTP id A38C13938C12 for ; Fri, 1 May 2020 12:03:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org A38C13938C12 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-322-4aWcuIk5N2Wex9MdEiqlUg-1; Fri, 01 May 2020 08:03:12 -0400 X-MC-Unique: 4aWcuIk5N2Wex9MdEiqlUg-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6F938107ACF2; Fri, 1 May 2020 12:03:11 +0000 (UTC) Received: from localhost (unknown [10.33.36.241]) by smtp.corp.redhat.com (Postfix) with ESMTP id 07D4C6A942; Fri, 1 May 2020 12:03:10 +0000 (UTC) Date: Fri, 1 May 2020 13:03:10 +0100 To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH] libstdc++: Replace deduced return type in ranges::iter_move (PR 92894) Message-ID: <20200501120310.GA498115@redhat.com> MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-27.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, 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-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" The deduced return type causes the instantiation of the function body, which can then require the instantiation of std::projected::operator* which is intentionally not defined. This patch uses a helper trait to define the return type, so that the function body doesn't need to be instantiated. That helper trait can then also be used in other places that currently check the return type of ranges::iter_move (iter_rvalue_reference_t and indirectly_readable). 2020-05-01 Jonathan Wakely Patrick Palka PR libstdc++/92894 * include/bits/iterator_concepts.h (ranges::__cust_imove::_IMove): Add trait to determine return type and an alias for it. (ranges::__cust_imove::_IMove::operator()): Use __result instead of deduced return type. (iter_rvalue_reference_t): Use _IMove::__type instead of checking the result of ranges::iter_move. (__detail::__indirectly_readable_impl): Use iter_rvalue_reference_t instead of checking the result of ranges::iter_move. * testsuite/24_iterators/indirect_callable/92894.cc: New test. Patrick, I prefer this to the patch you added to the bug. Avoiding doing overload resolution on ranges::iter_move(x) seems worthwhile. What do you think? I *think* the changes to __indirectly_readable_impl are equivalent. As far as I can tell, the point of the original { *in } and { ranges::iter_move(in) } constraints are to check that const In and In do the same thing. We could leave the { *in } on, but for consistency it seems better to change both. commit 312bf4457effa0ce99c7c4cb0ebe5e3fb0fd3747 Author: Jonathan Wakely Date: Fri May 1 10:50:50 2020 +0100 libstdc++: Replace deduced return type in ranges::iter_move (PR 92894) The deduced return type causes the instantiation of the function body, which can then require the instantiation of std::projected::operator* which is intentionally not defined. This patch uses a helper trait to define the return type, so that the function body doesn't need to be instantiated. That helper trait can then also be used in other places that currently check the return type of ranges::iter_move (iter_rvalue_reference_t and indirectly_readable). 2020-05-01 Jonathan Wakely Patrick Palka PR libstdc++/92894 * include/bits/iterator_concepts.h (ranges::__cust_imove::_IMove): Add trait to determine return type and an alias for it. (ranges::__cust_imove::_IMove::operator()): Use __result instead of deduced return type. (iter_rvalue_reference_t): Use _IMove::__type instead of checking the result of ranges::iter_move. (__detail::__indirectly_readable_impl): Use iter_rvalue_reference_t instead of checking the result of ranges::iter_move. * testsuite/24_iterators/indirect_callable/92894.cc: New test. diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index b598532089e..d84e8639ea8 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -89,6 +89,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct _IMove { private: + template + struct __result + { using type = iter_reference_t<_Tp>; }; + + template + requires __adl_imove<_Tp> + struct __result<_Tp> + { using type = decltype(iter_move(std::declval<_Tp>())); }; + + template + requires (!__adl_imove<_Tp>) + && is_lvalue_reference_v> + struct __result<_Tp> + { using type = remove_reference_t>&&; }; + template static constexpr bool _S_noexcept() @@ -100,16 +115,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } public: - template - requires __adl_imove<_Tp> || requires(_Tp& __e) { *__e; } - constexpr decltype(auto) + // The result type of iter_move(std::declval<_Tp>()) + template + using __type = typename __result<_Tp>::type; + + template + constexpr __type<_Tp> operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) { if constexpr (__adl_imove<_Tp>) return iter_move(static_cast<_Tp&&>(__e)); - else if constexpr (is_reference_v>) - return std::move(*__e); + else if constexpr (is_lvalue_reference_v>) + return static_cast<__type<_Tp>>(*__e); else return *__e; } @@ -123,10 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } // namespace ranges template<__detail::__dereferenceable _Tp> - requires requires(_Tp& __t) - { { ranges::iter_move(__t) } -> __detail::__can_reference; } + requires __detail::__can_reference> using iter_rvalue_reference_t - = decltype(ranges::iter_move(std::declval<_Tp&>())); + = ranges::__cust_imove::_IMove::__type<_Tp&>; template struct incrementable_traits { }; @@ -448,8 +465,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename iter_value_t<_In>; typename iter_reference_t<_In>; typename iter_rvalue_reference_t<_In>; - { *__in } -> same_as>; - { ranges::iter_move(__in) } -> same_as>; + requires same_as, + iter_reference_t<_In>>; + requires same_as, + iter_rvalue_reference_t<_In>>; } && common_reference_with&&, iter_value_t<_In>&> && common_reference_with&&, diff --git a/libstdc++-v3/testsuite/24_iterators/indirect_callable/92894.cc b/libstdc++-v3/testsuite/24_iterators/indirect_callable/92894.cc new file mode 100644 index 00000000000..78c4585923f --- /dev/null +++ b/libstdc++-v3/testsuite/24_iterators/indirect_callable/92894.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2020 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++2a" } +// { dg-do compile { target c++2a } } + +#include + +using std::projected; +using std::identity; +using std::indirect_unary_predicate; + +template> Pred> + constexpr void + all_of(T*, Pred) + { } + +void +test01() +{ + // PR libstdc++/92894 + struct X { }; + X x; + all_of(&x, [](X&) { return false; }); +} + +using std::iterator_t; +using std::ranges::input_range; +using std::ranges::borrowed_range; + +template, Proj>> Pred> + constexpr borrowed_iterator_t + find_if(R&& r, Pred pred, Proj proj = {}) + { } + +void +test02() +{ + // PR 94241 + struct s { int m; }; + s r[] = { s{0}, s{1}, s{2}, s{3} }; + find_if(r, [](auto const) { return true; }); +}