Index: libcxx/docs/Status/Cxx2bPapers.csv =================================================================== --- libcxx/docs/Status/Cxx2bPapers.csv +++ libcxx/docs/Status/Cxx2bPapers.csv @@ -25,7 +25,7 @@ "","","","","","" "`P0288R9 `__","LWG","``any_invocable``","October 2021","","" "`P0798R8 `__","LWG","Monadic operations for ``std::optional``","October 2021","|Complete|","14.0" -"`P0849R8 `__","LWG","``auto(x)``: ``DECAY_COPY`` in the language","October 2021","","" +"`P0849R8 `__","LWG","``auto(x)``: ``DECAY_COPY`` in the language","October 2021","|Complete|","14.0" "`P1072R10 `__","LWG","``basic_string::resize_and_overwrite``","October 2021","","" "`P1147R1 `__","LWG","Printing ``volatile`` Pointers","October 2021","|Complete|","14.0" "`P1272R4 `__","LWG","Byteswapping for fun&&nuf","October 2021","|Complete|","14.0" Index: libcxx/include/CMakeLists.txt =================================================================== --- libcxx/include/CMakeLists.txt +++ libcxx/include/CMakeLists.txt @@ -360,8 +360,8 @@ __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 Index: libcxx/include/__ranges/access.h =================================================================== --- libcxx/include/__ranges/access.h +++ 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 #include @@ -44,7 +43,7 @@ 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; @@ -56,7 +55,7 @@ __can_borrow<_Tp> && __class_or_enum > && requires(_Tp && __t) { - { _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator; + { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator; }; struct __fn { @@ -75,17 +74,17 @@ template 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 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; @@ -108,7 +107,7 @@ __can_borrow<_Tp> && requires(_Tp&& __t) { typename iterator_t<_Tp>; - { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for >; + { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for >; }; void end(auto&) = delete; @@ -121,7 +120,7 @@ __class_or_enum > && requires(_Tp && __t) { typename iterator_t<_Tp>; - { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for >; + { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for >; }; class __fn { @@ -140,17 +139,17 @@ template 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 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; Index: libcxx/include/__ranges/all.h =================================================================== --- libcxx/include/__ranges/all.h +++ 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 @@ -38,9 +38,9 @@ requires ranges::view> [[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 Index: libcxx/include/__ranges/size.h =================================================================== --- libcxx/include/__ranges/size.h +++ 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 #include @@ -26,7 +25,6 @@ #if !defined(_LIBCPP_HAS_NO_RANGES) -// clang-format off namespace ranges { template inline constexpr bool disable_sized_range = false; @@ -41,7 +39,7 @@ template 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 @@ -50,7 +48,7 @@ !__member_size<_Tp> && __class_or_enum> && requires(_Tp&& __t) { - { _VSTD::__decay_copy(size(_VSTD::forward<_Tp>(__t))) } -> __integer_like; + { _LIBCPP_AUTO_CAST(size(__t)) } -> __integer_like; }; template @@ -76,14 +74,14 @@ 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<__difference _Tp> @@ -118,8 +116,6 @@ } // namespace __cpo } // namespace ranges -// clang-format off - #endif // !defined(_LIBCPP_HAS_NO_RANGES) _LIBCPP_END_NAMESPACE_STD Index: libcxx/include/__utility/auto_cast.h =================================================================== --- libcxx/include/__utility/auto_cast.h +++ 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 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif -_LIBCPP_BEGIN_NAMESPACE_STD +#define _LIBCPP_AUTO_CAST(expr) static_cast::type>(expr) -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, 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 Index: libcxx/include/future =================================================================== --- libcxx/include/future +++ libcxx/include/future @@ -366,7 +366,7 @@ #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 #include @@ -2207,16 +2207,16 @@ { #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>{}; } Index: libcxx/include/module.modulemap =================================================================== --- libcxx/include/module.modulemap +++ libcxx/include/module.modulemap @@ -921,8 +921,8 @@ 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" } Index: libcxx/include/thread =================================================================== --- libcxx/include/thread +++ libcxx/include/thread @@ -88,7 +88,6 @@ #include <__mutex_base> #include <__thread/poll_with_backoff.h> #include <__threading_support> -#include <__utility/decay_copy.h> #include <__utility/forward.h> #include #include @@ -303,8 +302,8 @@ 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(); Index: libcxx/include/utility =================================================================== --- libcxx/include/utility +++ libcxx/include/utility @@ -218,6 +218,7 @@ #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> Index: libcxx/test/libcxx/diagnostics/detail.headers/utility/auto_cast.module.verify.cpp =================================================================== --- libcxx/test/libcxx/diagnostics/detail.headers/utility/auto_cast.module.verify.cpp +++ 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> Index: libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp =================================================================== --- libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp +++ libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp @@ -245,28 +245,27 @@ ASSERT_NOEXCEPT(std::ranges::begin(std::declval())); ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval())); -template struct NoThrowMemberBegin { - T begin() const noexcept; -}; -ASSERT_NOEXCEPT(std::ranges::begin(std::declval&>())); -ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval&>())); -ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval>&>())); -ASSERT_NOT_NOEXCEPT(std::ranges::cbegin(std::declval>&>())); + ThrowingIterator 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 struct NoThrowADLBegin { - friend T begin(NoThrowADLBegin&) noexcept { return T{}; } - friend T begin(NoThrowADLBegin const&) noexcept { return T{}; } -}; -ASSERT_NOEXCEPT(std::ranges::begin(std::declval&>())); -ASSERT_NOEXCEPT(std::ranges::cbegin(std::declval&>())); -ASSERT_NOT_NOEXCEPT(std::ranges::begin(std::declval>&>())); -ASSERT_NOT_NOEXCEPT(std::ranges::cbegin(std::declval>&>())); + friend ThrowingIterator begin(NoThrowADLBegin&) noexcept; // auto(begin(t)) doesn't throw + friend ThrowingIterator begin(const NoThrowADLBegin&) noexcept; +} ntab; +static_assert(noexcept(std::ranges::begin(ntab))); +static_assert(noexcept(std::ranges::cbegin(ntab))); + +struct NoThrowMemberBeginReturnsRef { + ThrowingIterator& 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))); Index: libcxx/test/std/ranges/range.access/range.access.end/end.pass.cpp =================================================================== --- libcxx/test/std/ranges/range.access/range.access.end/end.pass.cpp +++ libcxx/test/std/ranges/range.access/range.access.end/end.pass.cpp @@ -277,34 +277,34 @@ ASSERT_NOEXCEPT(std::ranges::end(std::declval())); ASSERT_NOEXCEPT(std::ranges::cend(std::declval())); -template struct NoThrowMemberEnd { - T begin() const; - T end() const noexcept; -}; -ASSERT_NOEXCEPT(std::ranges::end(std::declval&>())); -ASSERT_NOEXCEPT(std::ranges::cend(std::declval&>())); -ASSERT_NOT_NOEXCEPT(std::ranges::end(std::declval>&>())); -ASSERT_NOT_NOEXCEPT(std::ranges::cend(std::declval>&>())); + ThrowingIterator begin() const; + ThrowingIterator 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 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&>())); -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 { + ThrowingIterator begin() const; + friend ThrowingIterator end(NoThrowADLEnd&) noexcept; // auto(end(t)) doesn't throw + friend ThrowingIterator end(const NoThrowADLEnd&) noexcept; +} ntae; +static_assert(noexcept(std::ranges::end(ntae))); +static_assert(noexcept(std::ranges::cend(ntae))); + +struct NoThrowMemberEndReturnsRef { + ThrowingIterator begin() const; + ThrowingIterator& 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(); Index: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp =================================================================== --- libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp +++ libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp @@ -124,7 +124,7 @@ 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); assert(std::ranges::size(EnumSizeFunction()) == 42); assert(std::ranges::size(SizeFunctionConst()) == 42); Index: libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp =================================================================== --- libcxx/test/std/thread/thread.threads/thread.thread.class/thread.thread.constr/F.pass.cpp +++ 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 #include