From 4dd901f4d3aa072309eb23fbd8497f7916f7d77c Mon Sep 17 00:00:00 2001 From: Arthur O'Dwyer Date: Mon, 13 Dec 2021 14:50:37 -0500 Subject: [PATCH] [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 --- libcxx/include/__utility/decay_copy.h | 2 +- .../ranges/range.access/range.access.begin/begin.pass.cpp | 7 +++++++ .../std/ranges/range.access/range.access.end/end.pass.cpp | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/libcxx/include/__utility/decay_copy.h b/libcxx/include/__utility/decay_copy.h index 5c9716a89279..32238e117f56 100644 --- a/libcxx/include/__utility/decay_copy.h +++ b/libcxx/include/__utility/decay_copy.h @@ -24,7 +24,7 @@ template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR typename decay<_Tp>::type __decay_copy(_Tp&& __t) #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 { return _VSTD::forward<_Tp>(__t); diff --git a/libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp index 04f30c814359..3b712a1cc137 100644 --- a/libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp @@ -264,6 +264,13 @@ ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval&>())); ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval>&>())); ASSERT_NOT_NOEXCEPT(std::ranges::cbegin(std::declval>&>())); +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**) { testArray(); diff --git a/libcxx/test/std/ranges/range.access/range.access.end/end.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.end/end.pass.cpp index f860442af4fb..dd5da2ebf594 100644 --- a/libcxx/test/std/ranges/range.access/range.access.end/end.pass.cpp +++ b/libcxx/test/std/ranges/range.access/range.access.end/end.pass.cpp @@ -298,6 +298,13 @@ ASSERT_NOEXCEPT(std::ranges::cend(std::declval&>())); ASSERT_NOT_NOEXCEPT(std::ranges::end(std::declval>&>())); ASSERT_NOT_NOEXCEPT(std::ranges::cend(std::declval>&>())); +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**) { testArray();