]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Add noexcept to std::begin etc as per LWG 2280 and 3537
authorJonathan Wakely <jwakely@redhat.com>
Mon, 22 Mar 2021 15:15:12 +0000 (15:15 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Mon, 22 Mar 2021 15:56:49 +0000 (15:56 +0000)
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/range_access.cc: Check for
expected noexcept specifiers. Check result types of generic
std::begin and std::end overloads.
* testsuite/24_iterators/range_access/range_access_cpp14.cc:
Check for expected noexcept specifiers.
* testsuite/24_iterators/range_access/range_access_cpp17.cc:
Likewise.

libstdc++-v3/include/bits/range_access.h
libstdc++-v3/testsuite/24_iterators/range_access/range_access.cc
libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp14.cc
libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp17.cc

index ab26b64e44c0d4d74ece30a6bf645813e0ebae00..71ad28c3ab0feb38be7ad02b6929520b0fe8f153 100644 (file)
@@ -87,7 +87,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; }
 
   /**
@@ -97,7 +97,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
@@ -178,7 +178,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); }
 
   /**
@@ -188,7 +188,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); }
 
   /**
@@ -198,7 +198,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()); }
 
   /**
@@ -208,7 +208,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()); }
 
   /**
index 2380b1e0e317380cae60cc2baa216db83c14f630..b0b379c6ea55d69588a935ba4f2e19f12c05296b 100644 (file)
@@ -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)) );
 }
index 5a235de16781fbad5c62a58c9feaa242fc3e5483..75531719eeb359a5f0d7521c4edfceecac77cbb0 100644 (file)
@@ -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
index 481a52a16066d04da49d47dad0e0abdc49e5dcaa..358e19345e12893a71435d4c6edd8334c53e588f 100644 (file)
@@ -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" );
 }