diff options
Diffstat (limited to 'libstdc++-v3')
19 files changed, 461 insertions, 40 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7ec35de..4215128 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,74 @@ +2025-12-05 Patrick Palka <ppalka@redhat.com> + Tomasz Kamiński <tkaminsk@redhat.com> + + PR libstdc++/120446 + * include/bits/refwrap.h (__detail::__is_ref_wrapper): + Define as per P2655R3 for C++20. + (__detail::__ref_wrap_common_reference_exists_with): Likewise. + (basic_common_reference): Define partial specializations using + the above as per P2655R3 for C++20. + * include/bits/version.def (common_reference_wrapper): New. + * include/bits/version.h: Regenerate. + * include/std/functional (__glibcxx_want_common_reference_wrapper): + Define. + * testsuite/20_util/reference_wrapper/p2655r3.cc: New test. + +2025-12-05 Patrick Palka <ppalka@redhat.com> + + PR libstdc++/120446 + * include/bits/version.def (common_reference): New. + * include/bits/version.h: Regenerate. + * include/std/type_traits (__glibcxx_want_common_reference): + Define. + (__common_reference_impl<T1, T2, 1>): Add pointer convertibility + constraints as per P2655R3. + * testsuite/20_util/common_reference/p2655r3.cc: New test. + +2025-12-05 Patrick Palka <ppalka@redhat.com> + + PR c++/120446 + * include/std/type_traits (__common_reference_impl): Rewrite + partial specializations to use requires-clause instead of + an additional void_t template parameter. Consolidate the + partial specializations corresponding to bullet 1. + +2025-12-05 Patrick Palka <ppalka@redhat.com> + + * testsuite/20_util/function_objects/bind_front/111327.cc: + Add missing space before } ending a dg-error directive. + +2025-12-05 Patrick Palka <ppalka@redhat.com> + + PR libstdc++/111550 + * include/std/ranges (views::__adaptor::_Partial::operator()) + [_GLIBCXX_EXPLICIT_THIS_PARAMETER]: Also use deducing this + in C++20 mode when possible. + (views::__adaptor::_Pipe::Operator()) + [_GLIBCXX_EXPLICIT_THIS_PARAMETER]: Likewise. + * testsuite/std/ranges/adaptors/take.cc (test07): New test. + +2025-12-05 Patrick Palka <ppalka@redhat.com> + + PR libstdc++/111327 + * include/bits/binders.h (_Binder::operator()) + [_GLIBCXX_EXPLICIT_THIS_PARAMETER]: Also use deducing this in + C++20 mode when possible. + * testsuite/20_util/function_objects/bind_front/111327.cc: + Expect error inside header even in C++20 mode. + +2025-12-05 Patrick Palka <ppalka@redhat.com> + + PR libstdc++/111327 + * include/std/functional (_Not_fn::operator()) + [_GLIBCXX_EXPLICIT_THIS_PARAMETER]: Define as a single + overload using deducing this. + * testsuite/20_util/function_objects/not_fn/111327.cc: Extend test. + +2025-12-05 Patrick Palka <ppalka@redhat.com> + + * include/bits/c++config (_GLIBCXX_EXPLICIT_THIS_PARAMETER): + New. + 2025-12-04 François Dumont <frs.dumont@gmail.com> * include/debug/deque diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h index 6d8c0de..84b8b4c 100644 --- a/libstdc++-v3/include/bits/atomic_wait.h +++ b/libstdc++-v3/include/bits/atomic_wait.h @@ -118,7 +118,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __atomic_eq(const _Tp& __a, const _Tp& __b) { // TODO make this do the correct padding bit ignoring comparison - return __builtin_memcmp(&__a, &__b, sizeof(_Tp)) == 0; + return __builtin_memcmp(std::addressof(__a), std::addressof(__b), + sizeof(_Tp)) == 0; } // Storage for up to 64 bits of value, should be considered opaque bits. diff --git a/libstdc++-v3/include/bits/binders.h b/libstdc++-v3/include/bits/binders.h index 6489edd..9724717 100644 --- a/libstdc++-v3/include/bits/binders.h +++ b/libstdc++-v3/include/bits/binders.h @@ -125,7 +125,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_bound_args(__make_bound_args<_BoundArgs...>(std::forward<_Args>(__args)...)) { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); } -#if __cpp_explicit_this_parameter +#if _GLIBCXX_EXPLICIT_THIS_PARAMETER +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this template<typename _Self, typename... _CallArgs> constexpr _Result_t<_Self, _CallArgs...> operator()(this _Self&& __self, _CallArgs&&... __call_args) @@ -134,6 +136,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _S_call(__like_t<_Self, _Binder>(__self), std::forward<_CallArgs>(__call_args)...); } +# pragma GCC diagnostic pop #else template<typename... _CallArgs> requires true diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index eec3a4a..e6d8f18 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -927,6 +927,13 @@ namespace __gnu_cxx # define _GLIBCXX_USE_BUILTIN_TRAIT(BT) 0 #endif +// Whether deducing this is usable either officially, if in C++23 mode, or +// as an extension (Clang doesn't support the latter). +#if __cpp_explicit_this_parameter \ + || (__cplusplus >= 201103L && __GNUC__ >= 14 && !defined(_GLIBCXX_CLANG)) +# define _GLIBCXX_EXPLICIT_THIS_PARAMETER 202110L +#endif + // Mark code that should be ignored by the compiler, but seen by Doxygen. #define _GLIBCXX_DOXYGEN_ONLY(X) diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h index 612715e..5d9f8c8 100644 --- a/libstdc++-v3/include/bits/refwrap.h +++ b/libstdc++-v3/include/bits/refwrap.h @@ -457,6 +457,40 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) /// @} +#if __glibcxx_common_reference_wrapper // C++ >= 20 + namespace __detail + { + template<typename _Tp> + constexpr bool __is_ref_wrapper = false; + + template<typename _Tp> + constexpr bool __is_ref_wrapper<reference_wrapper<_Tp>> = true; + + template<typename _Rp, typename _Tp, typename _RQual, typename _TQual> + concept __ref_wrap_common_reference_exists_with = __is_ref_wrapper<_Rp> + && requires { typename common_reference_t<typename _Rp::type&, _TQual>; } + && convertible_to<_RQual, common_reference_t<typename _Rp::type&, _TQual>>; + } // namespace __detail + + template<typename _Rp, typename _Tp, + template<typename> class _RQual, template<typename> class _TQual> + requires __detail::__ref_wrap_common_reference_exists_with<_Rp, _Tp, + _RQual<_Rp>, _TQual<_Tp>> + && (!__detail::__ref_wrap_common_reference_exists_with<_Tp, _Rp, + _TQual<_Tp>, _RQual<_Rp>>) + struct basic_common_reference<_Rp, _Tp, _RQual, _TQual> + { using type = common_reference_t<typename _Rp::type&, _TQual<_Tp>>; }; + + template<typename _Tp, typename _Rp, + template<typename> class _TQual, template<typename> class _RQual> + requires __detail::__ref_wrap_common_reference_exists_with<_Rp, _Tp, + _RQual<_Rp>, _TQual<_Tp>> + && (!__detail::__ref_wrap_common_reference_exists_with<_Tp, _Rp, + _TQual<_Tp>, _RQual<_Rp>>) + struct basic_common_reference<_Tp, _Rp, _TQual, _RQual> + { using type = common_reference_t<typename _Rp::type&, _TQual<_Tp>>; }; +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index d20e085..412b9ce 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1822,6 +1822,22 @@ ftms = { }; ftms = { + name = common_reference; + values = { + v = 202302; + cxxmin = 20; // We treat P2655R3 as a DR against C++20. + }; +}; + +ftms = { + name = common_reference_wrapper; + values = { + v = 202302; + cxxmin = 20; // We treat P2655R3 as a DR against C++20. + }; +}; + +ftms = { name = formatters; values = { v = 202302; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index c75368d4..2b96934 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2030,6 +2030,26 @@ #endif /* !defined(__cpp_lib_flat_set) */ #undef __glibcxx_want_flat_set +#if !defined(__cpp_lib_common_reference) +# if (__cplusplus >= 202002L) +# define __glibcxx_common_reference 202302L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_common_reference) +# define __cpp_lib_common_reference 202302L +# endif +# endif +#endif /* !defined(__cpp_lib_common_reference) && defined(__glibcxx_want_common_reference) */ +#undef __glibcxx_want_common_reference + +#if !defined(__cpp_lib_common_reference_wrapper) +# if (__cplusplus >= 202002L) +# define __glibcxx_common_reference_wrapper 202302L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_common_reference_wrapper) +# define __cpp_lib_common_reference_wrapper 202302L +# endif +# endif +#endif /* !defined(__cpp_lib_common_reference_wrapper) && defined(__glibcxx_want_common_reference_wrapper) */ +#undef __glibcxx_want_common_reference_wrapper + #if !defined(__cpp_lib_formatters) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_formatters 202302L diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic index ccb77fa..0a510d8 100644 --- a/libstdc++-v3/include/std/atomic +++ b/libstdc++-v3/include/std/atomic @@ -406,21 +406,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept { - std::__atomic_wait_address_v(&_M_i, __old, - [__m, this] { return this->load(__m); }); + std::__atomic_wait_address_v(std::addressof(_M_i), __old, + [__m, this] { return this->load(__m); }); } // TODO add const volatile overload void notify_one() noexcept - { std::__atomic_notify_address(&_M_i, false); } + { std::__atomic_notify_address(std::addressof(_M_i), false); } void notify_all() noexcept - { std::__atomic_notify_address(&_M_i, true); } + { std::__atomic_notify_address(std::addressof(_M_i), true); } #endif // __cpp_lib_atomic_wait - }; /// Partial specialization for pointer types. diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 1928a27..570e9e9 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -64,6 +64,7 @@ #define __glibcxx_want_not_fn #define __glibcxx_want_ranges #define __glibcxx_want_reference_wrapper +#define __glibcxx_want_common_reference_wrapper #define __glibcxx_want_transparent_operators #include <bits/version.h> @@ -495,6 +496,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION # define _GLIBCXX_DEPR_BIND #endif +#if _GLIBCXX_EXPLICIT_THIS_PARAMETER + // Return a _Up that has the same cv-quals as _Tp. + template<typename _Tp, typename _Up> // _Up should be cv-unqualified + struct __cv_like + { using type = _Up; }; + + template<typename _Tp, typename _Up> + struct __cv_like<const _Tp, _Up> + { using type = const _Up; }; + + template<typename _Tp, typename _Up> + struct __cv_like<volatile _Tp, _Up> + { using type = volatile _Up; }; + + template<typename _Tp, typename _Up> + struct __cv_like<const volatile _Tp, _Up> + { using type = const volatile _Up; }; + + template<typename _Tp, typename _Up> + using __cv_like_t = typename __cv_like<_Tp, _Up>::type; +#endif + /// Type of the function object returned from bind(). template<typename _Signature> class _Bind; @@ -564,6 +587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _Res_type_impl = __invoke_result_t<_Fn&, _Mu_type<_BArgs, _CallArgs>&&...>; +#if !_GLIBCXX_EXPLICIT_THIS_PARAMETER template<typename _CallArgs> using _Res_type = _Res_type_impl<_Functor, _CallArgs, _Bound_args...>; @@ -576,6 +600,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename __cv_quals<__dependent<_CallArgs>>::type, _CallArgs, typename __cv_quals<_Bound_args>::type...>; +#endif public: template<typename... _Args> @@ -593,6 +618,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Bind(const _Bind&) = default; _Bind(_Bind&&) = default; +#if _GLIBCXX_EXPLICIT_THIS_PARAMETER +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr +# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this + template<typename... _Args, + typename _Self, + typename _Self_nonref = typename remove_reference<_Self>::type, + __enable_if_t<!is_volatile<_Self_nonref>::value, int> = 0, + typename _Result + = _Res_type_impl<__cv_like_t<_Self_nonref, _Functor>, + tuple<_Args...>, + __cv_like_t<_Self_nonref, _Bound_args>...>> + _GLIBCXX20_CONSTEXPR + _Result + operator()(this _Self&& __self, _Args&&... __args) + { + using _Bind_ref = __cv_like_t<_Self_nonref, _Bind>&; + if constexpr (is_const<_Self_nonref>::value) + return _Bind_ref(__self) + .template __call_c<_Result>(std::forward_as_tuple + (std::forward<_Args>(__args)...), + _Bound_indexes()); + else + return _Bind_ref(__self) + .template __call<_Result>(std::forward_as_tuple + (std::forward<_Args>(__args)...), + _Bound_indexes()); + } + +# if defined(_GLIBCXX_VOLATILE_BIND) + template<typename... _Args, + typename _Self, + typename _Self_nonref = typename remove_reference<_Self>::type, + __enable_if_t<is_volatile<_Self_nonref>::value, int> = 0, + typename _Result + = _Res_type_impl<__cv_like_t<_Self_nonref, _Functor>, + tuple<_Args...>, + __cv_like_t<_Self_nonref, _Bound_args>...>> + _GLIBCXX_DEPR_BIND + _Result + operator()(this _Self&& __self, _Args&&... __args) + { + using _Bind_ref = __cv_like_t<_Self_nonref, _Bind>&; + if constexpr (is_const<_Self_nonref>::value) + return _Bind_ref(__self) + .template __call_c_v<_Result>(std::forward_as_tuple + (std::forward<_Args>(__args)...), + _Bound_indexes()); + else + return _Bind_ref(__self) + .template __call_v<_Result>(std::forward_as_tuple + (std::forward<_Args>(__args)...), + _Bound_indexes()); + } +# endif +# pragma GCC diagnostic pop +#else // Call unqualified template<typename... _Args, typename _Result = _Res_type<tuple<_Args...>>> @@ -642,6 +724,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Bound_indexes()); } #endif // volatile +#endif }; /// Type of the function object returned from bind<R>(). @@ -1056,6 +1139,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Not_fn(_Not_fn&& __fn) = default; ~_Not_fn() = default; +#if _GLIBCXX_EXPLICIT_THIS_PARAMETER +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this + template<typename _Self, typename... _Args> + _GLIBCXX20_CONSTEXPR + decltype(_S_not<__inv_res_t<__like_t<_Self, _Fn>, _Args...>>()) + operator()(this _Self&& __self, _Args&&... __args) + noexcept(__is_nothrow_invocable<__like_t<_Self, _Fn>, _Args...>::value + && noexcept(_S_not<__inv_res_t<__like_t<_Self, _Fn>, _Args...>>())) + { + return !std::__invoke(__like_t<_Self, _Not_fn>(__self)._M_fn, + std::forward<_Args>(__args)...); + } +# pragma GCC diagnostic pop +#else // Macro to define operator() with given cv-qualifiers ref-qualifiers, // forwarding _M_fn and the function arguments with the same qualifiers, // and deducing the return type and exception-specification. @@ -1081,6 +1179,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOT_FN_CALL_OP( && ) _GLIBCXX_NOT_FN_CALL_OP( const && ) #undef _GLIBCXX_NOT_FN_CALL_OP +#endif private: _Fn _M_fn; diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index b3105c5..b81ee78 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -1259,7 +1259,9 @@ namespace views::__adaptor // Invoke _Adaptor with arguments __r, _M_args... according to the // value category of this _Partial object. -#if __cpp_explicit_this_parameter +#if _GLIBCXX_EXPLICIT_THIS_PARAMETER +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this template<typename _Self, typename _Range> requires __adaptor_invocable<_Adaptor, _Range, __like_t<_Self, _Args>...> constexpr auto @@ -1268,6 +1270,7 @@ namespace views::__adaptor return _Binder::_S_call(__like_t<_Self, _Partial>(__self)._M_binder, std::forward<_Range>(__r)); } +# pragma GCC diagnostic pop #else template<typename _Range> requires __adaptor_invocable<_Adaptor, _Range, const _Args&...> @@ -1336,7 +1339,9 @@ namespace views::__adaptor // Invoke _M_rhs(_M_lhs(__r)) according to the value category of this // range adaptor closure object. -#if __cpp_explicit_this_parameter +#if _GLIBCXX_EXPLICIT_THIS_PARAMETER +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this template<typename _Self, typename _Range> requires __pipe_invocable<__like_t<_Self, _Lhs>, __like_t<_Self, _Rhs>, _Range> constexpr auto @@ -1346,6 +1351,7 @@ namespace views::__adaptor (__like_t<_Self, _Pipe>(__self)._M_lhs (std::forward<_Range>(__r)))); } +# pragma GCC diagnostic pop #else template<typename _Range> requires __pipe_invocable<const _Lhs&, const _Rhs&, _Range> diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 5c09fac..7c157ea 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -41,6 +41,7 @@ #define __glibcxx_want_bool_constant #define __glibcxx_want_bounded_array_traits +#define __glibcxx_want_common_reference #define __glibcxx_want_constant_wrapper #define __glibcxx_want_has_unique_object_representations #define __glibcxx_want_integral_constant_callable @@ -4225,7 +4226,7 @@ template<typename _Ret, typename _Fn, typename... _Args> { using type = _Tp0; }; /// @cond undocumented - template<typename _Tp1, typename _Tp2, int _Bullet = 1, typename = void> + template<typename _Tp1, typename _Tp2, int _Bullet = 1> struct __common_reference_impl : __common_reference_impl<_Tp1, _Tp2, _Bullet + 1> { }; @@ -4238,46 +4239,38 @@ template<typename _Ret, typename _Fn, typename... _Args> // If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ... template<typename _Tp1, typename _Tp2> - struct __common_reference_impl<_Tp1&, _Tp2&, 1, - void_t<__common_ref<_Tp1&, _Tp2&>>> - { using type = __common_ref<_Tp1&, _Tp2&>; }; - - template<typename _Tp1, typename _Tp2> - struct __common_reference_impl<_Tp1&&, _Tp2&&, 1, - void_t<__common_ref<_Tp1&&, _Tp2&&>>> - { using type = __common_ref<_Tp1&&, _Tp2&&>; }; - - template<typename _Tp1, typename _Tp2> - struct __common_reference_impl<_Tp1&, _Tp2&&, 1, - void_t<__common_ref<_Tp1&, _Tp2&&>>> - { using type = __common_ref<_Tp1&, _Tp2&&>; }; - - template<typename _Tp1, typename _Tp2> - struct __common_reference_impl<_Tp1&&, _Tp2&, 1, - void_t<__common_ref<_Tp1&&, _Tp2&>>> - { using type = __common_ref<_Tp1&&, _Tp2&>; }; + requires is_reference_v<_Tp1> && is_reference_v<_Tp2> + && requires { typename __common_ref<_Tp1, _Tp2>; } +#if __cpp_lib_common_reference // C++ >= 20 + && is_convertible_v<add_pointer_t<_Tp1>, + add_pointer_t<__common_ref<_Tp1, _Tp2>>> + && is_convertible_v<add_pointer_t<_Tp2>, + add_pointer_t<__common_ref<_Tp1, _Tp2>>> +#endif + struct __common_reference_impl<_Tp1, _Tp2, 1> + { using type = __common_ref<_Tp1, _Tp2>; }; // Otherwise, if basic_common_reference<...>::type is well-formed, ... template<typename _Tp1, typename _Tp2> - struct __common_reference_impl<_Tp1, _Tp2, 2, - void_t<__basic_common_ref<_Tp1, _Tp2>>> + requires requires { typename __basic_common_ref<_Tp1, _Tp2>; } + struct __common_reference_impl<_Tp1, _Tp2, 2> { using type = __basic_common_ref<_Tp1, _Tp2>; }; // Otherwise, if COND-RES(T1, T2) is well-formed, ... template<typename _Tp1, typename _Tp2> - struct __common_reference_impl<_Tp1, _Tp2, 3, - void_t<__cond_res<_Tp1, _Tp2>>> + requires requires { typename __cond_res<_Tp1, _Tp2>; } + struct __common_reference_impl<_Tp1, _Tp2, 3> { using type = __cond_res<_Tp1, _Tp2>; }; // Otherwise, if common_type_t<T1, T2> is well-formed, ... template<typename _Tp1, typename _Tp2> - struct __common_reference_impl<_Tp1, _Tp2, 4, - void_t<common_type_t<_Tp1, _Tp2>>> + requires requires { typename common_type_t<_Tp1, _Tp2>; } + struct __common_reference_impl<_Tp1, _Tp2, 4> { using type = common_type_t<_Tp1, _Tp2>; }; // Otherwise, there shall be no member type. template<typename _Tp1, typename _Tp2> - struct __common_reference_impl<_Tp1, _Tp2, 5, void> + struct __common_reference_impl<_Tp1, _Tp2, 5> { }; // Otherwise, if sizeof...(T) is greater than two, ... @@ -4296,7 +4289,7 @@ template<typename _Ret, typename _Fn, typename... _Args> { }; /// @endcond -#endif // C++2a +#endif // C++20 #if __cplusplus >= 201103L // Stores a tuple of indices. Used by tuple and pair, and by bind() to diff --git a/libstdc++-v3/testsuite/20_util/bind/80564.cc b/libstdc++-v3/testsuite/20_util/bind/80564.cc new file mode 100644 index 0000000..f6e1a1e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/bind/80564.cc @@ -0,0 +1,50 @@ +// PR libstdc++/80564 - bind on SFINAE unfriendly generic lambda +// { dg-do compile { target c++14 } } + +#include <functional> + +struct A +{ + template<typename T> + auto operator()(T&) + { } + + template<typename T> + auto operator()(T&) const + { T::fail; } +}; + +void +test01() +{ + A a; + std::bind(a, 0)(); // doesn't consider the const overload + std::bind<void>(a, 0)(); +} + +void +test02() +{ + auto f = [] (auto& x) { x = 1; }; + int i; + std::bind(f, i)(); // doesn't try const-invoking the lambda + std::bind<void>(f, i)(); +} + +#if __cpp_variadic_using +template<typename... Ts> +struct overloaded : private Ts... +{ + overloaded(Ts... ts) : Ts(ts)... { } + using Ts::operator()...; +}; + +void +test03() +{ + A a; + auto f = std::bind(a, 0); + overloaded<decltype(f)> g(f); + g(); +} +#endif diff --git a/libstdc++-v3/testsuite/20_util/bind/cv_quals_2.cc b/libstdc++-v3/testsuite/20_util/bind/cv_quals_2.cc index e4c348f..6d37cc4 100644 --- a/libstdc++-v3/testsuite/20_util/bind/cv_quals_2.cc +++ b/libstdc++-v3/testsuite/20_util/bind/cv_quals_2.cc @@ -44,6 +44,9 @@ void test01() // { dg-error "no match" "" { target c++20 } 43 } } +// Ignore the reasons for deduction/substitution failure in the headers. +// { dg-prune-output "no type named 'type' in 'struct std::enable_if<false" } + int main() { test01(); diff --git a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc index dd47c43..46cc4bb 100644 --- a/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc +++ b/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc @@ -51,6 +51,7 @@ void test02() // Ignore the reasons for deduction/substitution failure in the headers. // Arrange for the match to work on installed trees as well as build trees. // { dg-prune-output "no type named 'type' in 'struct std::__invoke_result" } +// { dg-prune-output "no type named 'type' in 'struct std::enable_if<false" } int main() { diff --git a/libstdc++-v3/testsuite/20_util/common_reference/p2655r3.cc b/libstdc++-v3/testsuite/20_util/common_reference/p2655r3.cc new file mode 100644 index 0000000..4188dd2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/common_reference/p2655r3.cc @@ -0,0 +1,15 @@ +// P2655R3 - common_reference_t of reference_wrapper Should Be a Reference Type +// Implemented as a DR against C++20 +// { dg-do compile { target c++20 } } + +#include <type_traits> + +#if __cpp_lib_common_reference != 202302L +# error "Feature-test macro __cpp_lib_common_reference has wrong value in <type_traits>" +#endif + +struct A { }; +struct B { operator A&() const; }; + +static_assert( std::is_same_v<std::common_reference_t<A&, const B&>, A&> ); +static_assert( std::is_same_v<std::common_reference_t<const B&, A&>, A&> ); diff --git a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc index 58832a6..493ef08 100644 --- a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc @@ -50,4 +50,4 @@ int main() { std::move(std::as_const(g2))(); } -// { dg-error "no type named 'type' in 'std::__conditional_t<false, std::invoke_result<" "" { target c++23 } 0 } +// { dg-error "no type named 'type' in 'std::__conditional_t<false, std::invoke_result<" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc index 725a842..be58b0e 100644 --- a/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc +++ b/libstdc++-v3/testsuite/20_util/function_objects/not_fn/111327.cc @@ -15,15 +15,28 @@ struct G { bool operator()(...) const &&; }; +struct Weird { + void operator()(); + bool operator()() const { return true; } +}; + int main() { auto f = std::not_fn(F{}); - f(); // { dg-error "deleted" } + f(); // { dg-error "no match" } std::move(f)(); std::as_const(f)(); std::move(std::as_const(f))(); auto g = std::not_fn(G{}); - g(); // { dg-error "deleted" } - std::move(g)(); // { dg-error "deleted" } + g(); // { dg-error "no match" } + std::move(g)(); // { dg-error "no match" } std::move(std::as_const(g))(); + + auto h = std::not_fn(Weird{}); + h(); // { dg-error "no match" } } + +// { dg-error "no type named 'type' in 'struct std::__invoke_result<" "" { target *-*-* } 0 } +// { dg-error "no matching function for call to 'std::_Not_fn<Weird>" "" { target *-*-* } 0 } +// { dg-error "could not convert 'std::declval<void>\\(\\)' from 'void' to 'bool'" "" { target *-*-* } 0 } +// { dg-error "in argument to unary !" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc new file mode 100644 index 0000000..f2fafec --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc @@ -0,0 +1,75 @@ +// P2655R3 - common_reference_t of reference_wrapper Should Be a Reference Type +// Implemented as a DR against C++20 +// { dg-do compile { target c++20 } } + +#include <functional> + +#if __cpp_lib_common_reference_wrapper != 202302L +# error "Feature-test macro __cpp_lib_common_reference_wrapper has wrong value in <functional>" +#endif + +using std::is_same_v; +using std::common_reference_t; +using std::reference_wrapper; + +static_assert( is_same_v<common_reference_t<const reference_wrapper<int>&, int&>, int&> ); +static_assert( is_same_v<common_reference_t<int&, const reference_wrapper<int>&>, int&> ); + +static_assert( is_same_v<common_reference_t<reference_wrapper<int>, int&>, + common_reference_t<int&, int&>> ); +static_assert( is_same_v<common_reference_t<reference_wrapper<int>, const int&>, + common_reference_t<int&, const int&>> ); +static_assert( is_same_v<common_reference_t<reference_wrapper<const int>, int&>, + common_reference_t<const int&, int&>> ); + +static_assert( is_same_v<common_reference_t<int&, reference_wrapper<int>>, + common_reference_t<int&, int&>> ); +static_assert( is_same_v<common_reference_t<const int&, reference_wrapper<int>>, + common_reference_t<int&, const int&>> ); +static_assert( is_same_v<common_reference_t<int&, reference_wrapper<const int>>, + common_reference_t<const int&, int&>> ); + +static_assert( is_same_v<common_reference_t<reference_wrapper<int>&, reference_wrapper<int>&>, + reference_wrapper<int>&> ); + +static_assert( is_same_v<common_reference_t<reference_wrapper<char>, + reference_wrapper<int>>, + int> ); +static_assert( is_same_v<common_reference_t<reference_wrapper<reference_wrapper<int>>, + reference_wrapper<int>>, + reference_wrapper<int>> ); +static_assert( is_same_v<common_reference_t<reference_wrapper<int>, + reference_wrapper<reference_wrapper<int>>>, + reference_wrapper<int>> ); + +struct A { }; +struct B { operator A&() const; }; + +template<typename T, typename U> +concept has_common_reference = requires { + typename std::common_reference_t<T, U>; +}; + +static_assert( is_same_v<common_reference_t<reference_wrapper<A>, const B&>, A&> ); +// reference_wrapper<const B> is not convertible to A&, as it would require two user +// defined conversions. +static_assert( !has_common_reference<A, reference_wrapper<const B>> ); +static_assert( !has_common_reference<reference_wrapper<A>, reference_wrapper<const B>> ); + +struct D1 : A {}; +struct D2 : A {}; + +template<template<class> typename Qual1, template<class> typename Qual2> +struct std::basic_common_reference<D1, D2, Qual1, Qual2> + : std::common_reference<Qual1<A>, Qual2<A>> +{ }; + +template<template<class> typename Qual1, template<class> typename Qual2> +struct std::basic_common_reference<D2, D1, Qual1, Qual2> + : std::common_reference<Qual1<A>, Qual2<A>> +{ }; + +static_assert( is_same_v<common_reference_t<D1&, D2&>, A&> ); +static_assert( is_same_v<common_reference_t<reference_wrapper<D1>, D2&>, A&> ); +static_assert( is_same_v<common_reference_t<D1&, reference_wrapper<D2>>, A&> ); +static_assert( !has_common_reference<reference_wrapper<D1>, reference_wrapper<D2>> ); diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc b/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc index 1673772..9584c57 100644 --- a/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/take.cc @@ -118,6 +118,20 @@ test06() static_assert(!requires { views::all | take; }); } +void +test07() +{ + // PR libstdc++/111550 + struct Five { + operator int() & { return 5; } + operator int() && = delete; + }; + auto take_five = views::take(Five{}); + auto r = take_five(views::iota(0)); + auto take_five_piped = views::take(Five{}) | views::transform(std::identity{}); + auto s = take_five_piped(views::iota(0)); +} + int main() { @@ -127,4 +141,5 @@ main() test04(); test05(); test06(); + test07(); } |
