diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h index 1c62e58cc4e12..2ff549b4e15ce 100644 --- a/libcxx/include/__type_traits/reference_constructs_from_temporary.h +++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h @@ -30,6 +30,15 @@ _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_tempo #endif +#if __has_builtin(__reference_constructs_from_temporary) +template +inline const bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up); +#else +// TODO(LLVM 22): Remove this as all supported compilers should have __reference_constructs_from_temporary implemented. +template +inline const bool __reference_constructs_from_temporary_v = __reference_binds_to_temporary(_Tp, _Up); +#endif + _LIBCPP_END_NAMESPACE_STD #endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY_H diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 8dd62ae624f5e..6e7a430d219ea 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -258,6 +258,7 @@ template # include <__type_traits/maybe_const.h> # include <__type_traits/nat.h> # include <__type_traits/negation.h> +# include <__type_traits/reference_constructs_from_temporary.h> # include <__type_traits/remove_cv.h> # include <__type_traits/remove_cvref.h> # include <__type_traits/remove_reference.h> @@ -308,15 +309,6 @@ template class __tuple_leaf { _Hp __value_; - template - static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() { -# if __has_keyword(__reference_binds_to_temporary) - return !__reference_binds_to_temporary(_Hp, _Tp); -# else - return true; -# endif - } - public: _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_leaf& operator=(const __tuple_leaf&) = delete; @@ -346,7 +338,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(_Tp&& __t) noexcept(is_nothrow_constructible<_Hp, _Tp>::value) : __value_(std::forward<_Tp>(__t)) { - static_assert(__can_bind_reference<_Tp&&>(), + static_assert(!__reference_constructs_from_temporary_v<_Hp, _Tp&&>, "Attempted construction of reference element binds to a temporary whose lifetime has ended"); } @@ -354,7 +346,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(integral_constant, const _Alloc&, _Tp&& __t) : __value_(std::forward<_Tp>(__t)) { - static_assert(__can_bind_reference<_Tp&&>(), + static_assert(!__reference_constructs_from_temporary_v<_Hp, _Tp&&>, "Attempted construction of reference element binds to a temporary whose lifetime has ended"); } diff --git a/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.verify.cpp b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.verify.cpp index 4a6e3095c1019..a1a80483c4487 100644 --- a/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.verify.cpp +++ b/libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.verify.cpp @@ -38,9 +38,7 @@ template struct CannotDeduce { template void F(typename CannotDeduce>::type const&) {} - void f() { -#if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary) // Test that we emit our diagnostic from the library. // expected-error@tuple:* 8 {{Attempted construction of reference element binds to a temporary whose lifetime has ended}} @@ -73,8 +71,4 @@ void f() { std::tuple t2("hello"); // expected-note {{requested here}} std::tuple t3(std::allocator_arg, alloc, "hello"); // expected-note {{requested here}} } -#else -#error force failure -// expected-error@-1 {{force failure}} -#endif } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp index 463816929353b..d78de0eec8e53 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp @@ -18,12 +18,14 @@ #include #include "test_macros.h" -#if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary) -# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_binds_to_temporary(__VA_ARGS__), "") -# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(!__reference_binds_to_temporary(__VA_ARGS__), "") +#if TEST_HAS_BUILTIN(__reference_constructs_from_temporary) +# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_constructs_from_temporary(__VA_ARGS__), "") +# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) \ + static_assert(!__reference_constructs_from_temporary(__VA_ARGS__), "") #else -# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "") -# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "") +// TODO(LLVM 22): Remove this as all support compilers should have __reference_constructs_from_temporary implemented. +# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_binds_to_temporary(__VA_ARGS__), "") +# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(!__reference_binds_to_temporary(__VA_ARGS__), "") #endif template