mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 10:58:11 +08:00
[libc++] Use __reference_constructs_from_temporary if eligible (#141916)
Currently, libc++'s `<tuple>` is using the deprecated `__reference_binds_to_temporary` intrinsic. This PR starts to use `__reference_constructs_from_temporary` if possible. It seems that `__reference_constructs_from_temporary` should be used via an internal type traits provided in `<__type_traits/reference_constructs_from_temporary.h>`. But given the old intrinsic was directly used, this PR doesn't switch to the current convention yet. P2255R2 is related. Although the paper indicated that constructors of `tuple` should be deleted in such a case. --------- Co-authored-by: Nikolas Klauser <nikolasklauser@berlin.de>
This commit is contained in:
@@ -30,6 +30,15 @@ _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_tempo
|
||||
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__reference_constructs_from_temporary)
|
||||
template <class _Tp, class _Up>
|
||||
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 <class _Tp, class _Up>
|
||||
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
|
||||
|
||||
@@ -258,6 +258,7 @@ template <class... Types>
|
||||
# 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 <size_t _Ip, class _Hp, bool>
|
||||
class __tuple_leaf {
|
||||
_Hp __value_;
|
||||
|
||||
template <class _Tp>
|
||||
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<int, 0>, 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");
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,7 @@ template <class T> struct CannotDeduce {
|
||||
template <class ...Args>
|
||||
void F(typename CannotDeduce<std::tuple<Args...>>::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<std::string &&> t2("hello"); // expected-note {{requested here}}
|
||||
std::tuple<std::string &&> t3(std::allocator_arg, alloc, "hello"); // expected-note {{requested here}}
|
||||
}
|
||||
#else
|
||||
#error force failure
|
||||
// expected-error@-1 {{force failure}}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
#include <cassert>
|
||||
#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 <class Tp>
|
||||
|
||||
Reference in New Issue
Block a user