libstdc++: Correct noexcept-specifiers on span constructors
authorJonathan Wakely <jwakely@redhat.com>
Tue, 10 Dec 2019 23:50:26 +0000 (23:50 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 10 Dec 2019 23:50:26 +0000 (23:50 +0000)
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
libstdc++-v3/include/std/span
libstdc++-v3/testsuite/23_containers/span/nothrow_cons.cc [new file with mode: 0644]

index 2b8b9de8e075c5861866d063a5f7f82a5a47a173..3cc22a18b1c626dee93f504c50deb5b941b9da2f 100644 (file)
@@ -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
index ecce0b33b0bbd0e8f686996f7d311699969ac9bf..6328ecbcde5e323d755709b12c6227bfed06b096 100644 (file)
@@ -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 (file)
index 0000000..f28a338
--- /dev/null
@@ -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>>);