From patchwork Thu Feb 20 13:58:44 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1241440 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=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-519854-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=J9M8266b; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=hkZhP7UV; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 48NbmS2SJLz9sR4 for ; Fri, 21 Feb 2020 00:59:02 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=gddCG9eVOmcWkNkVtOP4nV8DToJUBHxGDvgDU010PY338hvL/kSHi +fKlXoHRQlyk3uAK+vLNF5Va6rItcPIuDxerlO8PVIzBpEqL0sq7m/fi7E38FAHS frm6wesrBz1orVLWiWbnLJqcTt5kfNAWumlGiDUwKFvxhmNGXB23cg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=0yiUn3DYzhDuSE5yEzcS2jPO94I=; b=J9M8266bfgEOljFbkD/E HZUwGXONQIr2McwFVb9F+0BsNk1tKK/er+xXq3jxdu4k2pT2NPZVEbvhuaryE+z3 1X0be1KdKxIvqrlbws47yWjZGPcWCvYk7dpEnkgkGp6eCAf0GS5Xq6g224sXx2hP yNFhE4I+gv4p6DSms+UwfPA= Received: (qmail 39667 invoked by alias); 20 Feb 2020 13:58:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 39658 invoked by uid 89); 20 Feb 2020 13:58:53 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-18.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 spammy= X-HELO: us-smtp-1.mimecast.com Received: from us-smtp-delivery-1.mimecast.com (HELO us-smtp-1.mimecast.com) (205.139.110.120) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 20 Feb 2020 13:58:51 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1582207129; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type; bh=jLgqDW51LhN08jJV0esh6OpIryj9X6yT6Twv1pVz5tk=; b=hkZhP7UViIFskUDUbgaT2VUK0kAPjVJ9GIQH/WfzIGI1KAs8G/kv1phSJyIIdX/d/evNjg EC+oBgwT/uw1b8f4ajiJ+Z4YzZZF7HpeWpFfJxDojIrwIpgW4NIEOER1eFWUl0vRUL3hhG TZNLKN8mJlZNVW5EJ0YWwX+mBHRqf54= 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-242-SBku2YdSOay_TlnZJqTNGA-1; Thu, 20 Feb 2020 08:58:46 -0500 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 7F903805752; Thu, 20 Feb 2020 13:58:45 +0000 (UTC) Received: from localhost (unknown [10.33.36.96]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2932A60BE1; Thu, 20 Feb 2020 13:58:44 +0000 (UTC) Date: Thu, 20 Feb 2020 13:58:44 +0000 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Issues with range access CPOs (P2091R0) Message-ID: <20200220135844.GA1862757@redhat.com> MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline This changes how arrays of unknown bound and/or incomplete element type are handled. * include/bits/range_access.h (ranges::begin): Reject array of incomplete type. (ranges::end, ranges::size): Require arrays to be bounded. (ranges::data): Require lvalue or borrowed_range. (ranges::iterator_t): Remove constraint. * testsuite/std/ranges/access/begin.cc: Do not check array of incomplete type. * testsuite/std/ranges/access/begin_neg.cc: New test. * testsuite/std/ranges/access/end_neg.cc: Adjust expected error. * testsuite/std/ranges/access/size_neg.cc: Adjust expected error. * testsuite/std/ranges/access/ssize.cc: Do not check array of incomplete type. Tested powerpc64le-linux, committed to master. commit e817c23f6806a6b9201a0a1f77b51cb863af51e9 Author: Jonathan Wakely Date: Thu Feb 20 13:20:44 2020 +0000 libstdc++: Issues with range access CPOs (P2091R0) This changes how arrays of unknown bound and/or incomplete element type are handled. * include/bits/range_access.h (ranges::begin): Reject array of incomplete type. (ranges::end, ranges::size): Require arrays to be bounded. (ranges::data): Require lvalue or borrowed_range. (ranges::iterator_t): Remove constraint. * testsuite/std/ranges/access/begin.cc: Do not check array of incomplete type. * testsuite/std/ranges/access/begin_neg.cc: New test. * testsuite/std/ranges/access/end_neg.cc: Adjust expected error. * testsuite/std/ranges/access/size_neg.cc: Adjust expected error. * testsuite/std/ranges/access/ssize.cc: Do not check array of incomplete type. diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h index e7a19305d23..eb91ade35ff 100644 --- a/libstdc++-v3/include/bits/range_access.h +++ b/libstdc++-v3/include/bits/range_access.h @@ -382,8 +382,8 @@ namespace ranges { __decay_copy(__t.begin()) } -> input_or_output_iterator; }; - template void begin(_Tp&&) = delete; - template void begin(initializer_list<_Tp>&&) = delete; + void begin(auto&) = delete; + void begin(const auto&) = delete; template concept __adl_begin = __class_or_enum> @@ -417,7 +417,9 @@ namespace ranges if constexpr (is_array_v>) { static_assert(is_lvalue_reference_v<_Tp>); - return __t; + using _Up = remove_all_extents_t>; + static_assert(sizeof(_Up) != 0, "not array of incomplete type"); + return __t + 0; } else if constexpr (__member_begin<_Tp>) return __t.begin(); @@ -433,8 +435,8 @@ namespace ranges -> sentinel_for(__t)))>; }; - template void end(_Tp&&) = delete; - template void end(initializer_list<_Tp>&&) = delete; + void end(auto&) = delete; + void end(const auto&) = delete; template concept __adl_end = __class_or_enum> @@ -451,7 +453,7 @@ namespace ranges static constexpr bool _S_noexcept() { - if constexpr (is_array_v>) + if constexpr (is_bounded_array_v>) return true; else if constexpr (__member_end<_Tp>) return noexcept(__decay_copy(std::declval<_Tp&>().end())); @@ -461,15 +463,14 @@ namespace ranges public: template<__maybe_borrowed_range _Tp> - requires is_array_v> || __member_end<_Tp> + requires is_bounded_array_v> || __member_end<_Tp> || __adl_end<_Tp> constexpr auto operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) { - if constexpr (is_array_v>) + if constexpr (is_bounded_array_v>) { static_assert(is_lvalue_reference_v<_Tp>); - static_assert(is_bounded_array_v>); return __t + extent_v>; } else if constexpr (__member_end<_Tp>) @@ -519,7 +520,8 @@ namespace ranges { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; }; - template void rbegin(_Tp&&) = delete; + void rbegin(auto&) = delete; + void rbegin(const auto&) = delete; template concept __adl_rbegin = __class_or_enum> @@ -582,7 +584,8 @@ namespace ranges -> sentinel_for; }; - template void rend(_Tp&&) = delete; + void rend(auto&) = delete; + void rend(const auto&) = delete; template concept __adl_rend = __class_or_enum> @@ -664,7 +667,8 @@ namespace ranges -> __detail::__is_integer_like; }; - template void size(_Tp&&) = delete; + void size(auto&) = delete; + void size(const auto&) = delete; template concept __adl_size = __class_or_enum> @@ -691,7 +695,7 @@ namespace ranges static constexpr bool _S_noexcept() { - if constexpr (is_array_v>) + if constexpr (is_bounded_array_v>) return true; else if constexpr (__member_size<_Tp>) return noexcept(__decay_copy(std::declval<_Tp>().size())); @@ -704,14 +708,13 @@ namespace ranges public: template - requires is_array_v> + requires is_bounded_array_v> || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp> constexpr auto operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) { - if constexpr (is_array_v>) + if constexpr (is_bounded_array_v>) { - static_assert(is_bounded_array_v>); return extent_v>; } else if constexpr (__member_size<_Tp>) @@ -826,7 +829,8 @@ namespace ranges } public: - template requires __member_data<_Tp> || __begin_data<_Tp> + template<__maybe_borrowed_range _Tp> + requires __member_data<_Tp> || __begin_data<_Tp> constexpr auto operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) { @@ -881,8 +885,8 @@ namespace ranges concept borrowed_range = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>; - template - using iterator_t = decltype(ranges::begin(std::declval<_Range&>())); + template + using iterator_t = decltype(ranges::begin(std::declval<_Tp&>())); template using sentinel_t = decltype(ranges::end(std::declval<_Range&>())); diff --git a/libstdc++-v3/testsuite/std/ranges/access/begin.cc b/libstdc++-v3/testsuite/std/ranges/access/begin.cc index b6801552c60..9cbdfe25a22 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/begin.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/begin.cc @@ -36,10 +36,10 @@ test01() constexpr long b[2] = { }; static_assert( std::ranges::begin(b) == (b + 0) ); - struct Incomplete; - using A = Incomplete[]; // unbounded array of incomplete type + struct X { }; + using A = X[]; // unbounded array extern A& f(); - static_assert( same_as ); + static_assert( same_as ); } void diff --git a/libstdc++-v3/testsuite/std/ranges/access/begin_neg.cc b/libstdc++-v3/testsuite/std/ranges/access/begin_neg.cc new file mode 100644 index 00000000000..f31428526f3 --- /dev/null +++ b/libstdc++-v3/testsuite/std/ranges/access/begin_neg.cc @@ -0,0 +1,39 @@ +// 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 + +auto +test01() +{ + using A = int[2]; + extern A&& f(); // rvalue of type that doesn't satisfy borrowed_range + return std::ranges::begin(f()); // { dg-error "no match" } +} + +struct incomplete; +extern incomplete array[2]; + +auto +test02() +{ + return std::ranges::begin(array); // { dg-error "here" } +} +// { dg-error "incomplete type" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/std/ranges/access/end_neg.cc b/libstdc++-v3/testsuite/std/ranges/access/end_neg.cc index 3f690faa73d..e16f684443e 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/end_neg.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/end_neg.cc @@ -25,9 +25,8 @@ extern int unbounded[]; auto test01() { - return std::ranges::end(unbounded); // { dg-error "here" } + return std::ranges::end(unbounded); // { dg-error "no match" } } -// { dg-error "static assertion failed" "" { target *-*-* } 0 } struct incomplete; extern incomplete array[2]; @@ -38,5 +37,3 @@ test02() return std::ranges::end(array); // { dg-error "here" } } // { dg-error "incomplete type" "" { target *-*-* } 0 } - - diff --git a/libstdc++-v3/testsuite/std/ranges/access/size_neg.cc b/libstdc++-v3/testsuite/std/ranges/access/size_neg.cc index 6ff8c1f892a..10d9b141fbf 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/size_neg.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/size_neg.cc @@ -25,6 +25,5 @@ extern int unbounded[]; auto test01() { - return std::ranges::size(unbounded); // { dg-error "here" } + return std::ranges::size(unbounded); // { dg-error "no match" } } -// { dg-error "static assertion failed" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/std/ranges/access/ssize.cc b/libstdc++-v3/testsuite/std/ranges/access/ssize.cc index 5aa05be8f20..6f5478e2bb1 100644 --- a/libstdc++-v3/testsuite/std/ranges/access/ssize.cc +++ b/libstdc++-v3/testsuite/std/ranges/access/ssize.cc @@ -36,11 +36,6 @@ test01() static_assert( std::same_as ); VERIFY( std::ranges::ssize(a2) == 2); static_assert( noexcept(std::ranges::ssize(a2)) ); - - struct Incomplete; - using A = Incomplete[2]; // bounded array of incomplete type - extern A& f(); - static_assert( std::same_as ); } void