[libcxx-commits] [libcxx] [libc++][type_traits] Implements "A type trait to detect reference binding to temporary" (PR #128649)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Feb 28 12:01:01 PST 2025
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/128649
>From ab218834c60aa52950974223d3b5387d288ce99e Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 24 Feb 2025 16:54:16 +0200
Subject: [PATCH 01/17] [libc++][type_traits] Implements "A type trait to
detect reference binding to temporary"
Implements partially: P2255R2: A type trait to detect reference binding to temporary
https://github.com/llvm/llvm-project/issues/105180
https://eel.is/c++draft/meta.type.synop
https://eel.is/c++draft/meta.unary.prop
Implented type traits:
- [x] `reference_constructs_from_temporary`
- [x] `reference_converts_from_temporary`
---
libcxx/docs/Status/Cxx23Papers.csv | 2 +-
libcxx/include/CMakeLists.txt | 2 +
.../reference_constructs_from_temporary.h | 42 ++++++
.../reference_converts_from_temporary.h | 42 ++++++
libcxx/include/module.modulemap | 8 ++
libcxx/include/type_traits | 14 ++
libcxx/modules/std/type_traits.inc | 16 ++-
...ference_constructs_from_temporary.pass.cpp | 121 +++++++++++++++++
...reference_converts_from_temporary.pass.cpp | 124 ++++++++++++++++++
9 files changed, 366 insertions(+), 5 deletions(-)
create mode 100644 libcxx/include/__type_traits/reference_constructs_from_temporary.h
create mode 100644 libcxx/include/__type_traits/reference_converts_from_temporary.h
create mode 100644 libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
create mode 100644 libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index bfaa63a7c224e..0f3db57788b49 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -43,7 +43,7 @@
"`P0627R6 <https://wg21.link/P0627R6>`__","Function to mark unreachable code","2022-02 (Virtual)","|Complete|","15",""
"`P1206R7 <https://wg21.link/P1206R7>`__","``ranges::to``: A function to convert any range to a container","2022-02 (Virtual)","|Complete|","17",""
"`P1413R3 <https://wg21.link/P1413R3>`__","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","2022-02 (Virtual)","|Complete|","","``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but clang doesn't issue a diagnostic for deprecated using template declarations."
-"`P2255R2 <https://wg21.link/P2255R2>`__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","","",""
+"`P2255R2 <https://wg21.link/P2255R2>`__","A type trait to detect reference binding to temporary","2022-02 (Virtual)","|Partial|","","Implemented the type traits only."
"`P2273R3 <https://wg21.link/P2273R3>`__","Making ``std::unique_ptr`` constexpr","2022-02 (Virtual)","|Complete|","16",""
"`P2387R3 <https://wg21.link/P2387R3>`__","Pipe support for user-defined range adaptors","2022-02 (Virtual)","|Complete|","19",""
"`P2440R1 <https://wg21.link/P2440R1>`__","``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right``","2022-02 (Virtual)","","",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index ee1d7b872b364..d7c36d6b438fb 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -867,6 +867,8 @@ set(files
__type_traits/negation.h
__type_traits/promote.h
__type_traits/rank.h
+ __type_traits/reference_constructs_from_temporary.h
+ __type_traits/reference_converts_from_temporary.h
__type_traits/remove_all_extents.h
__type_traits/remove_const.h
__type_traits/remove_const_ref.h
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
new file mode 100644
index 0000000000000..c7475c45bbe64
--- /dev/null
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARARY_H
+#define _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARARY_H
+
+#include <__config>
+#include <__type_traits/integral_constant.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_CXX03_LANG)
+
+template <class _Tp, class _Up>
+inline constexpr bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up);
+
+# if _LIBCPP_STD_VER >= 23
+
+template <class _Tp, class _Up>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS reference_constructs_from_temporary
+ : public bool_constant<__reference_constructs_from_temporary(_Tp, _Up)> {};
+
+template <class _Tp, class _Up>
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_temporary_v =
+ __reference_constructs_from_temporary_v<_Tp, _Up>;
+
+# endif
+
+#endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARARY_H
diff --git a/libcxx/include/__type_traits/reference_converts_from_temporary.h b/libcxx/include/__type_traits/reference_converts_from_temporary.h
new file mode 100644
index 0000000000000..f194d97dcd633
--- /dev/null
+++ b/libcxx/include/__type_traits/reference_converts_from_temporary.h
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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___TYPE_TRAITS_REFERENCE_CONVERTS_FROM_TEMPORARARY_H
+#define _LIBCPP___TYPE_TRAITS_REFERENCE_CONVERTS_FROM_TEMPORARARY_H
+
+#include <__config>
+#include <__type_traits/integral_constant.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_CXX03_LANG) && __has_builtin(__reference_converts_from_temporary)
+
+template <class _Tp, class _Up>
+inline constexpr bool __reference_converts_from_temporary_v = __reference_converts_from_temporary(_Tp, _Up);
+
+# if _LIBCPP_STD_VER >= 23
+
+template <class _Tp, class _Up>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS reference_converts_from_temporary
+ : public bool_constant<__reference_converts_from_temporary(_Tp, _Up)> {};
+
+template <class _Tp, class _Up>
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_converts_from_temporary_v =
+ __reference_converts_from_temporary_v<_Tp, _Up>;
+
+# endif
+
+#endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONVERTS_FROM_TEMPORARARY_H
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 0f2016e7f5d15..ed757aa734c8c 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -369,6 +369,14 @@ module std_core [system] {
module negation { header "__type_traits/negation.h" }
module promote { header "__type_traits/promote.h" }
module rank { header "__type_traits/rank.h" }
+ module reference_constructs_from_temporary {
+ header "__type_traits/reference_constructs_from_temporary.h"
+ export std_core.type_traits.integral_constant
+ }
+ module reference_converts_from_temporary {
+ header "__type_traits/reference_converts_from_temporary.h"
+ export std_core.type_traits.integral_constant
+ }
module remove_all_extents { header "__type_traits/remove_all_extents.h" }
module remove_const_ref { header "__type_traits/remove_const_ref.h" }
module remove_const { header "__type_traits/remove_const.h" }
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index ffcddb0176615..2c1b163cc66a0 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -143,6 +143,9 @@ namespace std
template<class T> struct has_unique_object_representations; // C++17
+ template<class T, class U> struct reference_constructs_from_temporary; // Since C++23
+ template<class T, class U> struct reference_converts_from_temporary; // Since C++23
+
// Relationships between types:
template <class T, class U> struct is_same;
template <class Base, class Derived> struct is_base_of;
@@ -382,6 +385,12 @@ namespace std
= has_virtual_destructor<T>::value; // C++17
template<class T> inline constexpr bool has_unique_object_representations_v // C++17
= has_unique_object_representations<T>::value;
+ template<class T, class U>
+ constexpr bool reference_constructs_from_temporary_v
+ = reference_constructs_from_temporary<T, U>::value; // Since C++23
+ template<class T, class U>
+ constexpr bool reference_converts_from_temporary_v
+ = reference_converts_from_temporary<T, U>::value; // Since C++23
// See C++14 20.10.5, type property queries
template <class T> inline constexpr size_t alignment_of_v
@@ -524,6 +533,11 @@ namespace std
# if _LIBCPP_STD_VER >= 23
# include <__type_traits/is_implicit_lifetime.h>
# endif
+// C++23 but private declarations are available in C++11.
+# if !defined(_LIBCPP_CXX03_LANG)
+# include <__type_traits/reference_constructs_from_temporary.h>
+# include <__type_traits/reference_converts_from_temporary.h>
+# endif
# include <version>
diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc
index f544f95c7aaaa..79c64f1cd9d96 100644
--- a/libcxx/modules/std/type_traits.inc
+++ b/libcxx/modules/std/type_traits.inc
@@ -106,8 +106,12 @@ export namespace std {
using std::has_unique_object_representations;
- // using std::reference_constructs_from_temporary;
- // using std::reference_converts_from_temporary;
+#if _LIBCPP_STD_VER >= 23
+ using std::reference_constructs_from_temporary;
+# if __has_builtin(__reference_converts_from_temporary)
+ using std::reference_converts_from_temporary;
+# endif
+#endif
// [meta.unary.prop.query], type property queries
using std::alignment_of;
@@ -284,8 +288,12 @@ export namespace std {
using std::is_unbounded_array_v;
using std::is_unsigned_v;
using std::is_volatile_v;
- // using std::reference_constructs_from_temporary_v;
- // using std::reference_converts_from_temporary_v;
+#if _LIBCPP_STD_VER >= 23
+ using std::reference_constructs_from_temporary_v;
+# if __has_builtin(__reference_converts_from_temporary)
+ using std::reference_converts_from_temporary_v;
+# endif
+#endif
// [meta.unary.prop.query], type property queries
using std::alignment_of_v;
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
new file mode 100644
index 0000000000000..d1ef96c2347e3
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
@@ -0,0 +1,121 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// <type_traits>
+
+// template<class T, class U> struct reference_constructs_from_temporary;
+
+// template<class T, class U>
+// constexpr bool reference_constructs_from_temporary_v
+// = reference_constructs_from_temporary<T, U>::value;
+
+#include <cassert>
+#include <type_traits>
+
+struct NonPOD {
+ NonPOD(int);
+};
+enum Enum { EV };
+struct POD {
+ Enum e;
+ int i;
+ float f;
+ NonPOD* p;
+};
+// Not PODs
+struct Derives : POD {};
+
+template <class T, class RefType = T&>
+struct ConvertsToRef {
+ operator RefType() const { return static_cast<RefType>(obj); }
+ mutable T obj = 42;
+};
+template <class T, class RefType = T&>
+class ConvertsToRefPrivate {
+ operator RefType() const { return static_cast<RefType>(obj); }
+ mutable T obj = 42;
+};
+
+struct ExplicitConversionRvalueRef {
+ operator int();
+ explicit operator int&&();
+};
+
+struct ExplicitConversionRef {
+ operator int();
+ explicit operator int&();
+};
+
+template <typename T, typename U, bool Expected>
+constexpr void test_reference_constructs_from_temporary() {
+ assert((std::reference_constructs_from_temporary<T, U>::value == Expected));
+ assert((std::reference_constructs_from_temporary_v<T, U> == Expected));
+}
+
+constexpr bool test() {
+ test_reference_constructs_from_temporary<int&, int&, false>();
+ test_reference_constructs_from_temporary<int&, int&, false>();
+ test_reference_constructs_from_temporary<int&, int&&, false>();
+
+ test_reference_constructs_from_temporary<const int&, int&, false>();
+ test_reference_constructs_from_temporary<const int&, const int&, false>();
+ test_reference_constructs_from_temporary<const int&, int&&, false>();
+
+ test_reference_constructs_from_temporary<int&, long&, false>(); // doesn't construct
+
+ test_reference_constructs_from_temporary<const int&, long&, true>();
+ test_reference_constructs_from_temporary<const int&, long&&, true>();
+ test_reference_constructs_from_temporary<int&&, long&, true>();
+
+ using LRef = ConvertsToRef<int, int&>;
+ using RRef = ConvertsToRef<int, int&&>;
+ using CLRef = ConvertsToRef<int, const int&>;
+ using LongRef = ConvertsToRef<long, long&>;
+
+ assert((std::is_constructible_v<int&, LRef>));
+ test_reference_constructs_from_temporary<int&, LRef, false>();
+
+ assert((std::is_constructible_v<int&&, RRef>));
+ test_reference_constructs_from_temporary<int&&, RRef, false>();
+
+ assert((std::is_constructible_v<const int&, CLRef>));
+ test_reference_constructs_from_temporary<int&&, CLRef, false>();
+
+ assert((std::is_constructible_v<const int&, LongRef>));
+ test_reference_constructs_from_temporary<const int&, LongRef, true>();
+ test_reference_constructs_from_temporary<const int&, ConvertsToRefPrivate<long, long&>, false>();
+
+ // Test that it doesn't accept non-reference types as input.
+ test_reference_constructs_from_temporary<int, long, false>();
+
+ test_reference_constructs_from_temporary<const int&, long, true>();
+
+ // Additional checks
+ test_reference_constructs_from_temporary<POD const&, Derives, true>();
+ test_reference_constructs_from_temporary<int&&, int, true>();
+ test_reference_constructs_from_temporary<const int&, int, true>();
+ test_reference_constructs_from_temporary<int&&, int&&, false>();
+ test_reference_constructs_from_temporary<const int&, int&&, false>();
+ test_reference_constructs_from_temporary<int&&, long&&, true>();
+ test_reference_constructs_from_temporary<int&&, long, true>();
+
+ test_reference_constructs_from_temporary<int&, ExplicitConversionRef, false>();
+ test_reference_constructs_from_temporary<const int&, ExplicitConversionRef, false>();
+ test_reference_constructs_from_temporary<int&&, ExplicitConversionRvalueRef, false>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
new file mode 100644
index 0000000000000..931e7eccbd87f
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
@@ -0,0 +1,124 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// These compilers don't support std::reference_converts_from_temporary yet.
+// UNSUPPORTED: android, apple-clang-15, apple-clang-16.1, apple-clang-16.2, clang-19
+
+// <type_traits>
+
+// template<class T, class U> struct reference_converts_from_temporary;
+
+// template<class T, class U>
+// constexpr bool reference_converts_from_temporary_v
+// = reference_converts_from_temporary<T, U>::value;
+
+#include <cassert>
+#include <type_traits>
+
+struct NonPOD {
+ NonPOD(int);
+};
+enum Enum { EV };
+struct POD {
+ Enum e;
+ int i;
+ float f;
+ NonPOD* p;
+};
+// Not PODs
+struct Derives : POD {};
+
+template <class T, class RefType = T&>
+struct ConvertsToRef {
+ operator RefType() const { return static_cast<RefType>(obj); }
+ mutable T obj = 42;
+};
+template <class T, class RefType = T&>
+class ConvertsToRefPrivate {
+ operator RefType() const { return static_cast<RefType>(obj); }
+ mutable T obj = 42;
+};
+
+struct ExplicitConversionRvalueRef {
+ operator int();
+ explicit operator int&&();
+};
+
+struct ExplicitConversionRef {
+ operator int();
+ explicit operator int&();
+};
+
+template <typename T, typename U, bool Expected>
+constexpr void test_reference_converts_from_temporary() {
+ assert((std::reference_converts_from_temporary<T, U>::value == Expected));
+ assert((std::reference_converts_from_temporary_v<T, U> == Expected));
+}
+
+constexpr bool test() {
+ test_reference_converts_from_temporary<int&, int&, false>();
+ test_reference_converts_from_temporary<int&, int&, false>();
+ test_reference_converts_from_temporary<int&, int&&, false>();
+
+ test_reference_converts_from_temporary<const int&, int&, false>();
+ test_reference_converts_from_temporary<const int&, const int&, false>();
+ test_reference_converts_from_temporary<const int&, int&&, false>();
+
+ test_reference_converts_from_temporary<int&, long&, false>(); // doesn't construct
+
+ test_reference_converts_from_temporary<const int&, long&, true>();
+ test_reference_converts_from_temporary<const int&, long&&, true>();
+ test_reference_converts_from_temporary<int&&, long&, true>();
+
+ using LRef = ConvertsToRef<int, int&>;
+ using RRef = ConvertsToRef<int, int&&>;
+ using CLRef = ConvertsToRef<int, const int&>;
+ using LongRef = ConvertsToRef<long, long&>;
+
+ assert((std::is_constructible_v<int&, LRef>));
+ test_reference_converts_from_temporary<int&, LRef, false>();
+
+ assert((std::is_constructible_v<int&&, RRef>));
+ test_reference_converts_from_temporary<int&&, RRef, false>();
+
+ assert((std::is_constructible_v<const int&, CLRef>));
+ test_reference_converts_from_temporary<int&&, CLRef, false>();
+
+ assert((std::is_constructible_v<const int&, LongRef>));
+ test_reference_converts_from_temporary<const int&, LongRef, true>();
+ test_reference_converts_from_temporary<const int&, ConvertsToRefPrivate<long, long&>, false>();
+
+ // Test that it doesn't accept non-reference types as input.
+ test_reference_converts_from_temporary<int, long, false>();
+
+ test_reference_converts_from_temporary<const int&, long, true>();
+
+ // Additional checks
+ test_reference_converts_from_temporary<POD const&, Derives, true>();
+ test_reference_converts_from_temporary<int&&, int, true>();
+ test_reference_converts_from_temporary<const int&, int, true>();
+ test_reference_converts_from_temporary<int&&, int&&, false>();
+ test_reference_converts_from_temporary<const int&, int&&, false>();
+ test_reference_converts_from_temporary<int&&, long&&, true>();
+ test_reference_converts_from_temporary<int&&, long, true>();
+
+ test_reference_converts_from_temporary<int&, ExplicitConversionRef, false>();
+ test_reference_converts_from_temporary<const int&, ExplicitConversionRef, true>();
+ test_reference_converts_from_temporary<int&&, ExplicitConversionRvalueRef, true>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
>From 016d341ad9d42dfcdcc8628b7ff0c7ca63409711 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 26 Feb 2025 11:49:21 +0200
Subject: [PATCH 02/17] Address comments
---
.../__type_traits/reference_constructs_from_temporary.h | 6 +-----
.../__type_traits/reference_converts_from_temporary.h | 4 +++-
libcxx/include/type_traits | 8 +++-----
.../reference_constructs_from_temporary.pass.cpp | 4 ++++
.../reference_converts_from_temporary.pass.cpp | 6 +++++-
5 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
index c7475c45bbe64..8314cfaf7f208 100644
--- a/libcxx/include/__type_traits/reference_constructs_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -18,10 +18,8 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if !defined(_LIBCPP_CXX03_LANG)
-
template <class _Tp, class _Up>
-inline constexpr bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up);
+const bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up);
# if _LIBCPP_STD_VER >= 23
@@ -35,8 +33,6 @@ _LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_tempo
# endif
-#endif
-
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___TYPE_TRAITS_REFERENCE_CONSTRUCTS_FROM_TEMPORARARY_H
diff --git a/libcxx/include/__type_traits/reference_converts_from_temporary.h b/libcxx/include/__type_traits/reference_converts_from_temporary.h
index f194d97dcd633..fb26a89ffd109 100644
--- a/libcxx/include/__type_traits/reference_converts_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_converts_from_temporary.h
@@ -18,7 +18,9 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if !defined(_LIBCPP_CXX03_LANG) && __has_builtin(__reference_converts_from_temporary)
+#if __has_builtin(__reference_converts_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
+ (__clang_patchlevel__ >= 2))
template <class _Tp, class _Up>
inline constexpr bool __reference_converts_from_temporary_v = __reference_converts_from_temporary(_Tp, _Up);
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 2c1b163cc66a0..25020213bacfb 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -533,11 +533,9 @@ namespace std
# if _LIBCPP_STD_VER >= 23
# include <__type_traits/is_implicit_lifetime.h>
# endif
-// C++23 but private declarations are available in C++11.
-# if !defined(_LIBCPP_CXX03_LANG)
-# include <__type_traits/reference_constructs_from_temporary.h>
-# include <__type_traits/reference_converts_from_temporary.h>
-# endif
+// C++23 but private declarations are available in previous standards.
+# include <__type_traits/reference_constructs_from_temporary.h>
+# include <__type_traits/reference_converts_from_temporary.h>
# include <version>
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
index d1ef96c2347e3..84cd8528596d1 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
@@ -19,6 +19,8 @@
#include <cassert>
#include <type_traits>
+#include "test_macros.h"
+
struct NonPOD {
NonPOD(int);
};
@@ -90,7 +92,9 @@ constexpr bool test() {
assert((std::is_constructible_v<const int&, LongRef>));
test_reference_constructs_from_temporary<const int&, LongRef, true>();
+#ifndef TEST_COMPILER_GCC
test_reference_constructs_from_temporary<const int&, ConvertsToRefPrivate<long, long&>, false>();
+#endif
// Test that it doesn't accept non-reference types as input.
test_reference_constructs_from_temporary<int, long, false>();
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
index 931e7eccbd87f..f128861861c54 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
@@ -9,7 +9,7 @@
// REQUIRES: std-at-least-c++23
// These compilers don't support std::reference_converts_from_temporary yet.
-// UNSUPPORTED: android, apple-clang-15, apple-clang-16.1, apple-clang-16.2, clang-19
+// UNSUPPORTED: android, apple-clang, clang-19.1.1
// <type_traits>
@@ -22,6 +22,8 @@
#include <cassert>
#include <type_traits>
+#include "test_macros.h"
+
struct NonPOD {
NonPOD(int);
};
@@ -93,7 +95,9 @@ constexpr bool test() {
assert((std::is_constructible_v<const int&, LongRef>));
test_reference_converts_from_temporary<const int&, LongRef, true>();
+#ifndef TEST_COMPILER_GCC
test_reference_converts_from_temporary<const int&, ConvertsToRefPrivate<long, long&>, false>();
+#endif
// Test that it doesn't accept non-reference types as input.
test_reference_converts_from_temporary<int, long, false>();
>From 5ad9e7003959002804eea2b89c72483255ad4f09 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 26 Feb 2025 11:59:15 +0200
Subject: [PATCH 03/17] Try to fix CI
---
.../__type_traits/reference_constructs_from_temporary.h | 4 ++--
.../include/__type_traits/reference_converts_from_temporary.h | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
index 8314cfaf7f208..aa88ff82096df 100644
--- a/libcxx/include/__type_traits/reference_constructs_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -21,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, class _Up>
const bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up);
-# if _LIBCPP_STD_VER >= 23
+#if _LIBCPP_STD_VER >= 23
template <class _Tp, class _Up>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS reference_constructs_from_temporary
@@ -31,7 +31,7 @@ template <class _Tp, class _Up>
_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_temporary_v =
__reference_constructs_from_temporary_v<_Tp, _Up>;
-# endif
+#endif
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/reference_converts_from_temporary.h b/libcxx/include/__type_traits/reference_converts_from_temporary.h
index fb26a89ffd109..f98769c12a7a7 100644
--- a/libcxx/include/__type_traits/reference_converts_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_converts_from_temporary.h
@@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
(__clang_patchlevel__ >= 2))
template <class _Tp, class _Up>
-inline constexpr bool __reference_converts_from_temporary_v = __reference_converts_from_temporary(_Tp, _Up);
+const bool __reference_converts_from_temporary_v = __reference_converts_from_temporary(_Tp, _Up);
# if _LIBCPP_STD_VER >= 23
>From 93742ac68b80a10a601035c1b65e9fa128ed1f84 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 26 Feb 2025 12:10:25 +0200
Subject: [PATCH 04/17] Fixed modules map condition
---
libcxx/modules/std/type_traits.inc | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc
index 79c64f1cd9d96..bc8be8e993ca2 100644
--- a/libcxx/modules/std/type_traits.inc
+++ b/libcxx/modules/std/type_traits.inc
@@ -108,7 +108,9 @@ export namespace std {
#if _LIBCPP_STD_VER >= 23
using std::reference_constructs_from_temporary;
-# if __has_builtin(__reference_converts_from_temporary)
+# if __has_builtin(__reference_converts_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
+ (__clang_patchlevel__ >= 2))
using std::reference_converts_from_temporary;
# endif
#endif
@@ -290,7 +292,9 @@ export namespace std {
using std::is_volatile_v;
#if _LIBCPP_STD_VER >= 23
using std::reference_constructs_from_temporary_v;
-# if __has_builtin(__reference_converts_from_temporary)
+# if __has_builtin(__reference_converts_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
+ (__clang_patchlevel__ >= 2))
using std::reference_converts_from_temporary_v;
# endif
#endif
>From 49910a03c4c3ea17ada0615c3d796480fbfcf9e7 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 26 Feb 2025 12:45:56 +0200
Subject: [PATCH 05/17] Fixed formatting
---
libcxx/modules/std/type_traits.inc | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc
index bc8be8e993ca2..3b772d3364d09 100644
--- a/libcxx/modules/std/type_traits.inc
+++ b/libcxx/modules/std/type_traits.inc
@@ -108,9 +108,9 @@ export namespace std {
#if _LIBCPP_STD_VER >= 23
using std::reference_constructs_from_temporary;
-# if __has_builtin(__reference_converts_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
- (__clang_patchlevel__ >= 2))
+# if __has_builtin(__reference_converts_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
+ (__clang_patchlevel__ >= 2))
using std::reference_converts_from_temporary;
# endif
#endif
@@ -292,9 +292,9 @@ export namespace std {
using std::is_volatile_v;
#if _LIBCPP_STD_VER >= 23
using std::reference_constructs_from_temporary_v;
-# if __has_builtin(__reference_converts_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
- (__clang_patchlevel__ >= 2))
+# if __has_builtin(__reference_converts_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
+ (__clang_patchlevel__ >= 2))
using std::reference_converts_from_temporary_v;
# endif
#endif
>From 8be80790c7716bae8190a36362d95d2f7ca61dea Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 26 Feb 2025 16:13:41 +0200
Subject: [PATCH 06/17] Try to fix CI
---
.../meta.unary.prop/reference_converts_from_temporary.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
index f128861861c54..a14173d8b04ae 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
@@ -9,7 +9,7 @@
// REQUIRES: std-at-least-c++23
// These compilers don't support std::reference_converts_from_temporary yet.
-// UNSUPPORTED: android, apple-clang, clang-19.1.1
+// UNSUPPORTED: android, apple-clang, clang-18, clang-19.1.0, clang-19.1.1
// <type_traits>
>From 17197b3b532a2f58317c3e414c26b55aa0e1c923 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Feb 2025 07:09:56 +0200
Subject: [PATCH 07/17] Try to fix Apple CI
---
.../__type_traits/reference_constructs_from_temporary.h | 8 +++++++-
libcxx/modules/std/type_traits.inc | 8 ++++++++
.../reference_constructs_from_temporary.pass.cpp | 3 +++
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
index aa88ff82096df..78242fe6d3aa8 100644
--- a/libcxx/include/__type_traits/reference_constructs_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -18,10 +18,14 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+#if __has_builtin(__reference_converts_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
+ (__clang_patchlevel__ >= 2))
+
template <class _Tp, class _Up>
const bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up);
-#if _LIBCPP_STD_VER >= 23
+# if _LIBCPP_STD_VER >= 23
template <class _Tp, class _Up>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS reference_constructs_from_temporary
@@ -31,6 +35,8 @@ template <class _Tp, class _Up>
_LIBCPP_NO_SPECIALIZATIONS inline constexpr bool reference_constructs_from_temporary_v =
__reference_constructs_from_temporary_v<_Tp, _Up>;
+# endif
+
#endif
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc
index 3b772d3364d09..268c172807e82 100644
--- a/libcxx/modules/std/type_traits.inc
+++ b/libcxx/modules/std/type_traits.inc
@@ -107,7 +107,11 @@ export namespace std {
using std::has_unique_object_representations;
#if _LIBCPP_STD_VER >= 23
+# if __has_builtin(__reference_constructs_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
+ (__clang_patchlevel__ >= 2))
using std::reference_constructs_from_temporary;
+# endif
# if __has_builtin(__reference_converts_from_temporary) || \
(defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
(__clang_patchlevel__ >= 2))
@@ -291,7 +295,11 @@ export namespace std {
using std::is_unsigned_v;
using std::is_volatile_v;
#if _LIBCPP_STD_VER >= 23
+# if __has_builtin(__reference_constructs_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
+ (__clang_patchlevel__ >= 2))
using std::reference_constructs_from_temporary_v;
+# endif
# if __has_builtin(__reference_converts_from_temporary) || \
(defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
(__clang_patchlevel__ >= 2))
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
index 84cd8528596d1..4cddc572604bb 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
@@ -8,6 +8,9 @@
// REQUIRES: std-at-least-c++23
+// These compilers don't support std::reference_converts_from_temporary yet.
+// UNSUPPORTED: apple-clang, clang-19.1.0, clang-19.1.1
+
// <type_traits>
// template<class T, class U> struct reference_constructs_from_temporary;
>From b92ffcb62592e6623b9717cb18c043d8c858009b Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Feb 2025 09:11:34 +0200
Subject: [PATCH 08/17] Try to fix CI
---
.../include/__type_traits/reference_constructs_from_temporary.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
index 78242fe6d3aa8..097d491840402 100644
--- a/libcxx/include/__type_traits/reference_constructs_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if __has_builtin(__reference_converts_from_temporary) || \
+#if __has_builtin(__reference_constructs_from_temporary) || \
(defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
(__clang_patchlevel__ >= 2))
>From cba8f242cdc7d55b0a79fad3f5e25e003393b308 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Feb 2025 09:12:18 +0200
Subject: [PATCH 09/17] Fixed formatting
---
.../include/__type_traits/reference_constructs_from_temporary.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
index 097d491840402..f3e73a4312aed 100644
--- a/libcxx/include/__type_traits/reference_constructs_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if __has_builtin(__reference_constructs_from_temporary) || \
+#if __has_builtin(__reference_constructs_from_temporary) || \
(defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
(__clang_patchlevel__ >= 2))
>From a5d6c8945aeba3b45487ad6137bcb526804b5737 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Feb 2025 10:10:19 +0200
Subject: [PATCH 10/17] Try to fix Android
---
.../reference_constructs_from_temporary.pass.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
index 4cddc572604bb..2a16568dde468 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
@@ -9,7 +9,7 @@
// REQUIRES: std-at-least-c++23
// These compilers don't support std::reference_converts_from_temporary yet.
-// UNSUPPORTED: apple-clang, clang-19.1.0, clang-19.1.1
+// UNSUPPORTED: android && clang-19.0, apple-clang, clang-19.1.0, clang-19.1.1
// <type_traits>
>From b3f16ddc783be4527138682fa82376ad0b0c9644 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 28 Feb 2025 08:43:11 +0200
Subject: [PATCH 11/17] Addressed review comments
---
libcxx/include/__config | 16 ++++++++++++++++
.../reference_constructs_from_temporary.h | 4 +---
.../reference_converts_from_temporary.h | 4 +---
libcxx/modules/std/type_traits.inc | 16 ++++------------
.../is_implicit_lifetime.pass.cpp | 2 +-
.../is_implicit_lifetime.verify.cpp | 2 +-
.../reference_constructs_from_temporary.pass.cpp | 2 +-
.../reference_converts_from_temporary.pass.cpp | 2 +-
8 files changed, 26 insertions(+), 22 deletions(-)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index c8224b07a6b81..a0cb23ea63b2d 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1215,6 +1215,22 @@ typedef __char32_t char32_t;
# define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 0
# endif
+// TODO(LLVM 22): Remove this macro once LLVM19 support ends.
+# if __has_builtin(__reference_constructs_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1))
+# define _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY 1
+# else
+# define _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY 0
+# endif
+
+// TODO(LLVM 22): Remove this macro once LLVM19 support ends.
+# if __has_builtin(__reference_converts_from_temporary) || \
+ (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1))
+# define _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY 1
+# else
+# define _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY 0
+# endif
+
#endif // __cplusplus
#endif // _LIBCPP___CONFIG
diff --git a/libcxx/include/__type_traits/reference_constructs_from_temporary.h b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
index f3e73a4312aed..4114580e19bb2 100644
--- a/libcxx/include/__type_traits/reference_constructs_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_constructs_from_temporary.h
@@ -18,9 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if __has_builtin(__reference_constructs_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
- (__clang_patchlevel__ >= 2))
+#if _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY
template <class _Tp, class _Up>
const bool __reference_constructs_from_temporary_v = __reference_constructs_from_temporary(_Tp, _Up);
diff --git a/libcxx/include/__type_traits/reference_converts_from_temporary.h b/libcxx/include/__type_traits/reference_converts_from_temporary.h
index f98769c12a7a7..e046124562ece 100644
--- a/libcxx/include/__type_traits/reference_converts_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_converts_from_temporary.h
@@ -18,9 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if __has_builtin(__reference_converts_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
- (__clang_patchlevel__ >= 2))
+#if _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY
template <class _Tp, class _Up>
const bool __reference_converts_from_temporary_v = __reference_converts_from_temporary(_Tp, _Up);
diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc
index 268c172807e82..d8dab686d02c6 100644
--- a/libcxx/modules/std/type_traits.inc
+++ b/libcxx/modules/std/type_traits.inc
@@ -107,14 +107,10 @@ export namespace std {
using std::has_unique_object_representations;
#if _LIBCPP_STD_VER >= 23
-# if __has_builtin(__reference_constructs_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
- (__clang_patchlevel__ >= 2))
+# if _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY
using std::reference_constructs_from_temporary;
# endif
-# if __has_builtin(__reference_converts_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
- (__clang_patchlevel__ >= 2))
+# if _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY
using std::reference_converts_from_temporary;
# endif
#endif
@@ -295,14 +291,10 @@ export namespace std {
using std::is_unsigned_v;
using std::is_volatile_v;
#if _LIBCPP_STD_VER >= 23
-# if __has_builtin(__reference_constructs_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
- (__clang_patchlevel__ >= 2))
+# if _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY
using std::reference_constructs_from_temporary_v;
# endif
-# if __has_builtin(__reference_converts_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1) && \
- (__clang_patchlevel__ >= 2))
+# if _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY
using std::reference_converts_from_temporary_v;
# endif
#endif
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
index 681ad13a07dfd..24adec37431e7 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
@@ -9,7 +9,7 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
// These compilers don't support __builtin_is_implicit_lifetime yet.
-// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16, apple-clang-17
+// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16
// <type_traits>
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
index 34462f9bf0ec6..4bcb10d0b7579 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
@@ -9,7 +9,7 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
// These compilers don't support __builtin_is_implicit_lifetime yet.
-// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16, apple-clang-17
+// UNSUPPORTED: clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16
// <type_traits>
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
index 2a16568dde468..ea79bb7d4e007 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
@@ -9,7 +9,7 @@
// REQUIRES: std-at-least-c++23
// These compilers don't support std::reference_converts_from_temporary yet.
-// UNSUPPORTED: android && clang-19.0, apple-clang, clang-19.1.0, clang-19.1.1
+// UNSUPPORTED: android && clang-19.0, apple-clang-15, apple-clang-16
// <type_traits>
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
index a14173d8b04ae..04ca1e7788a73 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
@@ -9,7 +9,7 @@
// REQUIRES: std-at-least-c++23
// These compilers don't support std::reference_converts_from_temporary yet.
-// UNSUPPORTED: android, apple-clang, clang-18, clang-19.1.0, clang-19.1.1
+// UNSUPPORTED: android, apple-clang-15, apple-clang-16, clang-18
// <type_traits>
>From 4edecb2f3975502ed68320c644aeb9e91ef967ea Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 28 Feb 2025 09:45:57 +0200
Subject: [PATCH 12/17] Try to fix CI
---
.../include/__type_traits/reference_converts_from_temporary.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__type_traits/reference_converts_from_temporary.h b/libcxx/include/__type_traits/reference_converts_from_temporary.h
index e046124562ece..812eaf60c9c9d 100644
--- a/libcxx/include/__type_traits/reference_converts_from_temporary.h
+++ b/libcxx/include/__type_traits/reference_converts_from_temporary.h
@@ -18,7 +18,7 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#if _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY
+#if _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY
template <class _Tp, class _Up>
const bool __reference_converts_from_temporary_v = __reference_converts_from_temporary(_Tp, _Up);
>From a8de754d749332556b932591b6b2b7c80ae8b502 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 28 Feb 2025 11:58:24 +0200
Subject: [PATCH 13/17] Minor tweaks
---
libcxx/include/__config | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index a0cb23ea63b2d..2412f00572db0 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1217,7 +1217,7 @@ typedef __char32_t char32_t;
// TODO(LLVM 22): Remove this macro once LLVM19 support ends.
# if __has_builtin(__reference_constructs_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1))
+ (defined(_LIBCPP_CLANG_VER) && (_LIBCPP_CLANG_VER == 1901))
# define _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY 1
# else
# define _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY 0
@@ -1225,7 +1225,7 @@ typedef __char32_t char32_t;
// TODO(LLVM 22): Remove this macro once LLVM19 support ends.
# if __has_builtin(__reference_converts_from_temporary) || \
- (defined(_LIBCPP_COMPILER_CLANG_BASED) && (__clang_major__ >= 19) && (__clang_minor__ >= 1))
+ (defined(_LIBCPP_CLANG_VER) && (_LIBCPP_CLANG_VER == 1901))
# define _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY 1
# else
# define _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY 0
>From d0e0416d90364df31b8fea8c6e25cbe385c624f8 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 28 Feb 2025 12:08:30 +0200
Subject: [PATCH 14/17] Fixed formatting
---
libcxx/include/__config | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 2412f00572db0..7bddd2b2b03d0 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1224,8 +1224,7 @@ typedef __char32_t char32_t;
# endif
// TODO(LLVM 22): Remove this macro once LLVM19 support ends.
-# if __has_builtin(__reference_converts_from_temporary) || \
- (defined(_LIBCPP_CLANG_VER) && (_LIBCPP_CLANG_VER == 1901))
+# if __has_builtin(__reference_converts_from_temporary) || (defined(_LIBCPP_CLANG_VER) && (_LIBCPP_CLANG_VER == 1901))
# define _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY 1
# else
# define _LIBCPP_HAS_REFERENCE_CONVERTS_FROM_TEMPORARY 0
>From 0f34c041decb58109a2e7ae5208e139b0c71423e Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 28 Feb 2025 17:12:03 +0200
Subject: [PATCH 15/17] Enable ANDROID
---
libcxx/include/__config | 2 +-
.../reference_constructs_from_temporary.pass.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 7bddd2b2b03d0..fc4547406b9f0 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1217,7 +1217,7 @@ typedef __char32_t char32_t;
// TODO(LLVM 22): Remove this macro once LLVM19 support ends.
# if __has_builtin(__reference_constructs_from_temporary) || \
- (defined(_LIBCPP_CLANG_VER) && (_LIBCPP_CLANG_VER == 1901))
+ (defined(_LIBCPP_CLANG_VER) && (_LIBCPP_CLANG_VER >= 1900))
# define _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY 1
# else
# define _LIBCPP_HAS_REFERENCE_CONSTRUCTS_FROM_TEMPORARY 0
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
index ea79bb7d4e007..3a7cabbcf5fd8 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
@@ -9,7 +9,7 @@
// REQUIRES: std-at-least-c++23
// These compilers don't support std::reference_converts_from_temporary yet.
-// UNSUPPORTED: android && clang-19.0, apple-clang-15, apple-clang-16
+// UNSUPPORTED: apple-clang-15, apple-clang-16
// <type_traits>
>From 2c717ea2e13eba57cef9fb92a0b6f72eb3208ae7 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 28 Feb 2025 19:27:37 +0200
Subject: [PATCH 16/17] Updated tests
---
.../meta/meta.unary/meta.unary.prop/common.h | 39 +++++++++++++
...ference_constructs_from_temporary.pass.cpp | 58 ++++---------------
...reference_converts_from_temporary.pass.cpp | 58 ++++---------------
3 files changed, 59 insertions(+), 96 deletions(-)
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
index be9149de89a6c..04815b8853eb3 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
@@ -44,4 +44,43 @@ class Abstract
virtual ~Abstract() = 0;
};
+// Types for reference_{constructs/converts}_from_temporary
+
+struct NonPOD {
+ NonPOD(int);
+};
+enum Enum { EV };
+struct POD {
+ Enum e;
+ int i;
+ float f;
+ NonPOD* p;
+};
+// Not PODs
+struct Derives : POD {};
+
+template <class T, class RefType = T&>
+class ConvertsToRef {
+public:
+ operator RefType() const { return static_cast<RefType>(obj); }
+ mutable T obj = 42;
+};
+template <class T, class RefType = T&>
+class ConvertsToRefPrivate {
+ operator RefType() const { return static_cast<RefType>(obj); }
+ mutable T obj = 42;
+};
+
+class ExplicitConversionRvalueRef {
+public:
+ operator int();
+ explicit operator int&&();
+};
+
+class ExplicitConversionRef {
+public:
+ operator int();
+ explicit operator int&();
+};
+
#endif // TEST_META_UNARY_COMP_COMMON_H
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
index 3a7cabbcf5fd8..612e4fadd4b0b 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_constructs_from_temporary.pass.cpp
@@ -22,42 +22,9 @@
#include <cassert>
#include <type_traits>
+#include "common.h"
#include "test_macros.h"
-struct NonPOD {
- NonPOD(int);
-};
-enum Enum { EV };
-struct POD {
- Enum e;
- int i;
- float f;
- NonPOD* p;
-};
-// Not PODs
-struct Derives : POD {};
-
-template <class T, class RefType = T&>
-struct ConvertsToRef {
- operator RefType() const { return static_cast<RefType>(obj); }
- mutable T obj = 42;
-};
-template <class T, class RefType = T&>
-class ConvertsToRefPrivate {
- operator RefType() const { return static_cast<RefType>(obj); }
- mutable T obj = 42;
-};
-
-struct ExplicitConversionRvalueRef {
- operator int();
- explicit operator int&&();
-};
-
-struct ExplicitConversionRef {
- operator int();
- explicit operator int&();
-};
-
template <typename T, typename U, bool Expected>
constexpr void test_reference_constructs_from_temporary() {
assert((std::reference_constructs_from_temporary<T, U>::value == Expected));
@@ -79,22 +46,17 @@ constexpr bool test() {
test_reference_constructs_from_temporary<const int&, long&&, true>();
test_reference_constructs_from_temporary<int&&, long&, true>();
- using LRef = ConvertsToRef<int, int&>;
- using RRef = ConvertsToRef<int, int&&>;
- using CLRef = ConvertsToRef<int, const int&>;
- using LongRef = ConvertsToRef<long, long&>;
-
- assert((std::is_constructible_v<int&, LRef>));
- test_reference_constructs_from_temporary<int&, LRef, false>();
+ assert((std::is_constructible_v<int&, ConvertsToRef<int, int&>>));
+ test_reference_constructs_from_temporary<int&, ConvertsToRef<int, int&>, false>();
- assert((std::is_constructible_v<int&&, RRef>));
- test_reference_constructs_from_temporary<int&&, RRef, false>();
+ assert((std::is_constructible_v<int&&, ConvertsToRef<int, int&&>>));
+ test_reference_constructs_from_temporary<int&&, ConvertsToRef<int, int&&>, false>();
- assert((std::is_constructible_v<const int&, CLRef>));
- test_reference_constructs_from_temporary<int&&, CLRef, false>();
+ assert((std::is_constructible_v<const int&, ConvertsToRef<int, const int&>>));
+ test_reference_constructs_from_temporary<int&&, ConvertsToRef<int, const int&>, false>();
- assert((std::is_constructible_v<const int&, LongRef>));
- test_reference_constructs_from_temporary<const int&, LongRef, true>();
+ assert((std::is_constructible_v<const int&, ConvertsToRef<long, long&>>));
+ test_reference_constructs_from_temporary<const int&, ConvertsToRef<long, long&>, true>();
#ifndef TEST_COMPILER_GCC
test_reference_constructs_from_temporary<const int&, ConvertsToRefPrivate<long, long&>, false>();
#endif
@@ -105,7 +67,7 @@ constexpr bool test() {
test_reference_constructs_from_temporary<const int&, long, true>();
// Additional checks
- test_reference_constructs_from_temporary<POD const&, Derives, true>();
+ test_reference_constructs_from_temporary<const POD&, Derives, true>();
test_reference_constructs_from_temporary<int&&, int, true>();
test_reference_constructs_from_temporary<const int&, int, true>();
test_reference_constructs_from_temporary<int&&, int&&, false>();
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
index 04ca1e7788a73..27baf4c97785a 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/reference_converts_from_temporary.pass.cpp
@@ -22,42 +22,9 @@
#include <cassert>
#include <type_traits>
+#include "common.h"
#include "test_macros.h"
-struct NonPOD {
- NonPOD(int);
-};
-enum Enum { EV };
-struct POD {
- Enum e;
- int i;
- float f;
- NonPOD* p;
-};
-// Not PODs
-struct Derives : POD {};
-
-template <class T, class RefType = T&>
-struct ConvertsToRef {
- operator RefType() const { return static_cast<RefType>(obj); }
- mutable T obj = 42;
-};
-template <class T, class RefType = T&>
-class ConvertsToRefPrivate {
- operator RefType() const { return static_cast<RefType>(obj); }
- mutable T obj = 42;
-};
-
-struct ExplicitConversionRvalueRef {
- operator int();
- explicit operator int&&();
-};
-
-struct ExplicitConversionRef {
- operator int();
- explicit operator int&();
-};
-
template <typename T, typename U, bool Expected>
constexpr void test_reference_converts_from_temporary() {
assert((std::reference_converts_from_temporary<T, U>::value == Expected));
@@ -79,22 +46,17 @@ constexpr bool test() {
test_reference_converts_from_temporary<const int&, long&&, true>();
test_reference_converts_from_temporary<int&&, long&, true>();
- using LRef = ConvertsToRef<int, int&>;
- using RRef = ConvertsToRef<int, int&&>;
- using CLRef = ConvertsToRef<int, const int&>;
- using LongRef = ConvertsToRef<long, long&>;
-
- assert((std::is_constructible_v<int&, LRef>));
- test_reference_converts_from_temporary<int&, LRef, false>();
+ assert((std::is_constructible_v<int&, ConvertsToRef<int, int&>>));
+ test_reference_converts_from_temporary<int&, ConvertsToRef<int, int&>, false>();
- assert((std::is_constructible_v<int&&, RRef>));
- test_reference_converts_from_temporary<int&&, RRef, false>();
+ assert((std::is_constructible_v<int&&, ConvertsToRef<int, int&&>>));
+ test_reference_converts_from_temporary<int&&, ConvertsToRef<int, int&&>, false>();
- assert((std::is_constructible_v<const int&, CLRef>));
- test_reference_converts_from_temporary<int&&, CLRef, false>();
+ assert((std::is_constructible_v<const int&, ConvertsToRef<int, const int&>>));
+ test_reference_converts_from_temporary<int&&, ConvertsToRef<int, const int&>, false>();
- assert((std::is_constructible_v<const int&, LongRef>));
- test_reference_converts_from_temporary<const int&, LongRef, true>();
+ assert((std::is_constructible_v<const int&, ConvertsToRef<long, long&>>));
+ test_reference_converts_from_temporary<const int&, ConvertsToRef<long, long&>, true>();
#ifndef TEST_COMPILER_GCC
test_reference_converts_from_temporary<const int&, ConvertsToRefPrivate<long, long&>, false>();
#endif
@@ -105,7 +67,7 @@ constexpr bool test() {
test_reference_converts_from_temporary<const int&, long, true>();
// Additional checks
- test_reference_converts_from_temporary<POD const&, Derives, true>();
+ test_reference_converts_from_temporary<const POD&, Derives, true>();
test_reference_converts_from_temporary<int&&, int, true>();
test_reference_converts_from_temporary<const int&, int, true>();
test_reference_converts_from_temporary<int&&, int&&, false>();
>From 65993fe912c82b99eb8952eff11f66eeebbe26c5 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 28 Feb 2025 21:59:24 +0200
Subject: [PATCH 17/17] Fix C++03
---
.../utilities/meta/meta.unary/meta.unary.prop/common.h | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
index 04815b8853eb3..c780d457d6d88 100644
--- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/common.h
@@ -39,13 +39,14 @@ struct A {
A& operator=(const A&);
};
-class Abstract
-{
- virtual ~Abstract() = 0;
+class Abstract {
+ virtual ~Abstract() = 0;
};
// Types for reference_{constructs/converts}_from_temporary
+#if TEST_STD_VER >= 23
+
struct NonPOD {
NonPOD(int);
};
@@ -83,4 +84,6 @@ class ExplicitConversionRef {
explicit operator int&();
};
+#endif
+
#endif // TEST_META_UNARY_COMP_COMMON_H
More information about the libcxx-commits
mailing list