Skip to content

Commit a660400

Browse files
frederick-vs-japhilnik777
authored andcommitted
[libc++] Use __reference_constructs_from_temporary if eligible (llvm#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>
1 parent c6b6ab4 commit a660400

File tree

4 files changed

+19
-22
lines changed

4 files changed

+19
-22
lines changed

libcxx/include/__type_traits/reference_constructs_from_temporary.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_tempo
3030

3131
#endif
3232

33+
#if __has_builtin(__reference_constructs_from_temporary)
34+
template <class _Tp, class _Up>
35+
inline const bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up);
36+
#else
37+
// TODO(LLVM 22): Remove this as all supported compilers should have __reference_constructs_from_temporary implemented.
38+
template <class _Tp, class _Up>
39+
inline const bool __reference_constructs_from_temporary_v = __reference_binds_to_temporary(_Tp, _Up);
40+
#endif
41+
3342
_LIBCPP_END_NAMESPACE_STD
3443

3544
#endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY_H

libcxx/include/tuple

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ template <class... Types>
258258
# include <__type_traits/maybe_const.h>
259259
# include <__type_traits/nat.h>
260260
# include <__type_traits/negation.h>
261+
# include <__type_traits/reference_constructs_from_temporary.h>
261262
# include <__type_traits/remove_cv.h>
262263
# include <__type_traits/remove_cvref.h>
263264
# include <__type_traits/remove_reference.h>
@@ -308,15 +309,6 @@ template <size_t _Ip, class _Hp, bool>
308309
class __tuple_leaf {
309310
_Hp __value_;
310311

311-
template <class _Tp>
312-
static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() {
313-
# if __has_keyword(__reference_binds_to_temporary)
314-
return !__reference_binds_to_temporary(_Hp, _Tp);
315-
# else
316-
return true;
317-
# endif
318-
}
319-
320312
public:
321313
_LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_leaf& operator=(const __tuple_leaf&) = delete;
322314

@@ -346,15 +338,15 @@ public:
346338
_LIBCPP_HIDE_FROM_ABI
347339
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(_Tp&& __t) noexcept(is_nothrow_constructible<_Hp, _Tp>::value)
348340
: __value_(std::forward<_Tp>(__t)) {
349-
static_assert(__can_bind_reference<_Tp&&>(),
341+
static_assert(!__reference_constructs_from_temporary_v<_Hp, _Tp&&>,
350342
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
351343
}
352344

353345
template <class _Tp, class _Alloc>
354346
_LIBCPP_HIDE_FROM_ABI
355347
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
356348
: __value_(std::forward<_Tp>(__t)) {
357-
static_assert(__can_bind_reference<_Tp&&>(),
349+
static_assert(!__reference_constructs_from_temporary_v<_Hp, _Tp&&>,
358350
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
359351
}
360352

libcxx/test/libcxx/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.verify.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ template <class T> struct CannotDeduce {
3838
template <class ...Args>
3939
void F(typename CannotDeduce<std::tuple<Args...>>::type const&) {}
4040

41-
4241
void f() {
43-
#if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary)
4442
// Test that we emit our diagnostic from the library.
4543
// expected-error@tuple:* 8 {{Attempted construction of reference element binds to a temporary whose lifetime has ended}}
4644

@@ -73,8 +71,4 @@ void f() {
7371
std::tuple<std::string &&> t2("hello"); // expected-note {{requested here}}
7472
std::tuple<std::string &&> t3(std::allocator_arg, alloc, "hello"); // expected-note {{requested here}}
7573
}
76-
#else
77-
#error force failure
78-
// expected-error@-1 {{force failure}}
79-
#endif
8074
}

libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/PR20855_tuple_ref_binding_diagnostics.pass.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
#include <cassert>
1919
#include "test_macros.h"
2020

21-
#if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary)
22-
# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_binds_to_temporary(__VA_ARGS__), "")
23-
# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(!__reference_binds_to_temporary(__VA_ARGS__), "")
21+
#if TEST_HAS_BUILTIN(__reference_constructs_from_temporary)
22+
# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_constructs_from_temporary(__VA_ARGS__), "")
23+
# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) \
24+
static_assert(!__reference_constructs_from_temporary(__VA_ARGS__), "")
2425
#else
25-
# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "")
26-
# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "")
26+
// TODO(LLVM 22): Remove this as all support compilers should have __reference_constructs_from_temporary implemented.
27+
# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(__reference_binds_to_temporary(__VA_ARGS__), "")
28+
# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(!__reference_binds_to_temporary(__VA_ARGS__), "")
2729
#endif
2830

2931
template <class Tp>

0 commit comments

Comments
 (0)