[libc++] Fix the noexceptness of __decay_copy.

When `a` was an array type, `__decay_copy(a)` was incorrectly marking itself
noexcept(false), because it is false that `int[10]` is nothrow convertible to `int[10]`
(in fact it is not convertible at all).

We have no tests explicitly for `__decay_copy`, but the new ranges::begin
and ranges::end tests fail before this patch.

Differential Revision: https://reviews.llvm.org/D115658
This commit is contained in:
Arthur O'Dwyer 2021-12-13 14:50:37 -05:00
parent aba437ceb2
commit 4dd901f4d3
3 changed files with 15 additions and 1 deletions

View File

@ -24,7 +24,7 @@ template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
typename decay<_Tp>::type __decay_copy(_Tp&& __t) typename decay<_Tp>::type __decay_copy(_Tp&& __t)
#if _LIBCPP_STD_VER > 17 #if _LIBCPP_STD_VER > 17
noexcept(is_nothrow_convertible_v<_Tp, remove_reference_t<_Tp>>) noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>)
#endif #endif
{ {
return _VSTD::forward<_Tp>(__t); return _VSTD::forward<_Tp>(__t);

View File

@ -264,6 +264,13 @@ ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval<NoThrowADLBegin<int*>&>()));
ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowADLBegin<ThrowingIterator<int>>&>())); ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowADLBegin<ThrowingIterator<int>>&>()));
ASSERT_NOT_NOEXCEPT(std::ranges::cbegin(std::declval<NoThrowADLBegin<ThrowingIterator<int>>&>())); ASSERT_NOT_NOEXCEPT(std::ranges::cbegin(std::declval<NoThrowADLBegin<ThrowingIterator<int>>&>()));
struct BeginReturnsArrayRef {
auto begin() const noexcept -> int(&)[10];
auto end() const noexcept -> int(&)[10];
} brar;
static_assert(noexcept(std::ranges::begin(brar)));
static_assert(noexcept(std::ranges::cbegin(brar)));
int main(int, char**) { int main(int, char**) {
testArray(); testArray();

View File

@ -298,6 +298,13 @@ ASSERT_NOEXCEPT(std::ranges::cend(std::declval<NoThrowADLEnd<int*>&>()));
ASSERT_NOT_NOEXCEPT(std::ranges::end(std::declval<NoThrowADLEnd<ThrowingIterator<int>>&>())); ASSERT_NOT_NOEXCEPT(std::ranges::end(std::declval<NoThrowADLEnd<ThrowingIterator<int>>&>()));
ASSERT_NOT_NOEXCEPT(std::ranges::cend(std::declval<NoThrowADLEnd<ThrowingIterator<int>>&>())); ASSERT_NOT_NOEXCEPT(std::ranges::cend(std::declval<NoThrowADLEnd<ThrowingIterator<int>>&>()));
struct BeginReturnsArrayRef {
auto begin() const noexcept -> int(&)[10];
auto end() const noexcept -> int(&)[10];
} brar;
static_assert(noexcept(std::ranges::end(brar)));
static_assert(noexcept(std::ranges::cend(brar)));
int main(int, char**) { int main(int, char**) {
testArray(); testArray();