[libcxx-commits] [libcxx] [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. (PR #152867)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Aug 10 08:48:24 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 1/4] [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 2/4] 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 3/4] 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 4/4] 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>{});
}
More information about the libcxx-commits
mailing list