diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst index d0383a705190d..6cbc0baf29487 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -97,6 +97,8 @@ Potentially breaking changes - The implementation of ``num_put::do_put`` has been replaced to improve the performance, which can lead to different output when printing pointers. +- User-defined specializations of ``std::common_reference`` are diagnosed now. To customize the common reference type, ``std::basic_common_reference`` should be specialized instead. + Announcements About Future Releases ----------------------------------- diff --git a/libcxx/include/__type_traits/common_reference.h b/libcxx/include/__type_traits/common_reference.h index c27da5251b9b7..7df55f7fecfd5 100644 --- a/libcxx/include/__type_traits/common_reference.h +++ b/libcxx/include/__type_traits/common_reference.h @@ -109,11 +109,18 @@ struct __common_ref {}; // Note C: For the common_reference trait applied to a parameter pack [...] template -struct common_reference; +struct _LIBCPP_NO_SPECIALIZATIONS common_reference; template using common_reference_t = typename common_reference<_Types...>::type; +template class, template class> +struct basic_common_reference {}; + +_LIBCPP_DIAGNOSTIC_PUSH +# if __has_warning("-Winvalid-specialization") +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Winvalid-specialization") +# endif // bullet 1 - sizeof...(T) == 0 template <> struct common_reference<> {}; @@ -145,9 +152,6 @@ struct __common_reference_sub_bullet1<_Tp, _Up> { // sub-bullet 2 - Otherwise, if basic_common_reference, remove_cvref_t, XREF(T1), XREF(T2)>::type // is well-formed, then the member typedef `type` denotes that type. -template class, template class> -struct basic_common_reference {}; - template using __basic_common_reference_t _LIBCPP_NODEBUG = typename basic_common_reference, @@ -180,10 +184,11 @@ struct __common_reference_sub_bullet3 : common_type<_Tp, _Up> {}; template requires requires { typename common_reference_t<_Tp, _Up>; } struct common_reference<_Tp, _Up, _Vp, _Rest...> : common_reference, _Vp, _Rest...> {}; +_LIBCPP_DIAGNOSTIC_POP // bullet 5 - Otherwise, there shall be no member `type`. template -struct common_reference {}; +struct _LIBCPP_NO_SPECIALIZATIONS common_reference {}; #endif // _LIBCPP_STD_VER >= 20 diff --git a/libcxx/test/libcxx/type_traits/no_specializations.verify.cpp b/libcxx/test/libcxx/type_traits/no_specializations.verify.cpp index 38560161f162e..897ae89365014 100644 --- a/libcxx/test/libcxx/type_traits/no_specializations.verify.cpp +++ b/libcxx/test/libcxx/type_traits/no_specializations.verify.cpp @@ -186,5 +186,12 @@ struct std::enable_if; // expected-error {{cannot be specialized}} # if TEST_STD_VER >= 20 template <> struct std::integral_constant; // expected-error {{cannot be specialized}} + +template <> +struct std::common_reference; // expected-error {{cannot be specialized}} +template <> +struct std::common_reference; // expected-error {{cannot be specialized}} +template <> +struct std::common_reference; // expected-error {{cannot be specialized}} # endif #endif diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp index 5fc6ffd37caf1..086e79b799c36 100644 --- a/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp +++ b/libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp @@ -78,16 +78,10 @@ struct missing_iter_value_t { }; static_assert(!check_indirectly_readable()); -struct unrelated_lvalue_ref_and_rvalue_ref {}; - -struct iter_ref1 {}; -template <> -struct std::common_reference {}; - -template <> -struct std::common_reference {}; - -static_assert(!std::common_reference_with); +struct iter_ref1 { + iter_ref1(const iter_ref1&) = delete; + iter_ref1(iter_ref1&&) = delete; +}; struct bad_iter_reference_t { using value_type = int; @@ -128,24 +122,9 @@ struct different_reference_types_with_common_reference { static_assert(check_indirectly_readable()); struct iter_ref4 { - operator iter_rvalue_ref() const; + operator iter_rvalue_ref(); }; -template