[libcxx-commits] [libcxx] [libc++] Simplify the implementation of __tuple_leaf (PR #115729)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Nov 14 05:16:56 PST 2024
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/115729
>From 2aac7d84a2c2d1f4524325b25af4a4dd76541542 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Mon, 11 Nov 2024 16:52:40 +0100
Subject: [PATCH] [libc++] Simplify the implementation of __tuple_leaf
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__expected/expected.h | 50 +---------
.../__utility/conditional_no_unique_address.h | 87 +++++++++++++++++
libcxx/include/module.modulemap | 47 ++++-----
libcxx/include/tuple | 97 +++++--------------
...5_tuple_ref_binding_diagnostics.verify.cpp | 7 +-
6 files changed, 136 insertions(+), 153 deletions(-)
create mode 100644 libcxx/include/__utility/conditional_no_unique_address.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 1610d1ee848a5f..7c3acae4095a21 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -863,6 +863,7 @@ set(files
__utility/as_lvalue.h
__utility/auto_cast.h
__utility/cmp.h
+ __utility/conditional_no_unique_address.h
__utility/convert_to_integral.h
__utility/declval.h
__utility/empty.h
diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h
index 3d3f11967ee746..2c7bd90fa03784 100644
--- a/libcxx/include/__expected/expected.h
+++ b/libcxx/include/__expected/expected.h
@@ -40,6 +40,7 @@
#include <__type_traits/remove_cv.h>
#include <__type_traits/remove_cvref.h>
#include <__utility/as_const.h>
+#include <__utility/conditional_no_unique_address.h>
#include <__utility/exception_guard.h>
#include <__utility/forward.h>
#include <__utility/in_place.h>
@@ -81,55 +82,6 @@ _LIBCPP_HIDE_FROM_ABI void __throw_bad_expected_access(_Arg&& __arg) {
# endif
}
-// If parameter type `_Tp` of `__conditional_no_unique_address` is neither
-// copyable nor movable, a constructor with this tag is provided. For that
-// constructor, the user has to provide a function and arguments. The function
-// must return an object of type `_Tp`. When the function is invoked by the
-// constructor, guaranteed copy elision kicks in and the `_Tp` is constructed
-// in place.
-struct __conditional_no_unique_address_invoke_tag {};
-
-// This class implements an object with `[[no_unique_address]]` conditionally applied to it,
-// based on the value of `_NoUnique`.
-//
-// A member of this class must always have `[[no_unique_address]]` applied to
-// it. Otherwise, the `[[no_unique_address]]` in the "`_NoUnique == true`" case
-// would not have any effect. In the `false` case, the `__v` is not
-// `[[no_unique_address]]`, so nullifies the effects of the "outer"
-// `[[no_unique_address]]` regarding data layout.
-//
-// If we had a language feature, this class would basically be replaced by `[[no_unique_address(condition)]]`.
-template <bool _NoUnique, class _Tp>
-struct __conditional_no_unique_address;
-
-template <class _Tp>
-struct __conditional_no_unique_address<true, _Tp> {
- template <class... _Args>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(in_place_t, _Args&&... __args)
- : __v(std::forward<_Args>(__args)...) {}
-
- template <class _Func, class... _Args>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(
- __conditional_no_unique_address_invoke_tag, _Func&& __f, _Args&&... __args)
- : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
- _LIBCPP_NO_UNIQUE_ADDRESS _Tp __v;
-};
-
-template <class _Tp>
-struct __conditional_no_unique_address<false, _Tp> {
- template <class... _Args>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(in_place_t, _Args&&... __args)
- : __v(std::forward<_Args>(__args)...) {}
-
- template <class _Func, class... _Args>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __conditional_no_unique_address(
- __conditional_no_unique_address_invoke_tag, _Func&& __f, _Args&&... __args)
- : __v(std::invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
-
- _Tp __v;
-};
-
// This function returns whether the type `_Second` can be stuffed into the tail padding
// of the `_First` type if both of them are given `[[no_unique_address]]`.
template <class _First, class _Second>
diff --git a/libcxx/include/__utility/conditional_no_unique_address.h b/libcxx/include/__utility/conditional_no_unique_address.h
new file mode 100644
index 00000000000000..fbb9bf103af515
--- /dev/null
+++ b/libcxx/include/__utility/conditional_no_unique_address.h
@@ -0,0 +1,87 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___UTILITY_CONDITIONAL_NO_UNIQUE_ADDRESS_H
+#define _LIBCPP___UTILITY_CONDITIONAL_NO_UNIQUE_ADDRESS_H
+
+#include <__config>
+#include <__type_traits/invoke.h>
+#include <__type_traits/is_swappable.h>
+#include <__utility/forward.h>
+#include <__utility/in_place.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// If parameter type `_Tp` of `__conditional_no_unique_address` is neither
+// copyable nor movable, a constructor with this tag is provided. For that
+// constructor, the user has to provide a function and arguments. The function
+// must return an object of type `_Tp`. When the function is invoked by the
+// constructor, guaranteed copy elision kicks in and the `_Tp` is constructed
+// in place.
+struct __conditional_no_unique_address_invoke_tag {};
+
+// This class implements an object with `[[no_unique_address]]` conditionally applied to it,
+// based on the value of `_NoUnique`.
+//
+// A member of this class must always have `[[no_unique_address]]` applied to
+// it. Otherwise, the `[[no_unique_address]]` in the "`_NoUnique == true`" case
+// would not have any effect. In the `false` case, the `__v` is not
+// `[[no_unique_address]]`, so nullifies the effects of the "outer"
+// `[[no_unique_address]]` regarding data layout.
+//
+// If we had a language feature, this class would basically be replaced by `[[no_unique_address(condition)]]`.
+template <bool _NoUnique, class _Tp>
+struct __conditional_no_unique_address;
+
+template <class _Tp>
+struct __conditional_no_unique_address<true, _Tp> {
+ template <class... _Args>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __conditional_no_unique_address(in_place_t, _Args&&... __args)
+ : __v(std::forward<_Args>(__args)...) {}
+
+ template <class _Func, class... _Args>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __conditional_no_unique_address(
+ __conditional_no_unique_address_invoke_tag, _Func&& __f, _Args&&... __args)
+ : __v(std::__invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+
+ _LIBCPP_NO_UNIQUE_ADDRESS _Tp __v;
+};
+
+template <class _Tp>
+struct __conditional_no_unique_address<false, _Tp> {
+ template <class... _Args>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __conditional_no_unique_address(in_place_t, _Args&&... __args)
+ : __v(std::forward<_Args>(__args)...) {}
+
+ template <class _Func, class... _Args>
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __conditional_no_unique_address(
+ __conditional_no_unique_address_invoke_tag, _Func&& __f, _Args&&... __args)
+ : __v(std::__invoke(std::forward<_Func>(__f), std::forward<_Args>(__args)...)) {}
+
+ _Tp __v;
+};
+
+template <bool _NoUnique, class _Tp>
+void swap(__conditional_no_unique_address<_NoUnique, _Tp>& __lhs,
+ __conditional_no_unique_address<_NoUnique, _Tp>& __rhs) _NOEXCEPT_(__is_swappable_v<_Tp>) {
+ using std::swap;
+ swap(__lhs.__v, __rhs.__v);
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___UTILITY_CONDITIONAL_NO_UNIQUE_ADDRESS_H
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index cd08b2810e437b..ac11ea532eb806 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1988,36 +1988,37 @@ module std [system] {
}
module utility {
- module as_const { header "__utility/as_const.h" }
- module as_lvalue { header "__utility/as_lvalue.h" }
- module auto_cast {
+ module as_const { header "__utility/as_const.h" }
+ module as_lvalue { header "__utility/as_lvalue.h" }
+ module auto_cast {
header "__utility/auto_cast.h"
export std_core.type_traits.decay // the macro expansion uses that trait
}
- module cmp { header "__utility/cmp.h" }
- module convert_to_integral { header "__utility/convert_to_integral.h" }
- module exception_guard { header "__utility/exception_guard.h" }
- module exchange { header "__utility/exchange.h" }
- module forward_like { header "__utility/forward_like.h" }
+ module cmp { header "__utility/cmp.h" }
+ module conditional_no_unique_address { header "__utility/conditional_no_unique_address.h" }
+ module convert_to_integral { header "__utility/convert_to_integral.h" }
+ module exception_guard { header "__utility/exception_guard.h" }
+ module exchange { header "__utility/exchange.h" }
+ module forward_like { header "__utility/forward_like.h" }
module in_place {
header "__utility/in_place.h"
export std_core.type_traits.integral_constant
}
- module integer_sequence { header "__utility/integer_sequence.h" }
- module is_pointer_in_range { header "__utility/is_pointer_in_range.h" }
- module is_valid_range { header "__utility/is_valid_range.h" }
- module move { header "__utility/move.h" }
- module no_destroy { header "__utility/no_destroy.h" }
- module pair { header "__utility/pair.h" }
- module piecewise_construct { header "__utility/piecewise_construct.h" }
- module priority_tag { header "__utility/priority_tag.h" }
- module private_constructor_tag { header "__utility/private_constructor_tag.h" }
- module rel_ops { header "__utility/rel_ops.h" }
- module scope_guard { header "__utility/scope_guard.h" }
- module small_buffer { header "__utility/small_buffer.h" }
- module swap { header "__utility/swap.h" }
- module to_underlying { header "__utility/to_underlying.h" }
- module unreachable { header "__utility/unreachable.h" }
+ module integer_sequence { header "__utility/integer_sequence.h" }
+ module is_pointer_in_range { header "__utility/is_pointer_in_range.h" }
+ module is_valid_range { header "__utility/is_valid_range.h" }
+ module move { header "__utility/move.h" }
+ module no_destroy { header "__utility/no_destroy.h" }
+ module pair { header "__utility/pair.h" }
+ module piecewise_construct { header "__utility/piecewise_construct.h" }
+ module priority_tag { header "__utility/priority_tag.h" }
+ module private_constructor_tag { header "__utility/private_constructor_tag.h" }
+ module rel_ops { header "__utility/rel_ops.h" }
+ module scope_guard { header "__utility/scope_guard.h" }
+ module small_buffer { header "__utility/small_buffer.h" }
+ module swap { header "__utility/swap.h" }
+ module to_underlying { header "__utility/to_underlying.h" }
+ module unreachable { header "__utility/unreachable.h" }
header "utility"
export *
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index c3f7b8041686d1..47ca7bc02f163c 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -257,8 +257,10 @@ template <class... Types>
#include <__type_traits/remove_cvref.h>
#include <__type_traits/remove_reference.h>
#include <__type_traits/unwrap_ref.h>
+#include <__utility/conditional_no_unique_address.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
+#include <__utility/in_place.h>
#include <__utility/integer_sequence.h>
#include <__utility/move.h>
#include <__utility/piecewise_construct.h>
@@ -283,25 +285,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// __tuple_leaf
-template <size_t _Ip, class _Hp, bool = is_empty<_Hp>::value && !__libcpp_is_final<_Hp>::value >
+template <size_t _Ip, class _Hp>
class __tuple_leaf;
-template <size_t _Ip, class _Hp, bool _Ep>
+template <size_t _Ip, class _Hp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
-swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y) noexcept(__is_nothrow_swappable_v<_Hp>) {
+swap(__tuple_leaf<_Ip, _Hp>& __x, __tuple_leaf<_Ip, _Hp>& __y) noexcept(__is_nothrow_swappable_v<_Hp>) {
swap(__x.get(), __y.get());
}
-template <size_t _Ip, class _Hp, bool _Ep>
+template <size_t _Ip, class _Hp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
-swap(const __tuple_leaf<_Ip, _Hp, _Ep>& __x,
- const __tuple_leaf<_Ip, _Hp, _Ep>& __y) noexcept(__is_nothrow_swappable_v<const _Hp>) {
+swap(const __tuple_leaf<_Ip, _Hp>& __x,
+ const __tuple_leaf<_Ip, _Hp>& __y) noexcept(__is_nothrow_swappable_v<const _Hp>) {
swap(__x.get(), __y.get());
}
-template <size_t _Ip, class _Hp, bool>
+template <size_t _Ip, class _Hp>
class __tuple_leaf {
- _Hp __value_;
+ _LIBCPP_NO_UNIQUE_ADDRESS __conditional_no_unique_address<is_empty<_Hp>::value && !__libcpp_is_final<_Hp>::value, _Hp>
+ __value_;
template <class _Tp>
static _LIBCPP_HIDE_FROM_ABI constexpr bool __can_bind_reference() {
@@ -315,23 +318,24 @@ class __tuple_leaf {
public:
_LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_leaf& operator=(const __tuple_leaf&) = delete;
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf() noexcept(is_nothrow_default_constructible<_Hp>::value) : __value_() {
+ _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf() noexcept(is_nothrow_default_constructible<_Hp>::value)
+ : __value_(in_place) {
static_assert(!is_reference<_Hp>::value, "Attempted to default construct a reference element in a tuple");
}
template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 0>, const _Alloc&) : __value_() {
+ _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 0>, const _Alloc&) : __value_(in_place) {
static_assert(!is_reference<_Hp>::value, "Attempted to default construct a reference element in a tuple");
}
template <class _Alloc>
_LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
- : __value_(allocator_arg_t(), __a) {
+ : __value_(in_place, allocator_arg_t(), __a) {
static_assert(!is_reference<_Hp>::value, "Attempted to default construct a reference element in a tuple");
}
template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) : __value_(__a) {
+ _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) : __value_(in_place, __a) {
static_assert(!is_reference<_Hp>::value, "Attempted to default construct a reference element in a tuple");
}
@@ -340,7 +344,7 @@ public:
__enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Tp>, __tuple_leaf>, is_constructible<_Hp, _Tp> >::value, int> = 0>
_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)) {
+ : __value_(in_place, std::forward<_Tp>(__t)) {
static_assert(__can_bind_reference<_Tp&&>(),
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
}
@@ -348,7 +352,7 @@ public:
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)) {
+ : __value_(in_place, std::forward<_Tp>(__t)) {
static_assert(__can_bind_reference<_Tp&&>(),
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
}
@@ -356,14 +360,14 @@ public:
template <class _Tp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
- : __value_(allocator_arg_t(), __a, std::forward<_Tp>(__t)) {
+ : __value_(in_place, allocator_arg_t(), __a, std::forward<_Tp>(__t)) {
static_assert(!is_reference<_Hp>::value, "Attempted to uses-allocator construct a reference element in a tuple");
}
template <class _Tp, class _Alloc>
_LIBCPP_HIDE_FROM_ABI
_LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
- : __value_(std::forward<_Tp>(__t), __a) {
+ : __value_(in_place, std::forward<_Tp>(__t), __a) {
static_assert(!is_reference<_Hp>::value, "Attempted to uses-allocator construct a reference element in a tuple");
}
@@ -382,65 +386,8 @@ public:
return 0;
}
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Hp& get() _NOEXCEPT { return __value_; }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Hp& get() const _NOEXCEPT { return __value_; }
-};
-
-template <size_t _Ip, class _Hp>
-class __tuple_leaf<_Ip, _Hp, true> : private _Hp {
-public:
- _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_leaf& operator=(const __tuple_leaf&) = delete;
-
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf() noexcept(is_nothrow_default_constructible<_Hp>::value) {}
-
- template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 0>, const _Alloc&) {}
-
- template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
- : _Hp(allocator_arg_t(), __a) {}
-
- template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) : _Hp(__a) {}
-
- template <class _Tp,
- __enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Tp>, __tuple_leaf>, is_constructible<_Hp, _Tp> >::value,
- int> = 0>
- _LIBCPP_HIDE_FROM_ABI
- _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(_Tp&& __t) noexcept(is_nothrow_constructible<_Hp, _Tp>::value)
- : _Hp(std::forward<_Tp>(__t)) {}
-
- template <class _Tp, class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
- : _Hp(std::forward<_Tp>(__t)) {}
-
- template <class _Tp, class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
- : _Hp(allocator_arg_t(), __a, std::forward<_Tp>(__t)) {}
-
- template <class _Tp, class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
- : _Hp(std::forward<_Tp>(__t), __a) {}
-
- __tuple_leaf(__tuple_leaf const&) = default;
- __tuple_leaf(__tuple_leaf&&) = default;
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int
- swap(__tuple_leaf& __t) noexcept(__is_nothrow_swappable_v<__tuple_leaf>) {
- std::swap(*this, __t);
- return 0;
- }
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int swap(const __tuple_leaf& __rhs) const
- noexcept(__is_nothrow_swappable_v<const __tuple_leaf>) {
- std::swap(*this, __rhs);
- return 0;
- }
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Hp& get() _NOEXCEPT { return static_cast<_Hp&>(*this); }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Hp& get() const _NOEXCEPT {
- return static_cast<const _Hp&>(*this);
- }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Hp& get() _NOEXCEPT { return __value_.__v; }
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Hp& get() const _NOEXCEPT { return __value_.__v; }
};
template <class... _Tp>
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 4a6e3095c10198..205d88858be142 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
@@ -40,12 +40,11 @@ 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 at tuple:* 8 {{Attempted construction of reference element binds to a temporary whose lifetime has ended}}
// Good news everybody! Clang now diagnoses this for us!
- // expected-error at tuple:* 0+ {{reference member '__value_' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
+ // expected-error at tuple:* 0+ {{reference member '__v' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}}
{
F<int, const std::string&>(std::make_tuple(1, "abc")); // expected-note 1 {{requested here}}
@@ -73,8 +72,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 at -1 {{force failure}}
-#endif
}
More information about the libcxx-commits
mailing list