[gcc r9-9366] libstdc++: Add noexcept to std::begin etc as per LWG 2280 and 3537

Jonathan Wakely redi@gcc.gnu.org
Tue Apr 20 18:52:03 GMT 2021


https://gcc.gnu.org/g:592ecfc48c73fdb497f1d74cd8d9fe84c3cec208

commit r9-9366-g592ecfc48c73fdb497f1d74cd8d9fe84c3cec208
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Mar 22 15:15:12 2021 +0000

    libstdc++: Add noexcept to std::begin etc as per LWG 2280 and 3537
    
    This implements the proposed changes for LWG 3537 (which we're allowed
    to do as an extension whatever the outcome of the issue). I noticed we
    didn't implement LWG 2280 completely, as the std::begin and std::end
    overloads for arrays were not noexcept.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/range_access.h (begin(T (&)[N]), end(T (&)[N])):
            Add missing 'noexcept' as per LWG 2280.
            (rbegin(T (&)[N]), rend(T (&)[N]), rbegin(initializer_list<T>))
            (rend(initializer_list<T>)): Add 'noexcept' as per LWG 3537.
            * testsuite/24_iterators/range_access.cc: Check for expected
            noexcept specifiers. Check result types of generic std::begin
            and std::end overloads.
            * testsuite/24_iterators/range_access_cpp14.cc: Check for
            expected noexcept specifiers.
            * testsuite/24_iterators/range_access_cpp17.cc: Likewise.
    
    (cherry picked from commit 00b46c00c8d9003c61e8f817668ad3380e16fedb)

Diff:
---
 libstdc++-v3/include/bits/range_access.h           | 12 ++++-----
 .../testsuite/24_iterators/range_access.cc         | 30 ++++++++++++++++++++++
 .../testsuite/24_iterators/range_access_cpp14.cc   | 15 +++++++++++
 .../testsuite/24_iterators/range_access_cpp17.cc   | 14 ++++++++++
 4 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/include/bits/range_access.h b/libstdc++-v3/include/bits/range_access.h
index dfdcd8e7207..3d99ea92027 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -84,7 +84,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   template<typename _Tp, size_t _Nm>
     inline _GLIBCXX14_CONSTEXPR _Tp*
-    begin(_Tp (&__arr)[_Nm])
+    begin(_Tp (&__arr)[_Nm]) noexcept
     { return __arr; }
 
   /**
@@ -94,7 +94,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   template<typename _Tp, size_t _Nm>
     inline _GLIBCXX14_CONSTEXPR _Tp*
-    end(_Tp (&__arr)[_Nm])
+    end(_Tp (&__arr)[_Nm]) noexcept
     { return __arr + _Nm; }
 
 #if __cplusplus >= 201402L
@@ -175,7 +175,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   template<typename _Tp, size_t _Nm>
     inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
-    rbegin(_Tp (&__arr)[_Nm])
+    rbegin(_Tp (&__arr)[_Nm]) noexcept
     { return reverse_iterator<_Tp*>(__arr + _Nm); }
 
   /**
@@ -185,7 +185,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   template<typename _Tp, size_t _Nm>
     inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*>
-    rend(_Tp (&__arr)[_Nm])
+    rend(_Tp (&__arr)[_Nm]) noexcept
     { return reverse_iterator<_Tp*>(__arr); }
 
   /**
@@ -195,7 +195,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   template<typename _Tp>
     inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
-    rbegin(initializer_list<_Tp> __il)
+    rbegin(initializer_list<_Tp> __il) noexcept
     { return reverse_iterator<const _Tp*>(__il.end()); }
 
   /**
@@ -205,7 +205,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   template<typename _Tp>
     inline _GLIBCXX17_CONSTEXPR reverse_iterator<const _Tp*>
-    rend(initializer_list<_Tp> __il)
+    rend(initializer_list<_Tp> __il) noexcept
     { return reverse_iterator<const _Tp*>(__il.begin()); }
 
   /**
diff --git a/libstdc++-v3/testsuite/24_iterators/range_access.cc b/libstdc++-v3/testsuite/24_iterators/range_access.cc
index 8b1ac966503..a374e5a199c 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_access.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_access.cc
@@ -27,4 +27,34 @@ test01()
   int arr[3] = {1, 2, 3};
   std::begin(arr);
   std::end(arr);
+
+  static_assert( noexcept(std::begin(arr)), "LWG 2280" );
+  static_assert( noexcept(std::end(arr)), "LWG 2280" );
+}
+
+void
+test02()
+{
+  extern void require_int(int*);
+  extern void require_long(long*);
+
+  struct B
+  {
+    int* begin() { return nullptr; }
+    long* begin() const { return nullptr; }
+  };
+
+  B b;
+  require_int( std::begin(b) );
+  require_long( std::begin(const_cast<const B&>(b)) );
+
+  struct E
+  {
+    int* end() { return nullptr; }
+    long* end() const { return nullptr; }
+  };
+
+  E e;
+  require_int( std::end(e) );
+  require_long( std::end(const_cast<const E&>(e)) );
 }
diff --git a/libstdc++-v3/testsuite/24_iterators/range_access_cpp14.cc b/libstdc++-v3/testsuite/24_iterators/range_access_cpp14.cc
index 29a469d7d6b..4cd239673ef 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_access_cpp14.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_access_cpp14.cc
@@ -39,10 +39,21 @@ void
 test02()
 {
   static int i[1];
+  // LWG 2280
   constexpr auto b  __attribute__((unused)) = std::begin(i);
   constexpr auto e  __attribute__((unused)) = std::end(i);
   constexpr auto cb __attribute__((unused)) = std::cbegin(i);
   constexpr auto ce __attribute__((unused)) = std::cend(i);
+
+  // LWG 2280
+  static_assert( noexcept(std::begin(i)),  "LWG 2280" );
+  static_assert( noexcept(std::end(i)),    "LWG 2280" );
+  static_assert( noexcept(std::cbegin(i)), "LWG 2280" );
+  static_assert( noexcept(std::cend(i)),   "LWG 2280" );
+
+  // LWG 3537
+  static_assert( noexcept(std::rbegin(i)),  "LWG 3537" );
+  static_assert( noexcept(std::rend(i)),    "LWG 3537" );
 }
 
 void
@@ -55,6 +66,10 @@ test03()
   VERIFY(std::rend(il) == std::reverse_iterator<const int*>(il.begin()));
   VERIFY(std::crbegin(il) == std::reverse_iterator<const int*>(il.end()));
   VERIFY(std::crend(il) == std::reverse_iterator<const int*>(il.begin()));
+
+  // LWG 3537
+  static_assert( noexcept(std::rbegin(il)),  "LWG 3537" );
+  static_assert( noexcept(std::rend(il)),    "LWG 3537" );
 }
 
 void
diff --git a/libstdc++-v3/testsuite/24_iterators/range_access_cpp17.cc b/libstdc++-v3/testsuite/24_iterators/range_access_cpp17.cc
index 9ba20090c77..e5085516ca6 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_access_cpp17.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_access_cpp17.cc
@@ -41,6 +41,16 @@ test02()
   static int i[] = { 1, 2 };
   static_assert(std::distance(std::begin(i), std::end(i)) == 2);
   static_assert(std::distance(std::cbegin(i), std::cend(i)) == 2);
+
+  // LWG 2280
+  static_assert( noexcept(std::begin(i)),  "LWG 2280" );
+  static_assert( noexcept(std::end(i)),    "LWG 2280" );
+  static_assert( noexcept(std::cbegin(i)), "LWG 2280" );
+  static_assert( noexcept(std::cend(i)),   "LWG 2280" );
+
+  // LWG 3537
+  static_assert( noexcept(std::rbegin(i)),  "LWG 3537" );
+  static_assert( noexcept(std::rend(i)),    "LWG 3537" );
 }
 
 void
@@ -54,4 +64,8 @@ test03()
   static_assert(std::rend(il) == reverse_iterator<const int*>(il.begin()));
   static_assert(std::crbegin(il) == reverse_iterator<const int*>(il.end()));
   static_assert(std::crend(il) == reverse_iterator<const int*>(il.begin()));
+
+  // LWG 3537
+  static_assert( noexcept(std::rbegin(il)),  "LWG 3537" );
+  static_assert( noexcept(std::rend(il)),    "LWG 3537" );
 }


More information about the Libstdc++-cvs mailing list