From patchwork Tue Jun 15 18:28:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1492411 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+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) 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=a+2Z8li6; 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 4G4H3B6Xp5z9sWX for ; Wed, 16 Jun 2021 04:31:50 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 15D1A3838012 for ; Tue, 15 Jun 2021 18:31:48 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 15D1A3838012 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1623781908; bh=FrlfnaJyXSQgmJg47+tYPeoeWR/EsIPBprhlciBLI2A=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=a+2Z8li6ZnIvvCHWNhyrSJ4AY3LVfA5YUKZxkaw5LucMh4lMwizwOpnODmDQGavIz HAbgUQU/6n7qrjwk2sRUL2ldgGy8m61CU9DWqFFwl3qJWQkbNi+MaEhxrv/iL3Mqv6 xBNgw9LHew1HhOPrEi+AuGYKSgRFldpBCxPSu0lg= 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 [216.205.24.124]) by sourceware.org (Postfix) with ESMTP id 46C87383980D for ; Tue, 15 Jun 2021 18:28:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 46C87383980D 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-27-nTyiRiwBMmeqq9k66Ez3DA-1; Tue, 15 Jun 2021 14:28:06 -0400 X-MC-Unique: nTyiRiwBMmeqq9k66Ez3DA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 2F1BC185060A; Tue, 15 Jun 2021 18:28:05 +0000 (UTC) Received: from localhost (unknown [10.33.36.175]) by smtp.corp.redhat.com (Postfix) with ESMTP id A8EBD5D9E2; Tue, 15 Jun 2021 18:28:04 +0000 (UTC) Date: Tue, 15 Jun 2021 19:28:03 +0100 To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Add noexcept specifiers to some range adaptors Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-13.9 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_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-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: * include/bits/ranges_util.h (view_interface): Add noexcept to empty, operator bool, data and size members. (subrange): Add noexcept to constructors. * include/std/ranges (single_view, ref_view): Add noexcept to constructors. (views::single, views::all): Add noexcept. * testsuite/std/ranges/adaptors/all.cc: Check noexcept. * testsuite/std/ranges/single_view.cc: Likewise. Tested powerpc64le-linux. Committed to trunk. commit 9245b0e84c262cc5fd8373e94de3d23a3807b122 Author: Jonathan Wakely Date: Tue Jun 15 16:36:12 2021 libstdc++: Add noexcept specifiers to some range adaptors Signed-off-by: Jonathan Wakely libstdc++-v3/ChangeLog: * include/bits/ranges_util.h (view_interface): Add noexcept to empty, operator bool, data and size members. (subrange): Add noexcept to constructors. * include/std/ranges (single_view, ref_view): Add noexcept to constructors. (views::single, views::all): Add noexcept. * testsuite/std/ranges/adaptors/all.cc: Check noexcept. * testsuite/std/ranges/single_view.cc: Likewise. diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 02561ee63f9..dd829ed957f 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -77,45 +77,67 @@ namespace ranges return static_cast(*this); } + static constexpr bool + _S_bool(bool) noexcept; // not defined + + template + static constexpr bool + _S_empty(_Tp& __t) + noexcept(noexcept(_S_bool(ranges::begin(__t) == ranges::end(__t)))) + { return ranges::begin(__t) == ranges::end(__t); } + + template + static constexpr auto + _S_size(_Tp& __t) + noexcept(noexcept(ranges::end(__t) - ranges::begin(__t))) + { return ranges::end(__t) - ranges::begin(__t); } + public: constexpr bool - empty() requires forward_range<_Derived> - { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); } + empty() + noexcept(noexcept(_S_empty(_M_derived()))) + requires forward_range<_Derived> + { return _S_empty(_M_derived()); } constexpr bool - empty() const requires forward_range - { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); } + empty() const + noexcept(noexcept(_S_empty(_M_derived()))) + requires forward_range + { return _S_empty(_M_derived()); } constexpr explicit - operator bool() requires requires { ranges::empty(_M_derived()); } + operator bool() noexcept(noexcept(ranges::empty(_M_derived()))) + requires requires { ranges::empty(_M_derived()); } { return !ranges::empty(_M_derived()); } constexpr explicit - operator bool() const requires requires { ranges::empty(_M_derived()); } + operator bool() const noexcept(noexcept(ranges::empty(_M_derived()))) + requires requires { ranges::empty(_M_derived()); } { return !ranges::empty(_M_derived()); } constexpr auto - data() requires contiguous_iterator> - { return to_address(ranges::begin(_M_derived())); } + data() noexcept(noexcept(ranges::begin(_M_derived()))) + requires contiguous_iterator> + { return std::to_address(ranges::begin(_M_derived())); } constexpr auto - data() const + data() const noexcept(noexcept(ranges::begin(_M_derived()))) requires range && contiguous_iterator> - { return to_address(ranges::begin(_M_derived())); } + { return std::to_address(ranges::begin(_M_derived())); } constexpr auto - size() + size() noexcept(noexcept(_S_size(_M_derived()))) requires forward_range<_Derived> && sized_sentinel_for, iterator_t<_Derived>> - { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); } + { return _S_size(_M_derived()); } constexpr auto - size() const + size() const noexcept(noexcept(_S_size(_M_derived()))) requires forward_range && sized_sentinel_for, iterator_t> - { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); } + { return _S_size(_M_derived()); } constexpr decltype(auto) front() requires forward_range<_Derived> @@ -223,6 +245,8 @@ namespace ranges constexpr subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s) + noexcept(is_nothrow_constructible_v<_It, decltype(__i)> + && is_nothrow_constructible_v<_Sent, _Sent&>) requires (!_S_store_size) : _M_begin(std::move(__i)), _M_end(__s) { } @@ -230,6 +254,8 @@ namespace ranges constexpr subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s, __size_type __n) + noexcept(is_nothrow_constructible_v<_It, decltype(__i)> + && is_nothrow_constructible_v<_Sent, _Sent&>) requires (_Kind == subrange_kind::sized) : _M_begin(std::move(__i)), _M_end(__s) { @@ -242,7 +268,9 @@ namespace ranges && __detail::__convertible_to_non_slicing, _It> && convertible_to, _Sent> constexpr - subrange(_Rng&& __r) requires _S_store_size && sized_range<_Rng> + subrange(_Rng&& __r) + noexcept(noexcept(subrange(__r, ranges::size(__r)))) + requires _S_store_size && sized_range<_Rng> : subrange(__r, ranges::size(__r)) { } @@ -251,7 +279,9 @@ namespace ranges && __detail::__convertible_to_non_slicing, _It> && convertible_to, _Sent> constexpr - subrange(_Rng&& __r) requires (!_S_store_size) + subrange(_Rng&& __r) + noexcept(noexcept(subrange(ranges::begin(__r), ranges::end(__r)))) + requires (!_S_store_size) : subrange(ranges::begin(__r), ranges::end(__r)) { } @@ -260,6 +290,7 @@ namespace ranges && convertible_to, _Sent> constexpr subrange(_Rng&& __r, __size_type __n) + noexcept(noexcept(subrange(ranges::begin(__r), ranges::end(__r), __n))) requires (_Kind == subrange_kind::sized) : subrange{ranges::begin(__r), ranges::end(__r), __n} { } diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 220a44e11a8..b2943490e31 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -197,11 +197,13 @@ namespace ranges constexpr explicit single_view(const _Tp& __t) + noexcept(is_nothrow_copy_constructible_v<_Tp>) : _M_value(__t) { } constexpr explicit single_view(_Tp&& __t) + noexcept(is_nothrow_move_constructible_v<_Tp>) : _M_value(std::move(__t)) { } @@ -211,6 +213,7 @@ namespace ranges requires constructible_from<_Tp, _Args...> constexpr explicit single_view(in_place_t, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Tp, _Args...>) : _M_value{in_place, std::forward<_Args>(__args)...} { } @@ -604,6 +607,7 @@ namespace views template constexpr auto operator()(_Tp&& __e) const + noexcept(noexcept(single_view>(std::forward<_Tp>(__e)))) { return single_view>(std::forward<_Tp>(__e)); } }; @@ -1022,6 +1026,7 @@ namespace views::__adaptor && requires { _S_fun(declval<_Tp>()); } constexpr ref_view(_Tp&& __t) + noexcept(noexcept(static_cast<_Range&>(std::declval<_Tp>()))) : _M_r(std::__addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) { } @@ -1069,12 +1074,25 @@ namespace views::__adaptor struct _All : __adaptor::_RangeAdaptorClosure { + template + static constexpr bool + _S_noexcept() + { + if constexpr (view>) + return is_nothrow_constructible_v, _Range>; + else if constexpr (__detail::__can_ref_view<_Range>) + return true; + else + return noexcept(subrange{std::declval<_Range>()}); + } + template requires view> || __detail::__can_ref_view<_Range> || __detail::__can_subrange<_Range> constexpr auto operator()(_Range&& __r) const + noexcept(_S_noexcept<_Range>()) { if constexpr (view>) return std::forward<_Range>(__r); diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc index 42913ad38a3..9a6a31e6cb4 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/all.cc @@ -130,6 +130,35 @@ test05() static_assert(!requires { 0 | all; }); } +template +struct BorrowedRange +{ + int* ptr = nullptr; + + BorrowedRange(int (&arr)[3]) noexcept : ptr(arr) { } + + int* begin() const noexcept(B1) { return ptr; } + int* end() const noexcept(B2) { return ptr + 3; } +}; + +template +const bool std::ranges::enable_borrowed_range> = true; + +void +test06() +{ + int x[] { 1, 2, 3 }; + + // Using ref_view: + static_assert(noexcept(views::all(x))); + + // Using subrange: + static_assert(noexcept(views::all(BorrowedRange(x)))); + static_assert(!noexcept(views::all(BorrowedRange(x)))); + static_assert(!noexcept(views::all(BorrowedRange(x)))); + static_assert(!noexcept(views::all(BorrowedRange(x)))); +} + int main() { @@ -138,4 +167,5 @@ main() static_assert(test03()); static_assert(test04()); test05(); + test06(); } diff --git a/libstdc++-v3/testsuite/std/ranges/single_view.cc b/libstdc++-v3/testsuite/std/ranges/single_view.cc index f530cc07565..c036fc8976a 100644 --- a/libstdc++-v3/testsuite/std/ranges/single_view.cc +++ b/libstdc++-v3/testsuite/std/ranges/single_view.cc @@ -73,10 +73,34 @@ test04() std::as_const(s).data(); } +void +test05() +{ + int i = 0; + static_assert(noexcept(std::ranges::single_view())); + static_assert(noexcept(std::ranges::single_view(i))); + static_assert(noexcept(std::ranges::single_view(1))); + static_assert(noexcept(std::ranges::single_view(std::in_place, 2))); + static_assert(noexcept(std::ranges::views::single(i))); + auto s = std::ranges::views::single(i); + static_assert(noexcept(s.begin())); + static_assert(noexcept(s.end())); + static_assert(noexcept(s.size())); + static_assert(noexcept(s.data())); + static_assert(noexcept(s.empty())); // view_interface::empty() + const auto cs = s; + static_assert(noexcept(cs.begin())); + static_assert(noexcept(cs.end())); + static_assert(noexcept(cs.size())); + static_assert(noexcept(cs.data())); + static_assert(noexcept(cs.empty())); // view_interface::empty() +} + int main() { test01(); test02(); test03(); test04(); + test05(); }