aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-03-22 15:15:12 +0000
committerJonathan Wakely <jwakely@redhat.com>2021-03-22 15:56:49 +0000
commit00b46c00c8d9003c61e8f817668ad3380e16fedb (patch)
tree44e489704c82932669387f011fdc5be1f22a17ed
parent87e3c2ef682e2ba7692ee56142a4eb5b6441c4d3 (diff)
downloadgcc-00b46c00c8d9003c61e8f817668ad3380e16fedb.zip
gcc-00b46c00c8d9003c61e8f817668ad3380e16fedb.tar.gz
gcc-00b46c00c8d9003c61e8f817668ad3380e16fedb.tar.bz2
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/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.
-rw-r--r--libstdc++-v3/include/bits/range_access.h12
-rw-r--r--libstdc++-v3/testsuite/24_iterators/range_access/range_access.cc30
-rw-r--r--libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp14.cc15
-rw-r--r--libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp17.cc14
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 ab26b64..71ad28c 100644
--- a/libstdc++-v3/include/bits/range_access.h
+++ b/libstdc++-v3/include/bits/range_access.h
@@ -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()); }
/**
diff --git a/libstdc++-v3/testsuite/24_iterators/range_access/range_access.cc b/libstdc++-v3/testsuite/24_iterators/range_access/range_access.cc
index 2380b1e..b0b379c 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_access/range_access.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_access/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/range_access_cpp14.cc b/libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp14.cc
index 5a235de..7553171 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp14.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_access/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/range_access_cpp17.cc b/libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp17.cc
index 481a52a1..358e193 100644
--- a/libstdc++-v3/testsuite/24_iterators/range_access/range_access_cpp17.cc
+++ b/libstdc++-v3/testsuite/24_iterators/range_access/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" );
}