Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@ _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);
#elif __has_builtin(__reference_binds_to_temporary)
// TODO: Remove this once all support compilers 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);
#else
// TODO: Remove this once https://github.com/llvm/llvm-project/issues/111477 no longer affects supported compilers.
template <class _Tp, class _Up>
inline const bool __reference_constructs_from_temporary_v = false;
#endif

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY_H
14 changes: 3 additions & 11 deletions libcxx/include/tuple
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -346,15 +338,15 @@ 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");
}

template <class _Tp, class _Alloc>
_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");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,16 @@ template <class T> struct CannotDeduce {
template <class ...Args>
void F(typename CannotDeduce<std::tuple<Args...>>::type const&) {}

#if TEST_HAS_BUILTIN(__reference_constructs_from_temporary)
# define TEST_HAS_REFERENCE_BINDING_TRAIT 1
#elif TEST_HAS_BUILTIN(__reference_binds_to_temporary)
# define TEST_HAS_REFERENCE_BINDING_TRAIT 1
#else
# define TEST_HAS_REFERENCE_BINDING_TRAIT 0
#endif

void f() {
#if TEST_HAS_BUILTIN_IDENTIFIER(__reference_binds_to_temporary)
#if TEST_HAS_REFERENCE_BINDING_TRAIT
// 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}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@
#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__), "")
#elif TEST_HAS_BUILTIN(__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__), "")
#else
# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "")
# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "")
# define ASSERT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "")
# define ASSERT_NOT_REFERENCE_BINDS_TEMPORARY(...) static_assert(true, "")
#endif

template <class Tp>
Expand Down
Loading