[libcxx-commits] [libcxx] cb8a0b0 - [libc++] [ranges] Introduce _LIBCPP_AUTO_CAST(x) for auto(x).

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Wed Dec 22 09:34:40 PST 2021


Author: Arthur O'Dwyer
Date: 2021-12-22T12:29:42-05:00
New Revision: cb8a0b07974eb6a6aa681c30ce694e13b33a3db5

URL: https://github.com/llvm/llvm-project/commit/cb8a0b07974eb6a6aa681c30ce694e13b33a3db5
DIFF: https://github.com/llvm/llvm-project/commit/cb8a0b07974eb6a6aa681c30ce694e13b33a3db5.diff

LOG: [libc++] [ranges] Introduce _LIBCPP_AUTO_CAST(x) for auto(x).

Clang is gaining `auto(x)` support in D113393; sadly there
seems to be no feature-test macro for it. Zhihao is opening
a core issue for that macro.

Use `_LIBCPP_AUTO_CAST` where C++20 specifies we should use `auto(x)`;
stop using `__decay_copy(x)` in those places.
In fact, remove `__decay_copy` entirely. As of C++20, it's purely
a paper specification tool signifying "Return just `x`, but it was
perfect-forwarded, so we understand you're going to have to call
its move-constructor sometimes." I believe there's no reason we'd
ever need to do its operation explicitly in code.

This heisenbugs away a test failure on MinGW; see D112214.

Differential Revision: https://reviews.llvm.org/D115686

Added: 
    libcxx/include/__utility/auto_cast.h
    libcxx/test/libcxx/diagnostics/detail.headers/utility/auto_cast.module.verify.cpp

Modified: 
    libcxx/docs/Status/Cxx2bPapers.csv
    libcxx/include/CMakeLists.txt
    libcxx/include/__ranges/access.h
    libcxx/include/__ranges/all.h
    libcxx/include/__ranges/size.h
    libcxx/include/future
    libcxx/include/module.modulemap
    libcxx/include/thread
    libcxx/include/utility
    libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp
    libcxx/test/std/ranges/range.access/range.access.end/end.pass.cpp
    libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
    libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp

Removed: 
    libcxx/include/__utility/decay_copy.h
    libcxx/test/libcxx/diagnostics/detail.headers/utility/decay_copy.module.verify.cpp


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv
index 8a5b75928e749..7a76e1f576451 100644
--- a/libcxx/docs/Status/Cxx2bPapers.csv
+++ b/libcxx/docs/Status/Cxx2bPapers.csv
@@ -25,7 +25,7 @@
 "","","","","",""
 "`P0288R9 <https://wg21.link/P0288R9>`__","LWG","``any_invocable``","October 2021","",""
 "`P0798R8 <https://wg21.link/P0798R8>`__","LWG","Monadic operations for ``std::optional``","October 2021","|Complete|","14.0"
-"`P0849R8 <https://wg21.link/P0849R8>`__","LWG","``auto(x)``: ``DECAY_COPY`` in the language","October 2021","",""
+"`P0849R8 <https://wg21.link/P0849R8>`__","LWG","``auto(x)``: ``DECAY_COPY`` in the language","October 2021","|Complete|","14.0"
 "`P1072R10 <https://wg21.link/P1072R10>`__","LWG","``basic_string::resize_and_overwrite``","October 2021","",""
 "`P1147R1 <https://wg21.link/P1147R1>`__","LWG","Printing ``volatile`` Pointers","October 2021","|Complete|","14.0"
 "`P1272R4 <https://wg21.link/P1272R4>`__","LWG","Byteswapping for fun&&nuf","October 2021","|Complete|","14.0"

diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 76eed6f64d3bc..180f7d4259cd3 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -360,8 +360,8 @@ set(files
   __tuple
   __undef_macros
   __utility/as_const.h
+  __utility/auto_cast.h
   __utility/cmp.h
-  __utility/decay_copy.h
   __utility/declval.h
   __utility/exchange.h
   __utility/forward.h

diff  --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h
index d54b3314e4359..c58849f7cf33b 100644
--- a/libcxx/include/__ranges/access.h
+++ b/libcxx/include/__ranges/access.h
@@ -14,8 +14,7 @@
 #include <__iterator/readable_traits.h>
 #include <__ranges/enable_borrowed_range.h>
 #include <__utility/as_const.h>
-#include <__utility/decay_copy.h>
-#include <__utility/forward.h>
+#include <__utility/auto_cast.h>
 #include <concepts>
 #include <type_traits>
 
@@ -39,7 +38,7 @@ namespace ranges::__begin {
   concept __member_begin =
     __can_borrow<_Tp> &&
     requires(_Tp&& __t) {
-      { _VSTD::__decay_copy(__t.begin()) } -> input_or_output_iterator;
+      { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
     };
 
   void begin(auto&) = delete;
@@ -51,7 +50,7 @@ namespace ranges::__begin {
     __can_borrow<_Tp> &&
     __class_or_enum<remove_cvref_t<_Tp> > &&
     requires(_Tp && __t) {
-      { _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator;
+      { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
     };
 
   struct __fn {
@@ -65,17 +64,17 @@ namespace ranges::__begin {
     template <class _Tp>
     requires __member_begin<_Tp>
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
-    noexcept(noexcept(_VSTD::__decay_copy(__t.begin())))
+    noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.begin())))
     {
-      return __t.begin();
+      return _LIBCPP_AUTO_CAST(__t.begin());
     }
 
     template <class _Tp>
     requires __unqualified_begin<_Tp>
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
-    noexcept(noexcept(_VSTD::__decay_copy(begin(__t))))
+    noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t))))
     {
-      return begin(__t);
+      return _LIBCPP_AUTO_CAST(begin(__t));
     }
 
     void operator()(auto&&) const = delete;
@@ -98,7 +97,7 @@ namespace ranges::__end {
     __can_borrow<_Tp> &&
     requires(_Tp&& __t) {
       typename iterator_t<_Tp>;
-      { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for<iterator_t<_Tp> >;
+      { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp> >;
     };
 
   void end(auto&) = delete;
@@ -111,7 +110,7 @@ namespace ranges::__end {
     __class_or_enum<remove_cvref_t<_Tp> > &&
     requires(_Tp && __t) {
       typename iterator_t<_Tp>;
-      { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for<iterator_t<_Tp> >;
+      { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for<iterator_t<_Tp> >;
     };
 
   class __fn {
@@ -126,17 +125,17 @@ namespace ranges::__end {
     template <class _Tp>
     requires __member_end<_Tp>
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
-    noexcept(noexcept(_VSTD::__decay_copy(__t.end())))
+    noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.end())))
     {
-      return _VSTD::forward<_Tp>(__t).end();
+      return _LIBCPP_AUTO_CAST(__t.end());
     }
 
     template <class _Tp>
     requires __unqualified_end<_Tp>
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
-    noexcept(noexcept(_VSTD::__decay_copy(end(__t))))
+    noexcept(noexcept(_LIBCPP_AUTO_CAST(end(__t))))
     {
-      return end(__t);
+      return _LIBCPP_AUTO_CAST(end(__t));
     }
 
     void operator()(auto&&) const = delete;

diff  --git a/libcxx/include/__ranges/all.h b/libcxx/include/__ranges/all.h
index affe13ee0862e..ccc77258ba10a 100644
--- a/libcxx/include/__ranges/all.h
+++ b/libcxx/include/__ranges/all.h
@@ -17,7 +17,7 @@
 #include <__ranges/range_adaptor.h>
 #include <__ranges/ref_view.h>
 #include <__ranges/subrange.h>
-#include <__utility/decay_copy.h>
+#include <__utility/auto_cast.h>
 #include <__utility/declval.h>
 #include <__utility/forward.h>
 #include <type_traits>
@@ -38,9 +38,9 @@ namespace __all {
       requires ranges::view<decay_t<_Tp>>
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
     constexpr auto operator()(_Tp&& __t) const
-      noexcept(noexcept(_VSTD::__decay_copy(_VSTD::forward<_Tp>(__t))))
+      noexcept(noexcept(_LIBCPP_AUTO_CAST(_VSTD::forward<_Tp>(__t))))
     {
-      return _VSTD::forward<_Tp>(__t);
+      return _LIBCPP_AUTO_CAST(_VSTD::forward<_Tp>(__t));
     }
 
     template<class _Tp>

diff  --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h
index af0a8479f2eca..c37467eaf747c 100644
--- a/libcxx/include/__ranges/size.h
+++ b/libcxx/include/__ranges/size.h
@@ -13,8 +13,7 @@
 #include <__iterator/concepts.h>
 #include <__iterator/iterator_traits.h>
 #include <__ranges/access.h>
-#include <__utility/decay_copy.h>
-#include <__utility/forward.h>
+#include <__utility/auto_cast.h>
 #include <concepts>
 #include <type_traits>
 
@@ -26,7 +25,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if !defined(_LIBCPP_HAS_NO_RANGES)
 
-// clang-format off
 namespace ranges {
 template<class>
 inline constexpr bool disable_sized_range = false;
@@ -41,7 +39,7 @@ namespace __size {
 
   template <class _Tp>
   concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) {
-    { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).size()) } -> __integer_like;
+    { _LIBCPP_AUTO_CAST(__t.size()) } -> __integer_like;
   };
 
   template <class _Tp>
@@ -50,7 +48,7 @@ namespace __size {
     !__member_size<_Tp> &&
     __class_or_enum<remove_cvref_t<_Tp>> &&
     requires(_Tp&& __t) {
-      { _VSTD::__decay_copy(size(_VSTD::forward<_Tp>(__t))) } -> __integer_like;
+      { _LIBCPP_AUTO_CAST(size(__t)) } -> __integer_like;
     };
 
   template <class _Tp>
@@ -76,14 +74,14 @@ namespace __size {
 
     template <__member_size _Tp>
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
-        noexcept(noexcept(_VSTD::forward<_Tp>(__t).size())) {
-      return _VSTD::forward<_Tp>(__t).size();
+        noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.size()))) {
+      return _LIBCPP_AUTO_CAST(__t.size());
     }
 
     template <__unqualified_size _Tp>
     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
-        noexcept(noexcept(size(_VSTD::forward<_Tp>(__t)))) {
-      return size(_VSTD::forward<_Tp>(__t));
+        noexcept(noexcept(_LIBCPP_AUTO_CAST(size(__t)))) {
+      return _LIBCPP_AUTO_CAST(size(__t));
     }
 
     template<__
diff erence _Tp>
@@ -118,8 +116,6 @@ inline namespace __cpo {
 } // namespace __cpo
 } // namespace ranges
 
-// clang-format off
-
 #endif // !defined(_LIBCPP_HAS_NO_RANGES)
 
 _LIBCPP_END_NAMESPACE_STD

diff  --git a/libcxx/include/__utility/decay_copy.h b/libcxx/include/__utility/auto_cast.h
similarity index 53%
rename from libcxx/include/__utility/decay_copy.h
rename to libcxx/include/__utility/auto_cast.h
index 32238e117f561..5c368e077508b 100644
--- a/libcxx/include/__utility/decay_copy.h
+++ b/libcxx/include/__utility/auto_cast.h
@@ -7,29 +7,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef _LIBCPP___UTILITY_DECAY_COPY_H
-#define _LIBCPP___UTILITY_DECAY_COPY_H
+#ifndef _LIBCPP___UTILITY_AUTO_CAST_H
+#define _LIBCPP___UTILITY_AUTO_CAST_H
 
 #include <__config>
-#include <__utility/forward.h>
 #include <type_traits>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
 #endif
 
-_LIBCPP_BEGIN_NAMESPACE_STD
+#define _LIBCPP_AUTO_CAST(expr) static_cast<typename decay<decltype((expr))>::type>(expr)
 
-template <class _Tp>
-_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, decay_t<_Tp>>)
-#endif
-{
-  return _VSTD::forward<_Tp>(__t);
-}
-
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___UTILITY_DECAY_COPY_H
+#endif // _LIBCPP___UTILITY_AUTO_CAST_H

diff  --git a/libcxx/include/future b/libcxx/include/future
index 99df8831a7784..6b666a70f48ed 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -366,7 +366,7 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>;
 #include <__debug>
 #include <__memory/allocator_arg_t.h>
 #include <__memory/uses_allocator.h>
-#include <__utility/decay_copy.h>
+#include <__utility/auto_cast.h>
 #include <__utility/forward.h>
 #include <chrono>
 #include <exception>
@@ -2207,16 +2207,16 @@ async(launch __policy, _Fp&& __f, _Args&&... __args)
     {
 #endif
         if (__does_policy_contain(__policy, launch::async))
-        return _VSTD::__make_async_assoc_state<_Rp>(_BF(_VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)),
-                                                     _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...));
+        return _VSTD::__make_async_assoc_state<_Rp>(_BF(_LIBCPP_AUTO_CAST(_VSTD::forward<_Fp>(__f)),
+                                                        _LIBCPP_AUTO_CAST(_VSTD::forward<_Args>(__args))...));
 #ifndef _LIBCPP_NO_EXCEPTIONS
     }
     catch ( ... ) { if (__policy == launch::async) throw ; }
 #endif
 
     if (__does_policy_contain(__policy, launch::deferred))
-        return _VSTD::__make_deferred_assoc_state<_Rp>(_BF(_VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)),
-                                                        _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...));
+        return _VSTD::__make_deferred_assoc_state<_Rp>(_BF(_LIBCPP_AUTO_CAST(_VSTD::forward<_Fp>(__f)),
+                                                           _LIBCPP_AUTO_CAST(_VSTD::forward<_Args>(__args))...));
     return future<_Rp>{};
 }
 

diff  --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 4194a7fb83fe5..1dc6db406a742 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -921,8 +921,8 @@ module std [system] {
 
     module __utility {
       module as_const            { private header "__utility/as_const.h" }
+      module auto_cast           { private header "__utility/auto_cast.h" }
       module cmp                 { private header "__utility/cmp.h" }
-      module decay_copy          { private header "__utility/decay_copy.h" }
       module declval             { private header "__utility/declval.h" }
       module exchange            { private header "__utility/exchange.h" }
       module forward             { private header "__utility/forward.h" }

diff  --git a/libcxx/include/thread b/libcxx/include/thread
index bf751c87aa3ba..a4632f6fe524c 100644
--- a/libcxx/include/thread
+++ b/libcxx/include/thread
@@ -88,7 +88,6 @@ void sleep_for(const chrono::duration<Rep, Period>& rel_time);
 #include <__mutex_base>
 #include <__thread/poll_with_backoff.h>
 #include <__threading_support>
-#include <__utility/decay_copy.h>
 #include <__utility/forward.h>
 #include <chrono>
 #include <cstddef>
@@ -303,8 +302,8 @@ thread::thread(_Fp&& __f, _Args&&... __args)
     typedef tuple<_TSPtr, typename decay<_Fp>::type, typename decay<_Args>::type...> _Gp;
     unique_ptr<_Gp> __p(
             new _Gp(_VSTD::move(__tsp),
-                    _VSTD::__decay_copy(_VSTD::forward<_Fp>(__f)),
-                    _VSTD::__decay_copy(_VSTD::forward<_Args>(__args))...));
+                    _VSTD::forward<_Fp>(__f),
+                    _VSTD::forward<_Args>(__args)...));
     int __ec = _VSTD::__libcpp_thread_create(&__t_, &__thread_proxy<_Gp>, __p.get());
     if (__ec == 0)
         __p.release();

diff  --git a/libcxx/include/utility b/libcxx/include/utility
index 9ab7b8e0ffb34..9dd7905516a86 100644
--- a/libcxx/include/utility
+++ b/libcxx/include/utility
@@ -218,6 +218,7 @@ template <class T>
 #include <__debug>
 #include <__tuple>
 #include <__utility/as_const.h>
+#include <__utility/auto_cast.h>
 #include <__utility/cmp.h>
 #include <__utility/declval.h>
 #include <__utility/exchange.h>

diff  --git a/libcxx/test/libcxx/diagnostics/detail.headers/utility/decay_copy.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/utility/auto_cast.module.verify.cpp
similarity index 89%
rename from libcxx/test/libcxx/diagnostics/detail.headers/utility/decay_copy.module.verify.cpp
rename to libcxx/test/libcxx/diagnostics/detail.headers/utility/auto_cast.module.verify.cpp
index b15d23c71f2c5..cf012c3d17e04 100644
--- a/libcxx/test/libcxx/diagnostics/detail.headers/utility/decay_copy.module.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/detail.headers/utility/auto_cast.module.verify.cpp
@@ -11,5 +11,5 @@
 // WARNING: This test was generated by 'generate_private_header_tests.py'
 // and should not be edited manually.
 
-// expected-error@*:* {{use of private header from outside its module: '__utility/decay_copy.h'}}
-#include <__utility/decay_copy.h>
+// expected-error@*:* {{use of private header from outside its module: '__utility/auto_cast.h'}}
+#include <__utility/auto_cast.h>

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 05e6211f7a541..95d2196803b28 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
@@ -249,28 +249,27 @@ constexpr bool testBeginFunction() {
 ASSERT_NOEXCEPT(std::ranges::begin(std::declval<int (&)[10]>()));
 ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval<int (&)[10]>()));
 
-template<class T>
 struct NoThrowMemberBegin {
-  T begin() const noexcept;
-};
-ASSERT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowMemberBegin<int*>&>()));
-ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval<NoThrowMemberBegin<int*>&>()));
-ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowMemberBegin<ThrowingIterator<int>>&>()));
-ASSERT_NOT_NOEXCEPT(std::ranges::cbegin(std::declval<NoThrowMemberBegin<ThrowingIterator<int>>&>()));
+  ThrowingIterator<int> begin() const noexcept; // auto(t.begin()) doesn't throw
+} ntmb;
+static_assert(noexcept(std::ranges::begin(ntmb)));
+static_assert(noexcept(std::ranges::cbegin(ntmb)));
 
-template<class T>
 struct NoThrowADLBegin {
-  friend T begin(NoThrowADLBegin&) noexcept { return T{}; }
-  friend T begin(NoThrowADLBegin const&) noexcept { return T{}; }
-};
-ASSERT_NOEXCEPT(std::ranges::begin(std::declval<NoThrowADLBegin<int*>&>()));
-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::cbegin(std::declval<NoThrowADLBegin<ThrowingIterator<int>>&>()));
+  friend ThrowingIterator<int> begin(NoThrowADLBegin&) noexcept;  // auto(begin(t)) doesn't throw
+  friend ThrowingIterator<int> begin(const NoThrowADLBegin&) noexcept;
+} ntab;
+static_assert(noexcept(std::ranges::begin(ntab)));
+static_assert(noexcept(std::ranges::cbegin(ntab)));
+
+struct NoThrowMemberBeginReturnsRef {
+  ThrowingIterator<int>& begin() const noexcept; // auto(t.begin()) may throw
+} ntmbrr;
+static_assert(!noexcept(std::ranges::begin(ntmbrr)));
+static_assert(!noexcept(std::ranges::cbegin(ntmbrr)));
 
 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)));

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 1e4fc0213fc4f..84b4904d8f963 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
@@ -283,34 +283,34 @@ constexpr bool testEndFunction() {
 ASSERT_NOEXCEPT(std::ranges::end(std::declval<int (&)[10]>()));
 ASSERT_NOEXCEPT(std::ranges::cend(std::declval<int (&)[10]>()));
 
-template<class T>
 struct NoThrowMemberEnd {
-  T begin() const;
-  T end() const noexcept;
-};
-ASSERT_NOEXCEPT(std::ranges::end(std::declval<NoThrowMemberEnd<int*>&>()));
-ASSERT_NOEXCEPT(std::ranges::cend(std::declval<NoThrowMemberEnd<int*>&>()));
-ASSERT_NOT_NOEXCEPT(std::ranges::end(std::declval<NoThrowMemberEnd<ThrowingIterator<int>>&>()));
-ASSERT_NOT_NOEXCEPT(std::ranges::cend(std::declval<NoThrowMemberEnd<ThrowingIterator<int>>&>()));
+  ThrowingIterator<int> begin() const;
+  ThrowingIterator<int> end() const noexcept; // auto(t.end()) doesn't throw
+} ntme;
+static_assert(noexcept(std::ranges::end(ntme)));
+static_assert(noexcept(std::ranges::cend(ntme)));
 
-template<class T>
 struct NoThrowADLEnd {
-  T begin() const;
-  friend T end(NoThrowADLEnd&) noexcept { return T{}; }
-  friend T end(NoThrowADLEnd const&) noexcept { return T{}; }
-};
-ASSERT_NOEXCEPT(std::ranges::end(std::declval<NoThrowADLEnd<int*>&>()));
-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::cend(std::declval<NoThrowADLEnd<ThrowingIterator<int>>&>()));
-
-struct BeginReturnsArrayRef {
+  ThrowingIterator<int> begin() const;
+  friend ThrowingIterator<int> end(NoThrowADLEnd&) noexcept;  // auto(end(t)) doesn't throw
+  friend ThrowingIterator<int> end(const NoThrowADLEnd&) noexcept;
+} ntae;
+static_assert(noexcept(std::ranges::end(ntae)));
+static_assert(noexcept(std::ranges::cend(ntae)));
+
+struct NoThrowMemberEndReturnsRef {
+  ThrowingIterator<int> begin() const;
+  ThrowingIterator<int>& end() const noexcept; // auto(t.end()) may throw
+} ntmerr;
+static_assert(!noexcept(std::ranges::end(ntmerr)));
+static_assert(!noexcept(std::ranges::cend(ntmerr)));
+
+struct EndReturnsArrayRef {
     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)));
-
+} erar;
+static_assert(noexcept(std::ranges::end(erar)));
+static_assert(noexcept(std::ranges::cend(erar)));
 
 int main(int, char**) {
   testArray();

diff  --git a/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp b/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
index 92023cc6a2873..4d91e3dafebdc 100644
--- a/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
@@ -135,7 +135,7 @@ struct SizeFunctionSigned {
 bool constexpr testHasSizeFunction() {
   assert(std::ranges::size(SizeFunction()) == 42);
   ASSERT_SAME_TYPE(decltype(std::ranges::size(SizeFunction())), size_t);
-  assert(std::ranges::size(MoveOnlySizeFunction()) == 42);
+  static_assert(!std::is_invocable_v<RangeSizeT, MoveOnlySizeFunction>);
   assert(std::ranges::size(EnumSizeFunction()) == 42);
   assert(std::ranges::size(SizeFunctionConst()) == 42);
 

diff  --git a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
index c0468fd8ca228..c3d5189e1bba7 100644
--- a/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
+++ b/libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp
@@ -21,7 +21,7 @@
 // (It's fixed in the upcoming Clang 14, by https://reviews.llvm.org/D109651.)
 // Prior to the fix, when statically linked, the unwind info for the two
 // (default and overridden) operator new implementations clash.
-// XFAIL: target={{.+}}-windows-gnu && !windows-dll && clang-13
+// UNSUPPORTED: target={{.+}}-windows-gnu && !windows-dll && clang-13
 
 #include <thread>
 #include <new>


        


More information about the libcxx-commits mailing list