[libcxx-commits] [libcxx] [libc++][tuple.apply] Implement P2255R2 make_from_tuple part. (PR #152867)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Aug 16 03:08:39 PDT 2025
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/152867
>From 7d345a59e0a3b3b0be34634d2431cc6f4835dbd7 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sun, 10 Aug 2025 00:47:22 +0800
Subject: [PATCH 01/10] [libc++] Implement std::make_from_tuple mandates: If
tuple_size_v<remove_reference_t<Tuple>> is 1, then
reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))>
is false.
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
libcxx/include/tuple | 14 ++++++++---
.../tuple.apply/make_from_tuple.verify.cpp | 23 +++++++++++++++++++
2 files changed, 34 insertions(+), 3 deletions(-)
create mode 100644 libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index be30ab5b2173d..9988470102266 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1432,6 +1432,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t,
enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr)
_LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))
#endif // _LIBCPP_STD_VER >= 20
+#undef _LIBCPP_NOEXCEPT_RETURN
template <class _Tp, class _Tuple,
class _Seq = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>, class = void>
@@ -1451,10 +1452,17 @@ template <class _Tp, class _Tuple>
#else
template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp, _Tuple>>> // strengthen
#endif // _LIBCPP_STD_VER >= 20
+
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
- _LIBCPP_NOEXCEPT_RETURN(std::__make_from_tuple_impl<_Tp>(
- std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))
-# undef _LIBCPP_NOEXCEPT_RETURN
+ noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
+ make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
+ if constexpr (tuple_size_v<remove_reference_t<_Tuple>> == 1) {
+ static_assert(!__reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>,
+ "Attempted construction of reference element binds to a temporary whose lifetime has ended");
+ }
+ return std::__make_from_tuple_impl<_Tp>(
+ std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>());
+}
# endif // _LIBCPP_STD_VER >= 17
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
new file mode 100644
index 0000000000000..0ca16088964f7
--- /dev/null
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// <tuple>
+
+// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
+// Mandates: If tuple_size_v<remove_reference_t<Tuple>> is 1, then reference_constructs_from_temporary_v<T, decltype(get<0>(declval<Tuple>()))> is false.
+
+#include <tuple>
+#include <utility>
+
+void test() {
+ // expected-error@*:* {{static assertion failed}}
+ // expected-error@*:* {{returning reference to local temporary object}}
+ std::ignore = std::make_from_tuple<const int&>(std::tuple<char>{});
+}
>From 6312ab09cb5d5a04583b6ff4a04d2f070f20f1e7 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sun, 10 Aug 2025 10:48:45 +0800
Subject: [PATCH 02/10] Address review comments
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
.../tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
index 0ca16088964f7..28e3435278659 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
// <tuple>
>From 01fe5463fc9144876d66b5c56f51e715dea8c8b6 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sun, 10 Aug 2025 11:51:23 +0800
Subject: [PATCH 03/10] Fix test
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
.../tuple.tuple/tuple.apply/make_from_tuple.verify.cpp | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
index 28e3435278659..5f967edfbe775 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -18,6 +18,12 @@
void test() {
// expected-error@*:* {{static assertion failed}}
+
+ // Turns to an error since C++26 (Disallow Binding a Returned Glvalue to a Temporary https://wg21.link/P2748R5).
+#if _LIBCPP_STD_VER >= 26
// expected-error@*:* {{returning reference to local temporary object}}
+#else
+ // expected-warning@*:* {{returning reference to local temporary object}}
+#endif
std::ignore = std::make_from_tuple<const int&>(std::tuple<char>{});
}
>From 21b69d4334c4d0f468961ef6618ad7ba38d86653 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sun, 10 Aug 2025 23:47:55 +0800
Subject: [PATCH 04/10] XFAIL test in clang-module-build, because the
diagnostic in tuple std header cannot emitted
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
.../tuple.apply/make_from_tuple.verify.cpp | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
index 5f967edfbe775..a7399f4de2c89 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -8,6 +8,9 @@
// REQUIRES: std-at-least-c++17
+// No diagnostic gets emitted when we build with modules.
+// XFAIL: clang-modules-build
+
// <tuple>
// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
@@ -16,14 +19,16 @@
#include <tuple>
#include <utility>
+#include "test_macros.h"
+
void test() {
// expected-error@*:* {{static assertion failed}}
// Turns to an error since C++26 (Disallow Binding a Returned Glvalue to a Temporary https://wg21.link/P2748R5).
-#if _LIBCPP_STD_VER >= 26
- // expected-error@*:* {{returning reference to local temporary object}}
+#if TEST_STD_VER >= 26
+ // expected-error at tuple:* {{returning reference to local temporary object}}
#else
- // expected-warning@*:* {{returning reference to local temporary object}}
+ // expected-warning at tuple:* {{returning reference to local temporary object}}
#endif
std::ignore = std::make_from_tuple<const int&>(std::tuple<char>{});
}
>From 59baea19152240367828e4e7152a6ecd64f3f832 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Mon, 11 Aug 2025 00:09:39 +0800
Subject: [PATCH 05/10] Only disable c++17 clang-modules-build
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
.../tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
index a7399f4de2c89..0f53ae6c46b1e 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -9,7 +9,7 @@
// REQUIRES: std-at-least-c++17
// No diagnostic gets emitted when we build with modules.
-// XFAIL: clang-modules-build
+// XFAIL: (c++17 && clang-modules-build)
// <tuple>
>From 4e735668081fd54530ccaa67b5de85840befe137 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Tue, 12 Aug 2025 11:14:07 +0800
Subject: [PATCH 06/10] Guard with _LIBCPP_STD_VER >= 23 and update test
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
libcxx/include/tuple | 2 ++
.../tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 9988470102266..c095843d3a69f 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1456,10 +1456,12 @@ template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
+#if _LIBCPP_STD_VER >= 23
if constexpr (tuple_size_v<remove_reference_t<_Tuple>> == 1) {
static_assert(!__reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>,
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
}
+#endif // _LIBCPP_STD_VER >= 23
return std::__make_from_tuple_impl<_Tp>(
std::forward<_Tuple>(__t), make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>());
}
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
index 0f53ae6c46b1e..dd61e8ab6f1de 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-// REQUIRES: std-at-least-c++17
+// REQUIRES: std-at-least-c++23
// No diagnostic gets emitted when we build with modules.
-// XFAIL: (c++17 && clang-modules-build)
+// XFAIL: clang-modules-build
// <tuple>
>From 3caf149015a35064776a146128e325a01cb77b63 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Tue, 12 Aug 2025 12:37:55 +0800
Subject: [PATCH 07/10] Remove xfail
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
.../tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
index dd61e8ab6f1de..12d778408d5ec 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -8,9 +8,6 @@
// REQUIRES: std-at-least-c++23
-// No diagnostic gets emitted when we build with modules.
-// XFAIL: clang-modules-build
-
// <tuple>
// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&);
>From 65472f9e188ed7b67227ecfe2094a6d8d4afcd83 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Wed, 13 Aug 2025 15:09:44 +0800
Subject: [PATCH 08/10] Check compiler implemented
__reference_constructs_from_temporary
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
libcxx/include/tuple | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index c095843d3a69f..2618e2d7334d0 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1456,7 +1456,7 @@ template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
-#if _LIBCPP_STD_VER >= 23
+#if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
if constexpr (tuple_size_v<remove_reference_t<_Tuple>> == 1) {
static_assert(!__reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>,
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
>From d58024352d8b9ac75c1e081ff93368f76df49faf Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 15 Aug 2025 10:50:24 +0800
Subject: [PATCH 09/10] Use std::reference_constructs_from_temporary_v
---
libcxx/include/tuple | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index 2618e2d7334d0..b046e2aed43e2 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -1458,7 +1458,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
#if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary)
if constexpr (tuple_size_v<remove_reference_t<_Tuple>> == 1) {
- static_assert(!__reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>,
+ static_assert(!std::reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>,
"Attempted construction of reference element binds to a temporary whose lifetime has ended");
}
#endif // _LIBCPP_STD_VER >= 23
>From b5424dfe5d0f9342ad7468354d43fc7389ccbaf6 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sat, 16 Aug 2025 18:08:16 +0800
Subject: [PATCH 10/10] Disable static_assert diagnostic message verify if no
builtin __reference_constructs_from_temporary
Signed-off-by: yronglin <yronglin777 at gmail.com>
---
.../tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
index 12d778408d5ec..7cf7d5c42ed9d 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp
@@ -19,7 +19,12 @@
#include "test_macros.h"
void test() {
+
+ // FreeBSD ci use clang 19.1.1, which hasn't implement __reference_constructs_from_temporary.
+ // The static_assert inner std::make_from_tuple will not tiggered.
+#if __has_builtin(__reference_constructs_from_temporary)
// expected-error@*:* {{static assertion failed}}
+#endif
// Turns to an error since C++26 (Disallow Binding a Returned Glvalue to a Temporary https://wg21.link/P2748R5).
#if TEST_STD_VER >= 26
More information about the libcxx-commits
mailing list