aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-12-10 23:50:26 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2019-12-10 23:50:26 +0000
commitcff87282f4f50c2fd471a2fe0df49312716a8caf (patch)
tree86eeb876af5718df8e8f38dd5347d6e2c594a446 /libstdc++-v3
parenta6ae300f9a019aff902cd11068af0956288d6541 (diff)
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
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog7
-rw-r--r--libstdc++-v3/include/std/span3
-rw-r--r--libstdc++-v3/testsuite/23_containers/span/nothrow_cons.cc59
3 files changed, 68 insertions, 1 deletions
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 <jwakely@redhat.com>
+
+ (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 <fdumont@gcc.gnu.org>
* 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<size_type>(__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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <span>
+
+using std::span;
+using std::is_nothrow_constructible_v;
+
+static_assert( is_nothrow_constructible_v<span<int>> );
+static_assert( is_nothrow_constructible_v<span<int, 0>> );
+
+static_assert( is_nothrow_constructible_v<span<int>, span<int>&> );
+static_assert( is_nothrow_constructible_v<span<const int>, span<int>&> );
+static_assert( is_nothrow_constructible_v<span<int>, span<int, 1>&> );
+static_assert( is_nothrow_constructible_v<span<const int>, span<int, 1>&> );
+static_assert( is_nothrow_constructible_v<span<int, 1>, span<int, 1>&> );
+static_assert( is_nothrow_constructible_v<span<const int, 1>, span<int, 1>&> );
+
+static_assert( is_nothrow_constructible_v<span<int>, int(&)[1]> );
+static_assert( is_nothrow_constructible_v<span<int, 1>, int(&)[1]> );
+static_assert( is_nothrow_constructible_v<span<int>, std::array<int, 1>&> );
+static_assert( is_nothrow_constructible_v<span<int, 1>, std::array<int, 1>&> );
+
+template<bool>
+struct sentinel { int* p; };
+
+template<bool B>
+bool operator==(sentinel<B> s, int* p) noexcept { return s.p == p; }
+
+template<bool B>
+std::ptrdiff_t operator-(sentinel<B> s, int* p) noexcept(B) { return s.p - p; }
+
+template<bool B>
+std::ptrdiff_t operator-(int* p, sentinel<B> s) noexcept { return p - s.p; }
+
+static_assert(std::sized_sentinel_for<sentinel<true>, int*>);
+static_assert(std::sized_sentinel_for<sentinel<false>, int*>);
+
+static_assert(is_nothrow_constructible_v<span<int>, int*, std::size_t>);
+static_assert(is_nothrow_constructible_v<span<int>, int*, const int*>);
+static_assert(is_nothrow_constructible_v<span<int>, int*, sentinel<true>>);
+static_assert(!is_nothrow_constructible_v<span<int>, int*, sentinel<false>>);