From cff87282f4f50c2fd471a2fe0df49312716a8caf Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Tue, 10 Dec 2019 23:50:26 +0000 Subject: [PATCH] libstdc++: Correct noexcept-specifiers on span constructors As discussed at https://github.com/cplusplus/draft/issues/3534 two std::span constructors specify incorrect conditions for throwing exceptions. This patch makes those constructors have correct noexcept-specifiers that accurately reflect what can actually throw. (span(ContiguousIterator, Sentinel)): Add conditional noexcept. * include/std/span (span(ContiguousIterator, size_type)): Change noexcept to be unconditionally true. * testsuite/23_containers/span/nothrow_cons.cc: New test. From-SVN: r279206 --- libstdc++-v3/ChangeLog | 7 +++ libstdc++-v3/include/std/span | 3 +- .../23_containers/span/nothrow_cons.cc | 59 +++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 libstdc++-v3/testsuite/23_containers/span/nothrow_cons.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 2b8b9de8e07..3cc22a18b1c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2019-12-10 Jonathan Wakely + + (span(ContiguousIterator, Sentinel)): Add conditional noexcept. + * include/std/span (span(ContiguousIterator, size_type)): Change + noexcept to be unconditionally true. + * testsuite/23_containers/span/nothrow_cons.cc: New test. + 2019-12-10 François Dumont * include/bits/stl_algobase.h diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index ecce0b33b0b..6328ecbcde5 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -210,6 +210,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && (!is_convertible_v<_Sentinel, size_type>) constexpr span(_ContiguousIterator __first, _Sentinel __last) + noexcept(noexcept(__last - __first)) : _M_extent(static_cast(__last - __first)), _M_ptr(std::to_address(__first)) { @@ -221,7 +222,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION requires (__is_compatible_iterator<_ContiguousIterator>::value) constexpr span(_ContiguousIterator __first, size_type __count) - noexcept(noexcept(std::to_address(__first))) + noexcept : _M_extent(__count), _M_ptr(std::to_address(__first)) { __glibcxx_assert(_Extent == dynamic_extent || __count == _Extent); } diff --git a/libstdc++-v3/testsuite/23_containers/span/nothrow_cons.cc b/libstdc++-v3/testsuite/23_containers/span/nothrow_cons.cc new file mode 100644 index 00000000000..f28a3386aaf --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/span/nothrow_cons.cc @@ -0,0 +1,59 @@ +// Copyright (C) 2019 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::span; +using std::is_nothrow_constructible_v; + +static_assert( is_nothrow_constructible_v> ); +static_assert( is_nothrow_constructible_v> ); + +static_assert( is_nothrow_constructible_v, span&> ); +static_assert( is_nothrow_constructible_v, span&> ); +static_assert( is_nothrow_constructible_v, span&> ); +static_assert( is_nothrow_constructible_v, span&> ); +static_assert( is_nothrow_constructible_v, span&> ); +static_assert( is_nothrow_constructible_v, span&> ); + +static_assert( is_nothrow_constructible_v, int(&)[1]> ); +static_assert( is_nothrow_constructible_v, int(&)[1]> ); +static_assert( is_nothrow_constructible_v, std::array&> ); +static_assert( is_nothrow_constructible_v, std::array&> ); + +template +struct sentinel { int* p; }; + +template +bool operator==(sentinel s, int* p) noexcept { return s.p == p; } + +template +std::ptrdiff_t operator-(sentinel s, int* p) noexcept(B) { return s.p - p; } + +template +std::ptrdiff_t operator-(int* p, sentinel s) noexcept { return p - s.p; } + +static_assert(std::sized_sentinel_for, int*>); +static_assert(std::sized_sentinel_for, int*>); + +static_assert(is_nothrow_constructible_v, int*, std::size_t>); +static_assert(is_nothrow_constructible_v, int*, const int*>); +static_assert(is_nothrow_constructible_v, int*, sentinel>); +static_assert(!is_nothrow_constructible_v, int*, sentinel>); -- 2.30.2