[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:12:44 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/11] [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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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/11] 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

>From 7c1b301ce71a4135465d7756512c5c75ababa324 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sat, 16 Aug 2025 18:12:29 +0800
Subject: [PATCH 11/11] Format

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 .../tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp   | 3 +--
 1 file changed, 1 insertion(+), 2 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 7cf7d5c42ed9d..2dfbae9138864 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,9 +19,8 @@
 #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. 
+  // The static_assert inner std::make_from_tuple will not triggered.
 #if __has_builtin(__reference_constructs_from_temporary)
   // expected-error@*:* {{static assertion failed}}
 #endif



More information about the libcxx-commits mailing list