[libcxx-commits] [libcxx] [libc++][type_traits] P2674R1: A trait for implicit lifetime types (PR #106870)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Oct 8 09:56:15 PDT 2024
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/106870
>From 31240ba0d8aff815dfb4cf90eab290805b921cbc Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 24 Aug 2024 23:52:42 +0300
Subject: [PATCH 01/13] [libc++][type_traits] P2647R1: A trait for implicit
lifetime types
Implements P2674R1: https://wg21.link/P2674R1
- https://eel.is/c++draft/type.traits
- https://eel.is/c++draft/meta.type.synop
- https://eel.is/c++draft/meta.unary.prop
- https://eel.is/c++draft/support.limits
- https://eel.is/c++draft/version.syn
Implementation details:
- Uses compiler intrinsic `__builtin_is_implicit_lifetime`:
- https://github.com/llvm/llvm-project/pull/101807
- Tests based on:
- https://github.com/llvm/llvm-project/blob/d213981c80626698a07b11ce872acba098a863d4/clang/test/SemaCXX/type-traits.cpp#L1989
References:
- Implicit-lifetime
- Implicit-lifetime types [basic.types.general]/9: https://eel.is/c++draft/basic.types.general
- Implicit-lifetime class [class.prop]/9: https://eel.is/c++draft/class.prop
- P0593R6 Implicit creation of objects for low-level object manipulation: https://wg21.link/P0593R6
- P1010R1 Container support for implicit lifetime types: https://wg21.link/P1010R1
- P0593R6 Implicit creation of objects for low-level object manipulation: https://wg21.link/P0593R6
Closes: #105259
---
libcxx/include/CMakeLists.txt | 1 +
.../__type_traits/is_implicit_lifetime.h | 50 +++
libcxx/include/type_traits | 8 +
.../is_implicit_lifetime.pass.cpp | 361 ++++++++++++++++++
.../is_implicit_lifetime.verify.cpp | 37 ++
5 files changed, 457 insertions(+)
create mode 100644 libcxx/include/__type_traits/is_implicit_lifetime.h
create mode 100644 libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
create mode 100644 libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 32579272858a8e..6c755e90214b44 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -778,6 +778,7 @@ set(files
__type_traits/is_floating_point.h
__type_traits/is_function.h
__type_traits/is_fundamental.h
+ __type_traits/is_implicit_lifetime.h
__type_traits/is_implicitly_default_constructible.h
__type_traits/is_integral.h
__type_traits/is_literal_type.h
diff --git a/libcxx/include/__type_traits/is_implicit_lifetime.h b/libcxx/include/__type_traits/is_implicit_lifetime.h
new file mode 100644
index 00000000000000..4cd593ebdbda60
--- /dev/null
+++ b/libcxx/include/__type_traits/is_implicit_lifetime.h
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_IS_IMPLICIT_LIFETIME_H
+#define _LIBCPP___TYPE_TRAITS_IS_IMPLICIT_LIFETIME_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 _LIBCPP_STD_VER >= 23
+# if __has_builtin(__builtin_is_implicit_lifetime)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_implicit_lifetime : public bool_constant<__builtin_is_implicit_lifetime(_Tp)> {};
+
+template <class _Tp>
+inline constexpr bool is_implicit_lifetime_v = __builtin_is_implicit_lifetime(_Tp);
+
+# else
+
+template <typename _Tp>
+struct is_implicit_lifetime
+ : std::disjunction< std::is_scalar<_Tp>,
+ std::is_array<_Tp>,
+ std::is_aggregate<_Tp>,
+ std::conjunction< std::is_trivially_destructible<_Tp>,
+ std::disjunction< std::is_trivially_default_constructible<_Tp>,
+ std::is_trivially_copy_constructible<_Tp>,
+ std::is_trivially_move_constructible<_Tp>>>> {};
+
+template <class _Tp>
+inline constexpr bool is_implicit_lifetime_v = is_implicit_lifetime<_Tp>::value;
+
+# endif
+#endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___TYPE_TRAITS_IS_IMPLICIT_LIFETIME_H
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 5937d4fdc9e1a7..d29721a371c39a 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -137,6 +137,8 @@ namespace std
template <class T> struct is_nothrow_swappable; // C++17
template <class T> struct is_nothrow_destructible;
+ template<class T> struct is_implicit_lifetime; // Since C++23
+
template <class T> struct has_virtual_destructor;
template<class T> struct has_unique_object_representations; // C++17
@@ -374,6 +376,8 @@ namespace std
= is_nothrow_swappable<T>::value; // C++17
template <class T> inline constexpr bool is_nothrow_destructible_v
= is_nothrow_destructible<T>::value; // C++17
+ template<class T>
+ constexpr bool is_implicit_lifetime_v = is_implicit_lifetime<T>::value; // Since C++23
template <class T> inline constexpr bool has_virtual_destructor_v
= has_virtual_destructor<T>::value; // C++17
template<class T> inline constexpr bool has_unique_object_representations_v // C++17
@@ -517,6 +521,10 @@ namespace std
# include <__type_traits/unwrap_ref.h>
#endif
+#if _LIBCPP_STD_VER >= 23
+# include <__type_traits/is_implicit_lifetime.h>
+#endif
+
#include <version>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
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
new file mode 100644
index 00000000000000..7a6af8ba28d80d
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp
@@ -0,0 +1,361 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17, c++20
+
+// <type_traits>
+
+// template<class T> struct is_implicit_lifetime;
+
+#include <cassert>
+#include <cstddef>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "test_macros.h"
+
+enum Enum { EV };
+enum SignedEnum : signed int {};
+enum UnsignedEnum : unsigned int {};
+
+enum class EnumClass { EV };
+enum class SignedEnumClass : signed int {};
+enum class UnsignedEnumClass : unsigned int {};
+
+struct EmptyStruct {};
+struct IncompleteStruct;
+
+struct NoEligibleTrivialContructor {
+ NoEligibleTrivialContructor() {};
+ NoEligibleTrivialContructor(const NoEligibleTrivialContructor&) {}
+ NoEligibleTrivialContructor(NoEligibleTrivialContructor&&) {}
+};
+
+struct OnlyDefaultConstructorIsTrivial {
+ OnlyDefaultConstructorIsTrivial() = default;
+ OnlyDefaultConstructorIsTrivial(const OnlyDefaultConstructorIsTrivial&) {}
+ OnlyDefaultConstructorIsTrivial(OnlyDefaultConstructorIsTrivial&&) {}
+};
+
+struct AllContstructorsAreTrivial {
+ AllContstructorsAreTrivial() = default;
+ AllContstructorsAreTrivial(const AllContstructorsAreTrivial&) = default;
+ AllContstructorsAreTrivial(AllContstructorsAreTrivial&&) = default;
+};
+
+struct InheritedNoEligibleTrivialConstructor : NoEligibleTrivialContructor {
+ using NoEligibleTrivialContructor::NoEligibleTrivialContructor;
+};
+
+struct InheritedOnlyDefaultConstructorIsTrivial : OnlyDefaultConstructorIsTrivial {
+ using OnlyDefaultConstructorIsTrivial::OnlyDefaultConstructorIsTrivial;
+};
+
+struct InheritedAllContstructorsAreTrivial : AllContstructorsAreTrivial {
+ using AllContstructorsAreTrivial::AllContstructorsAreTrivial;
+};
+
+struct UserDeclaredDestructor {
+ ~UserDeclaredDestructor() = default;
+};
+
+struct UserProvidedDestructor {
+ ~UserProvidedDestructor() {}
+};
+
+struct UserDeletedDestructorInAggregate {
+ ~UserDeletedDestructorInAggregate() = delete;
+};
+
+struct UserDeletedDestructorInNonAggregate {
+ virtual void NonAggregate();
+ ~UserDeletedDestructorInNonAggregate() = delete;
+};
+
+struct DeletedDestructorViaBaseInAggregate : UserDeletedDestructorInAggregate {};
+struct DeletedDestructorViaBaseInNonAggregate : UserDeletedDestructorInNonAggregate {};
+
+template <bool B>
+struct ConstrainedUserDeclaredDefaultConstructor {
+ ConstrainedUserDeclaredDefaultConstructor()
+ requires B
+ = default;
+ ConstrainedUserDeclaredDefaultConstructor(const ConstrainedUserDeclaredDefaultConstructor&) {}
+};
+
+template <bool B>
+struct ConstrainedUserProvidedDestructor {
+ ~ConstrainedUserProvidedDestructor() = default;
+ ~ConstrainedUserProvidedDestructor()
+ requires B
+ {}
+};
+
+struct StructWithFlexibleArrayMember {
+ int arr[];
+};
+
+struct StructWithZeroSizedArray {
+ int arr[0];
+};
+
+#ifdef TEST_COMPILER_CLANG
+// typedef int *align_value_int __attribute__((align_value(16)));
+using AlignValueInt = int* __attribute__((align_value(16)));
+// typedef float float4 __attribute__((ext_vector_type(4)));
+using Float4 = float __attribute__((ext_vector_type(4)));
+
+struct [[clang::enforce_read_only_placement]] EnforceReadOnlyPlacement {};
+struct [[clang::type_visibility("hidden")]] TypeVisibility {};
+#endif
+
+// Test implicit-lifetime type
+template <typename T, bool Expected>
+constexpr void test_is_implicit_lifetime() {
+ static_assert(std::is_implicit_lifetime<T>::value == Expected);
+
+ // Runtime check
+ assert(std::is_implicit_lifetime_v<T> == Expected);
+}
+
+// Test pointer, reference, array, etc. types
+template <typename T>
+constexpr void test_is_implicit_lifetime() {
+ test_is_implicit_lifetime<T, true>();
+
+ // cv-qualified
+ test_is_implicit_lifetime<const T, true>();
+ test_is_implicit_lifetime<volatile T, true>();
+
+ test_is_implicit_lifetime<T&, false>();
+ test_is_implicit_lifetime<T&&, false>();
+
+ // Pointer types
+ test_is_implicit_lifetime<T*, true>();
+ test_is_implicit_lifetime<T* __restrict, true>();
+
+ // Arrays
+ test_is_implicit_lifetime<T[], true>();
+ test_is_implicit_lifetime<T[0], true>();
+ test_is_implicit_lifetime<T[94], true>();
+}
+
+// #ifdef TEST_COMPILER_CLANG
+// // Test language extensions: attributes
+// template <typename T>
+// constexpr void test_is_implicit_lifetime_with_attributes() {
+// test_is_implicit_lifetime<T [[clang::annotate_type("category2")]]*, true>();
+// test_is_implicit_lifetime<T __attribute__((btf_type_tag("user")))*, true>();
+// static_assert(__builtin_is_implicit_lifetime(int __attribute__((btf_type_tag("user"))) *));
+
+// test_is_implicit_lifetime<T __attribute__((noderef))*, true>();
+
+// test_is_implicit_lifetime<T* _Nonnull, true>();
+// test_is_implicit_lifetime<T* _Null_unspecified, true>();
+// test_is_implicit_lifetime<T* _Nullable, true>();
+// }
+// #endif // TEST_COMPILER_CLANG
+
+constexpr bool test() {
+ // Standard fundamental C++ types
+
+ test_is_implicit_lifetime<decltype(nullptr), true>();
+ test_is_implicit_lifetime<std::nullptr_t, true>();
+
+ test_is_implicit_lifetime<void, false>();
+ test_is_implicit_lifetime<const void, false>();
+ test_is_implicit_lifetime<volatile void, false>();
+
+ test_is_implicit_lifetime<bool>();
+
+ test_is_implicit_lifetime<char>();
+ test_is_implicit_lifetime<signed char>();
+ test_is_implicit_lifetime<unsigned char>();
+
+#if !defined(TEST_HAS_NO_WIDE_CHARACTERS)
+ test_is_implicit_lifetime<wchar_t>();
+#endif
+
+#if !defined(TEST_HAS_NO_CHAR8_T)
+ test_is_implicit_lifetime<char8_t>();
+#endif
+ test_is_implicit_lifetime<char16_t>();
+ test_is_implicit_lifetime<char32_t>();
+
+ // test_is_implicit_lifetime<int, true>();
+ // test_is_implicit_lifetime<int&, false>();
+ // test_is_implicit_lifetime<int&&, false>();
+
+ // test_is_implicit_lifetime<int*, true>();
+ // test_is_implicit_lifetime<int[], true>();
+ // test_is_implicit_lifetime<int[0], true>();
+ // test_is_implicit_lifetime<int[94], true>();
+ test_is_implicit_lifetime<short>();
+ test_is_implicit_lifetime<short int>();
+ test_is_implicit_lifetime<signed short>();
+ test_is_implicit_lifetime<signed short int>();
+ test_is_implicit_lifetime<unsigned short>();
+ test_is_implicit_lifetime<unsigned short int>();
+ test_is_implicit_lifetime<int>();
+ test_is_implicit_lifetime<signed>();
+ test_is_implicit_lifetime<signed int>();
+ test_is_implicit_lifetime<unsigned>();
+ test_is_implicit_lifetime<unsigned int>();
+ test_is_implicit_lifetime<long>();
+ test_is_implicit_lifetime<long int>();
+ test_is_implicit_lifetime<signed long>();
+ test_is_implicit_lifetime<signed long int>();
+ test_is_implicit_lifetime<unsigned long>();
+ test_is_implicit_lifetime<unsigned long int>();
+ test_is_implicit_lifetime<long long>();
+ test_is_implicit_lifetime<long long int>();
+ test_is_implicit_lifetime<signed long long>();
+ test_is_implicit_lifetime<signed long long int>();
+ test_is_implicit_lifetime<unsigned long long>();
+ test_is_implicit_lifetime<unsigned long long int>();
+
+ test_is_implicit_lifetime<float>();
+ test_is_implicit_lifetime<double>();
+ test_is_implicit_lifetime<long double>();
+
+ test_is_implicit_lifetime<Enum>();
+ test_is_implicit_lifetime<SignedEnum>();
+ test_is_implicit_lifetime<UnsignedEnum>();
+
+ test_is_implicit_lifetime<EnumClass>();
+ test_is_implicit_lifetime<SignedEnumClass>();
+ test_is_implicit_lifetime<UnsignedEnumClass>();
+
+ test_is_implicit_lifetime<void(), false>();
+ test_is_implicit_lifetime<void()&, false>();
+ test_is_implicit_lifetime<void() const, false>();
+ test_is_implicit_lifetime<void (&)(), false>();
+ test_is_implicit_lifetime<void (*)(), true>();
+
+ // test_is_implicit_lifetime<int UserDeclaredDestructor::*, true>();
+ // test_is_implicit_lifetime<int (UserDeclaredDestructor::*)(), true>();
+ // test_is_implicit_lifetime<int (UserDeclaredDestructor::*)() const, true>();
+ // test_is_implicit_lifetime<int (UserDeclaredDestructor::*)()&, true>();
+ // test_is_implicit_lifetime<int (UserDeclaredDestructor::*)()&&, true>();
+
+ // Implicit-lifetime class types
+
+ test_is_implicit_lifetime<EmptyStruct>();
+ test_is_implicit_lifetime<int EmptyStruct::*, true>(); // Pointer-to-member
+ test_is_implicit_lifetime<int (EmptyStruct::*)(), true>();
+ test_is_implicit_lifetime<int (EmptyStruct::*)() const, true>();
+ test_is_implicit_lifetime<int (EmptyStruct::*)()&, true>();
+ test_is_implicit_lifetime<int (EmptyStruct::*)()&&, true>();
+
+ test_is_implicit_lifetime<IncompleteStruct[], true>();
+ test_is_implicit_lifetime<IncompleteStruct[82], true>();
+
+ test_is_implicit_lifetime<UserDeclaredDestructor>();
+
+ test_is_implicit_lifetime<UserProvidedDestructor, false>();
+
+ test_is_implicit_lifetime<NoEligibleTrivialContructor, false>();
+
+ test_is_implicit_lifetime<OnlyDefaultConstructorIsTrivial, true>();
+
+ test_is_implicit_lifetime<AllContstructorsAreTrivial, true>();
+
+ test_is_implicit_lifetime<InheritedNoEligibleTrivialConstructor, false>();
+
+ test_is_implicit_lifetime<InheritedOnlyDefaultConstructorIsTrivial, true>();
+
+ test_is_implicit_lifetime<InheritedAllContstructorsAreTrivial, true>();
+
+ test_is_implicit_lifetime<UserDeletedDestructorInAggregate, true>();
+
+ test_is_implicit_lifetime<UserDeletedDestructorInNonAggregate, false>();
+
+ test_is_implicit_lifetime<DeletedDestructorViaBaseInAggregate, true>();
+
+ test_is_implicit_lifetime<DeletedDestructorViaBaseInNonAggregate, false>();
+
+ test_is_implicit_lifetime<ConstrainedUserDeclaredDefaultConstructor<true>, true>();
+ test_is_implicit_lifetime<ConstrainedUserDeclaredDefaultConstructor<false>, false>();
+
+ test_is_implicit_lifetime<ConstrainedUserProvidedDestructor<true>, false>();
+ test_is_implicit_lifetime<ConstrainedUserProvidedDestructor<false>, true>();
+
+ test_is_implicit_lifetime<StructWithFlexibleArrayMember, true>();
+
+ test_is_implicit_lifetime<StructWithZeroSizedArray, true>();
+
+ // C++ standard library types
+
+ test_is_implicit_lifetime<std::pair<int, float>>();
+ test_is_implicit_lifetime<std::tuple<int, float>>();
+
+ // Standard C types
+
+ test_is_implicit_lifetime<_Complex float>();
+ test_is_implicit_lifetime<_Complex double>();
+ test_is_implicit_lifetime<_Complex long double>();
+
+ // test_is_implicit_lifetime<_Imaginary float>();
+ // test_is_implicit_lifetime<_Imaginary double>();
+ // test_is_implicit_lifetime<_Imaginary long double>();
+
+ // Standard C23 types
+
+#ifdef TEST_COMPILER_CLANG
+ test_is_implicit_lifetime<_BitInt(8)>();
+ test_is_implicit_lifetime<_BitInt(128)>();
+#endif
+
+ // Language extensions: Types
+
+#if !defined(TEST_HAS_NO_INT128)
+ test_is_implicit_lifetime<__int128_t>();
+ test_is_implicit_lifetime<__uint128_t>();
+#endif
+
+ // #if __STDC_VERSION__ >= 20
+ // #endif
+
+#ifdef TEST_COMPILER_CLANG
+ // https://clang.llvm.org/docs/LanguageExtensions.html#half-precision-floating-point
+ test_is_implicit_lifetime<__fp16>();
+ test_is_implicit_lifetime<__bf16>();
+#endif // TEST_COMPILER_CLANG
+
+ // Language extensions: Attributes
+
+#ifdef TEST_COMPILER_CLANG
+ test_is_implicit_lifetime<AlignValueInt, true>();
+ test_is_implicit_lifetime<Float4, true>();
+
+ test_is_implicit_lifetime<EnforceReadOnlyPlacement, true>();
+ test_is_implicit_lifetime<TypeVisibility, true>();
+
+ // test_is_implicit_lifetime_with_attributes<int>();
+ // test_is_implicit_lifetime_with_attributes<float>();
+
+ test_is_implicit_lifetime<int [[clang::annotate_type("category2")]]*, true>();
+ test_is_implicit_lifetime<int __attribute__((btf_type_tag("user")))*, true>();
+
+ test_is_implicit_lifetime<int __attribute__((noderef))*, true>();
+
+ test_is_implicit_lifetime<int* _Nonnull, true>();
+ test_is_implicit_lifetime<int* _Null_unspecified, true>();
+ test_is_implicit_lifetime<int* _Nullable, true>();
+#endif // TEST_COMPILER_CLANG
+
+ 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/is_implicit_lifetime.verify.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
new file mode 100644
index 00000000000000..c557731b91a67f
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_implicit_lifetime.verify.cpp
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17, c++20
+
+// <type_traits>
+
+// template<class T> struct is_implicit_lifetime;
+
+#include <cassert>
+#include <cstddef>
+#include <type_traits>
+
+#include "test_macros.h"
+
+struct IncompleteStruct;
+
+// expected-error@*:* {{incomplete type 'IncompleteStruct' used in type trait expression}}
+static_assert(!std::is_implicit_lifetime<IncompleteStruct>::value);
+
+// expected-error@*:* {{atomic types are not supported in '__builtin_is_implicit_lifetime'}}
+static_assert(!std::is_implicit_lifetime<_Atomic int>::value);
+
+#if 0
+// FIXME: "variable length arrays in C++ are a Clang extension"
+void test(int n) {
+ int varArr[n];
+ using VarArrT = decltype(varArr);
+ // expected-error@*:* {{variable length arrays are not supported in '__builtin_is_implicit_lifetime'}}
+ static_assert(std::is_implicit_lifetime<VarArrT>::value);
+}
+#endif
>From c8ae04b9c1519d2050fd01572dd30846d712e160 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 31 Aug 2024 23:18:20 +0300
Subject: [PATCH 02/13] Cleanup + FTM
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +
libcxx/docs/ReleaseNotes/20.rst | 1 +
libcxx/docs/Status/Cxx23Papers.csv | 2 +-
.../__type_traits/is_implicit_lifetime.h | 15 ------
libcxx/include/module.modulemap | 1 +
libcxx/include/version | 4 ++
libcxx/modules/std/type_traits.inc | 8 +++-
.../type_traits.version.compile.pass.cpp | 43 +++++++++++++++++
.../version.version.compile.pass.cpp | 43 +++++++++++++++++
.../is_implicit_lifetime.pass.cpp | 48 ++-----------------
.../is_implicit_lifetime.verify.cpp | 22 ++++-----
.../generate_feature_test_macro_components.py | 7 +++
12 files changed, 122 insertions(+), 74 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index c909a4300db1a6..05b08da5215350 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -336,6 +336,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_ios_noreplace`` ``202207L``
---------------------------------------------------------- -----------------
+ ``__cpp_lib_is_implicit_lifetime`` ``202302L``
+ ---------------------------------------------------------- -----------------
``__cpp_lib_is_scoped_enum`` ``202011L``
---------------------------------------------------------- -----------------
``__cpp_lib_mdspan`` ``202207L``
diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index 93d6027291ad95..cb95d7059eb837 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -41,6 +41,7 @@ Implemented Papers
- P2747R2: ``constexpr`` placement new (`Github <https://github.com/llvm/llvm-project/issues/105427>`__)
- P2609R3: Relaxing Ranges Just A Smidge (`Github <https://github.com/llvm/llvm-project/issues/105253>`__)
- P2985R0: A type trait for detecting virtual base classes (`Github <https://github.com/llvm/llvm-project/issues/105432>`__)
+- P2674R1: A trait for implicit lifetime types (`Github <https://github.com/llvm/llvm-project/issues/105259>`__)
Improvements and New Features
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 2c8a91d8401b53..2cf63b29ab53ba 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -113,7 +113,7 @@
"`P2572R1 <https://wg21.link/P2572R1>`__","``std::format`` fill character allowances","2023-02 (Issaquah)","|Complete|","17.0",""
"`P2693R1 <https://wg21.link/P2693R1>`__","Formatting ``thread::id`` and ``stacktrace``","2023-02 (Issaquah)","|Partial|","","The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is not implemented yet"
"`P2679R2 <https://wg21.link/P2679R2>`__","Fixing ``std::start_lifetime_as`` for arrays","2023-02 (Issaquah)","","",""
-"`P2674R1 <https://wg21.link/P2674R1>`__","A trait for implicit lifetime types","2023-02 (Issaquah)","","",""
+"`P2674R1 <https://wg21.link/P2674R1>`__","A trait for implicit lifetime types","2023-02 (Issaquah)","|Complete|","20.0",""
"`P2655R3 <https://wg21.link/P2655R3>`__","``common_reference_t`` of ``reference_wrapper`` Should Be a Reference Type","2023-02 (Issaquah)","","",""
"`P2652R2 <https://wg21.link/P2652R2>`__","Disallow User Specialization of ``allocator_traits``","2023-02 (Issaquah)","|Complete|","19.0",""
"`P2787R1 <https://wg21.link/P2787R1>`__","``pmr::generator`` - Promise Types are not Values","2023-02 (Issaquah)","","",""
diff --git a/libcxx/include/__type_traits/is_implicit_lifetime.h b/libcxx/include/__type_traits/is_implicit_lifetime.h
index 4cd593ebdbda60..2aba420bd2b59d 100644
--- a/libcxx/include/__type_traits/is_implicit_lifetime.h
+++ b/libcxx/include/__type_traits/is_implicit_lifetime.h
@@ -27,21 +27,6 @@ struct _LIBCPP_TEMPLATE_VIS is_implicit_lifetime : public bool_constant<__builti
template <class _Tp>
inline constexpr bool is_implicit_lifetime_v = __builtin_is_implicit_lifetime(_Tp);
-# else
-
-template <typename _Tp>
-struct is_implicit_lifetime
- : std::disjunction< std::is_scalar<_Tp>,
- std::is_array<_Tp>,
- std::is_aggregate<_Tp>,
- std::conjunction< std::is_trivially_destructible<_Tp>,
- std::disjunction< std::is_trivially_default_constructible<_Tp>,
- std::is_trivially_copy_constructible<_Tp>,
- std::is_trivially_move_constructible<_Tp>>>> {};
-
-template <class _Tp>
-inline constexpr bool is_implicit_lifetime_v = is_implicit_lifetime<_Tp>::value;
-
# endif
#endif
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index f193b5d95f49f5..da3fa1cbaa66ba 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1944,6 +1944,7 @@ module std_private_type_traits_is_final [system
module std_private_type_traits_is_floating_point [system] { header "__type_traits/is_floating_point.h" }
module std_private_type_traits_is_function [system] { header "__type_traits/is_function.h" }
module std_private_type_traits_is_fundamental [system] { header "__type_traits/is_fundamental.h" }
+module std_private_type_traits_is_implicit_lifetime [system] { header "__type_traits/is_implicit_lifetime.h" }
module std_private_type_traits_is_implicitly_default_constructible [system] {
header "__type_traits/is_implicitly_default_constructible.h"
export std_private_type_traits_integral_constant
diff --git a/libcxx/include/version b/libcxx/include/version
index dc1d3fd268ce83..482913b2759c9b 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -138,6 +138,7 @@ __cpp_lib_ios_noreplace 202207L <ios>
__cpp_lib_is_aggregate 201703L <type_traits>
__cpp_lib_is_constant_evaluated 201811L <type_traits>
__cpp_lib_is_final 201402L <type_traits>
+__cpp_lib_is_implicit_lifetime 202302L <type_traits>
__cpp_lib_is_invocable 201703L <type_traits>
__cpp_lib_is_layout_compatible 201907L <type_traits>
__cpp_lib_is_nothrow_convertible 201806L <type_traits>
@@ -473,6 +474,9 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_forward_like 202207L
# define __cpp_lib_invoke_r 202106L
# define __cpp_lib_ios_noreplace 202207L
+# if __has_builtin(__builtin_is_implicit_lifetime)
+# define __cpp_lib_is_implicit_lifetime 202302L
+# endif
# define __cpp_lib_is_scoped_enum 202011L
# define __cpp_lib_mdspan 202207L
# define __cpp_lib_modules 202207L
diff --git a/libcxx/modules/std/type_traits.inc b/libcxx/modules/std/type_traits.inc
index d368daf35ccb8c..d7b5a7243746b2 100644
--- a/libcxx/modules/std/type_traits.inc
+++ b/libcxx/modules/std/type_traits.inc
@@ -98,7 +98,9 @@ export namespace std {
using std::is_nothrow_destructible;
- // using std::is_implicit_lifetime;
+#if _LIBCPP_STD_VER >= 23 && __has_builtin(__builtin_is_implicit_lifetime)
+ using std::is_implicit_lifetime;
+#endif
using std::has_virtual_destructor;
@@ -243,7 +245,9 @@ export namespace std {
using std::is_destructible_v;
using std::is_empty_v;
using std::is_final_v;
- // using std::is_implicit_lifetime_v;
+#if _LIBCPP_STD_VER >= 23 && __has_builtin(__builtin_is_implicit_lifetime)
+ using std::is_implicit_lifetime_v;
+#endif
using std::is_move_assignable_v;
using std::is_move_constructible_v;
using std::is_nothrow_assignable_v;
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp
index 1cbf2699a95bcc..d9d698ace2b653 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.compile.pass.cpp
@@ -23,6 +23,7 @@
__cpp_lib_is_aggregate 201703L [C++17]
__cpp_lib_is_constant_evaluated 201811L [C++20]
__cpp_lib_is_final 201402L [C++14]
+ __cpp_lib_is_implicit_lifetime 202302L [C++23]
__cpp_lib_is_invocable 201703L [C++17]
__cpp_lib_is_layout_compatible 201907L [C++20]
__cpp_lib_is_nothrow_convertible 201806L [C++20]
@@ -75,6 +76,10 @@
# error "__cpp_lib_is_final should not be defined before c++14"
# endif
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined before c++23"
+# endif
+
# ifdef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should not be defined before c++17"
# endif
@@ -179,6 +184,10 @@
# error "__cpp_lib_is_final should have the value 201402L in c++14"
# endif
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined before c++23"
+# endif
+
# ifdef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should not be defined before c++17"
# endif
@@ -301,6 +310,10 @@
# error "__cpp_lib_is_final should have the value 201402L in c++17"
# endif
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined before c++23"
+# endif
+
# ifndef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should be defined in c++17"
# endif
@@ -444,6 +457,10 @@
# error "__cpp_lib_is_final should have the value 201402L in c++20"
# endif
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined before c++23"
+# endif
+
# ifndef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should be defined in c++20"
# endif
@@ -614,6 +631,19 @@
# error "__cpp_lib_is_final should have the value 201402L in c++23"
# endif
+# if __has_builtin(__builtin_is_implicit_lifetime)
+# ifndef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should be defined in c++23"
+# endif
+# if __cpp_lib_is_implicit_lifetime != 202302L
+# error "__cpp_lib_is_implicit_lifetime should have the value 202302L in c++23"
+# endif
+# else
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined when the requirement '__has_builtin(__builtin_is_implicit_lifetime)' is not met!"
+# endif
+# endif
+
# ifndef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should be defined in c++23"
# endif
@@ -796,6 +826,19 @@
# error "__cpp_lib_is_final should have the value 201402L in c++26"
# endif
+# if __has_builtin(__builtin_is_implicit_lifetime)
+# ifndef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should be defined in c++26"
+# endif
+# if __cpp_lib_is_implicit_lifetime != 202302L
+# error "__cpp_lib_is_implicit_lifetime should have the value 202302L in c++26"
+# endif
+# else
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined when the requirement '__has_builtin(__builtin_is_implicit_lifetime)' is not met!"
+# endif
+# endif
+
# ifndef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should be defined in c++26"
# endif
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index a022c90e166c8d..10cf69f67c39f9 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -125,6 +125,7 @@
__cpp_lib_is_aggregate 201703L [C++17]
__cpp_lib_is_constant_evaluated 201811L [C++20]
__cpp_lib_is_final 201402L [C++14]
+ __cpp_lib_is_implicit_lifetime 202302L [C++23]
__cpp_lib_is_invocable 201703L [C++17]
__cpp_lib_is_layout_compatible 201907L [C++20]
__cpp_lib_is_nothrow_convertible 201806L [C++20]
@@ -671,6 +672,10 @@
# error "__cpp_lib_is_final should not be defined before c++14"
# endif
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined before c++23"
+# endif
+
# ifdef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should not be defined before c++17"
# endif
@@ -1550,6 +1555,10 @@
# error "__cpp_lib_is_final should have the value 201402L in c++14"
# endif
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined before c++23"
+# endif
+
# ifdef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should not be defined before c++17"
# endif
@@ -2564,6 +2573,10 @@
# error "__cpp_lib_is_final should have the value 201402L in c++17"
# endif
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined before c++23"
+# endif
+
# ifndef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should be defined in c++17"
# endif
@@ -3842,6 +3855,10 @@
# error "__cpp_lib_is_final should have the value 201402L in c++20"
# endif
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined before c++23"
+# endif
+
# ifndef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should be defined in c++20"
# endif
@@ -5306,6 +5323,19 @@
# error "__cpp_lib_is_final should have the value 201402L in c++23"
# endif
+# if __has_builtin(__builtin_is_implicit_lifetime)
+# ifndef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should be defined in c++23"
+# endif
+# if __cpp_lib_is_implicit_lifetime != 202302L
+# error "__cpp_lib_is_implicit_lifetime should have the value 202302L in c++23"
+# endif
+# else
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined when the requirement '__has_builtin(__builtin_is_implicit_lifetime)' is not met!"
+# endif
+# endif
+
# ifndef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should be defined in c++23"
# endif
@@ -7112,6 +7142,19 @@
# error "__cpp_lib_is_final should have the value 201402L in c++26"
# endif
+# if __has_builtin(__builtin_is_implicit_lifetime)
+# ifndef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should be defined in c++26"
+# endif
+# if __cpp_lib_is_implicit_lifetime != 202302L
+# error "__cpp_lib_is_implicit_lifetime should have the value 202302L in c++26"
+# endif
+# else
+# ifdef __cpp_lib_is_implicit_lifetime
+# error "__cpp_lib_is_implicit_lifetime should not be defined when the requirement '__has_builtin(__builtin_is_implicit_lifetime)' is not met!"
+# endif
+# endif
+
# ifndef __cpp_lib_is_invocable
# error "__cpp_lib_is_invocable should be defined in c++26"
# 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 7a6af8ba28d80d..2b8d00ea577455 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
@@ -8,6 +8,10 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// These compilers don't support __builtin_is_implicit_lifetime yet.
+// UNSUPPORTED: clang-17, clang-18, clang-19, gcc-14, apple-clang-16, apple-clang-17
+// XFAIL: apple-clang
+
// <type_traits>
// template<class T> struct is_implicit_lifetime;
@@ -106,10 +110,8 @@ struct StructWithZeroSizedArray {
};
#ifdef TEST_COMPILER_CLANG
-// typedef int *align_value_int __attribute__((align_value(16)));
using AlignValueInt = int* __attribute__((align_value(16)));
-// typedef float float4 __attribute__((ext_vector_type(4)));
-using Float4 = float __attribute__((ext_vector_type(4)));
+using Float4 = float __attribute__((ext_vector_type(4)));
struct [[clang::enforce_read_only_placement]] EnforceReadOnlyPlacement {};
struct [[clang::type_visibility("hidden")]] TypeVisibility {};
@@ -146,22 +148,6 @@ constexpr void test_is_implicit_lifetime() {
test_is_implicit_lifetime<T[94], true>();
}
-// #ifdef TEST_COMPILER_CLANG
-// // Test language extensions: attributes
-// template <typename T>
-// constexpr void test_is_implicit_lifetime_with_attributes() {
-// test_is_implicit_lifetime<T [[clang::annotate_type("category2")]]*, true>();
-// test_is_implicit_lifetime<T __attribute__((btf_type_tag("user")))*, true>();
-// static_assert(__builtin_is_implicit_lifetime(int __attribute__((btf_type_tag("user"))) *));
-
-// test_is_implicit_lifetime<T __attribute__((noderef))*, true>();
-
-// test_is_implicit_lifetime<T* _Nonnull, true>();
-// test_is_implicit_lifetime<T* _Null_unspecified, true>();
-// test_is_implicit_lifetime<T* _Nullable, true>();
-// }
-// #endif // TEST_COMPILER_CLANG
-
constexpr bool test() {
// Standard fundamental C++ types
@@ -188,14 +174,6 @@ constexpr bool test() {
test_is_implicit_lifetime<char16_t>();
test_is_implicit_lifetime<char32_t>();
- // test_is_implicit_lifetime<int, true>();
- // test_is_implicit_lifetime<int&, false>();
- // test_is_implicit_lifetime<int&&, false>();
-
- // test_is_implicit_lifetime<int*, true>();
- // test_is_implicit_lifetime<int[], true>();
- // test_is_implicit_lifetime<int[0], true>();
- // test_is_implicit_lifetime<int[94], true>();
test_is_implicit_lifetime<short>();
test_is_implicit_lifetime<short int>();
test_is_implicit_lifetime<signed short>();
@@ -238,12 +216,6 @@ constexpr bool test() {
test_is_implicit_lifetime<void (&)(), false>();
test_is_implicit_lifetime<void (*)(), true>();
- // test_is_implicit_lifetime<int UserDeclaredDestructor::*, true>();
- // test_is_implicit_lifetime<int (UserDeclaredDestructor::*)(), true>();
- // test_is_implicit_lifetime<int (UserDeclaredDestructor::*)() const, true>();
- // test_is_implicit_lifetime<int (UserDeclaredDestructor::*)()&, true>();
- // test_is_implicit_lifetime<int (UserDeclaredDestructor::*)()&&, true>();
-
// Implicit-lifetime class types
test_is_implicit_lifetime<EmptyStruct>();
@@ -301,10 +273,6 @@ constexpr bool test() {
test_is_implicit_lifetime<_Complex double>();
test_is_implicit_lifetime<_Complex long double>();
- // test_is_implicit_lifetime<_Imaginary float>();
- // test_is_implicit_lifetime<_Imaginary double>();
- // test_is_implicit_lifetime<_Imaginary long double>();
-
// Standard C23 types
#ifdef TEST_COMPILER_CLANG
@@ -319,9 +287,6 @@ constexpr bool test() {
test_is_implicit_lifetime<__uint128_t>();
#endif
- // #if __STDC_VERSION__ >= 20
- // #endif
-
#ifdef TEST_COMPILER_CLANG
// https://clang.llvm.org/docs/LanguageExtensions.html#half-precision-floating-point
test_is_implicit_lifetime<__fp16>();
@@ -337,9 +302,6 @@ constexpr bool test() {
test_is_implicit_lifetime<EnforceReadOnlyPlacement, true>();
test_is_implicit_lifetime<TypeVisibility, true>();
- // test_is_implicit_lifetime_with_attributes<int>();
- // test_is_implicit_lifetime_with_attributes<float>();
-
test_is_implicit_lifetime<int [[clang::annotate_type("category2")]]*, true>();
test_is_implicit_lifetime<int __attribute__((btf_type_tag("user")))*, true>();
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 c557731b91a67f..9a43d082f50931 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
@@ -8,30 +8,26 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// These compilers don't support __builtin_is_implicit_lifetime yet.
+// UNSUPPORTED: clang-17, clang-18, clang-19, gcc-14, apple-clang-16, apple-clang-17
+// XFAIL: apple-clang
+
// <type_traits>
// template<class T> struct is_implicit_lifetime;
-#include <cassert>
-#include <cstddef>
#include <type_traits>
-#include "test_macros.h"
-
struct IncompleteStruct;
// expected-error@*:* {{incomplete type 'IncompleteStruct' used in type trait expression}}
static_assert(!std::is_implicit_lifetime<IncompleteStruct>::value);
+// expected-error@*:* {{incomplete type 'IncompleteStruct' used in type trait expression}}
+static_assert(!std::is_implicit_lifetime_v<IncompleteStruct>);
+
// expected-error@*:* {{atomic types are not supported in '__builtin_is_implicit_lifetime'}}
static_assert(!std::is_implicit_lifetime<_Atomic int>::value);
-#if 0
-// FIXME: "variable length arrays in C++ are a Clang extension"
-void test(int n) {
- int varArr[n];
- using VarArrT = decltype(varArr);
- // expected-error@*:* {{variable length arrays are not supported in '__builtin_is_implicit_lifetime'}}
- static_assert(std::is_implicit_lifetime<VarArrT>::value);
-}
-#endif
+// expected-error@*:* {{atomic types are not supported in '__builtin_is_implicit_lifetime'}}
+static_assert(!std::is_implicit_lifetime_v<_Atomic int>);
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 3bdd3adad15b4e..1f5a6b22b47de0 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -742,6 +742,13 @@ def add_version_header(tc):
"values": {"c++14": 201402},
"headers": ["type_traits"],
},
+ {
+ "name": "__cpp_lib_is_implicit_lifetime",
+ "values": {"c++23": 202302},
+ "headers": ["type_traits"],
+ "test_suite_guard": "__has_builtin(__builtin_is_implicit_lifetime)",
+ "libcxx_guard": "__has_builtin(__builtin_is_implicit_lifetime)",
+ },
{
"name": "__cpp_lib_is_invocable",
"values": {"c++17": 201703},
>From 25e6e5e1e373228593d700648168630e50abb920 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 3 Sep 2024 21:53:47 +0300
Subject: [PATCH 03/13] Address a review comment
---
.../meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
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 2b8d00ea577455..4abae28e1cf27b 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
@@ -120,9 +120,7 @@ struct [[clang::type_visibility("hidden")]] TypeVisibility {};
// Test implicit-lifetime type
template <typename T, bool Expected>
constexpr void test_is_implicit_lifetime() {
- static_assert(std::is_implicit_lifetime<T>::value == Expected);
-
- // Runtime check
+ assert(std::is_implicit_lifetime<T>::value == Expected);
assert(std::is_implicit_lifetime_v<T> == Expected);
}
>From b1eb87aaa4979aaa99a9a92b5600efc557a8bbc5 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 5 Sep 2024 16:11:14 +0300
Subject: [PATCH 04/13] Addressed review comments
---
.../is_implicit_lifetime.pass.cpp | 44 +------------------
.../is_implicit_lifetime.verify.cpp | 5 ++-
2 files changed, 4 insertions(+), 45 deletions(-)
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 4abae28e1cf27b..8052fcb64a54be 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,8 +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-17, clang-18, clang-19, gcc-14, apple-clang-16, apple-clang-17
-// XFAIL: apple-clang
+// UNSUPPORTED: clang-17, clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16, apple-clang-17
// <type_traits>
@@ -109,14 +108,6 @@ struct StructWithZeroSizedArray {
int arr[0];
};
-#ifdef TEST_COMPILER_CLANG
-using AlignValueInt = int* __attribute__((align_value(16)));
-using Float4 = float __attribute__((ext_vector_type(4)));
-
-struct [[clang::enforce_read_only_placement]] EnforceReadOnlyPlacement {};
-struct [[clang::type_visibility("hidden")]] TypeVisibility {};
-#endif
-
// Test implicit-lifetime type
template <typename T, bool Expected>
constexpr void test_is_implicit_lifetime() {
@@ -142,7 +133,6 @@ constexpr void test_is_implicit_lifetime() {
// Arrays
test_is_implicit_lifetime<T[], true>();
- test_is_implicit_lifetime<T[0], true>();
test_is_implicit_lifetime<T[94], true>();
}
@@ -278,38 +268,6 @@ constexpr bool test() {
test_is_implicit_lifetime<_BitInt(128)>();
#endif
- // Language extensions: Types
-
-#if !defined(TEST_HAS_NO_INT128)
- test_is_implicit_lifetime<__int128_t>();
- test_is_implicit_lifetime<__uint128_t>();
-#endif
-
-#ifdef TEST_COMPILER_CLANG
- // https://clang.llvm.org/docs/LanguageExtensions.html#half-precision-floating-point
- test_is_implicit_lifetime<__fp16>();
- test_is_implicit_lifetime<__bf16>();
-#endif // TEST_COMPILER_CLANG
-
- // Language extensions: Attributes
-
-#ifdef TEST_COMPILER_CLANG
- test_is_implicit_lifetime<AlignValueInt, true>();
- test_is_implicit_lifetime<Float4, true>();
-
- test_is_implicit_lifetime<EnforceReadOnlyPlacement, true>();
- test_is_implicit_lifetime<TypeVisibility, true>();
-
- test_is_implicit_lifetime<int [[clang::annotate_type("category2")]]*, true>();
- test_is_implicit_lifetime<int __attribute__((btf_type_tag("user")))*, true>();
-
- test_is_implicit_lifetime<int __attribute__((noderef))*, true>();
-
- test_is_implicit_lifetime<int* _Nonnull, true>();
- test_is_implicit_lifetime<int* _Null_unspecified, true>();
- test_is_implicit_lifetime<int* _Nullable, true>();
-#endif // TEST_COMPILER_CLANG
-
return true;
}
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 9a43d082f50931..657d84c5bc9dac 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,8 +9,9 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
// These compilers don't support __builtin_is_implicit_lifetime yet.
-// UNSUPPORTED: clang-17, clang-18, clang-19, gcc-14, apple-clang-16, apple-clang-17
-// XFAIL: apple-clang
+// UNSUPPORTED: clang-17, clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16, apple-clang-17
+
+// ADDITIONAL_COMPILE_FLAGS: -Wno-vla, -Wno-zero-length-array
// <type_traits>
>From db95d1d2c59130f98235ebd22cc0c206baf58c62 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 5 Sep 2024 18:04:51 +0300
Subject: [PATCH 05/13] Addressed philnik's comment
---
.../meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp | 2 +-
.../meta.unary.prop/is_implicit_lifetime.verify.cpp | 4 +---
2 files changed, 2 insertions(+), 4 deletions(-)
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 8052fcb64a54be..cf852805358133 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-17, clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16, apple-clang-17
+// UNSUPPORTED: clang-17, 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 657d84c5bc9dac..516ab218885726 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,9 +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-17, clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16, apple-clang-17
-
-// ADDITIONAL_COMPILE_FLAGS: -Wno-vla, -Wno-zero-length-array
+// UNSUPPORTED: clang-17, clang-18, clang-19, gcc-14, apple-clang-15, apple-clang-16
// <type_traits>
>From 69ac1d35cc8279261b83ec7610db179fbae3c32c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 8 Sep 2024 18:05:03 +0300
Subject: [PATCH 06/13] Addressed some comments
---
.../meta.unary.prop/is_implicit_lifetime.pass.cpp | 7 -------
.../meta.unary.prop/is_implicit_lifetime.verify.cpp | 6 ------
2 files changed, 13 deletions(-)
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 cf852805358133..bfcb5c4b51f3f4 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
@@ -139,7 +139,6 @@ constexpr void test_is_implicit_lifetime() {
constexpr bool test() {
// Standard fundamental C++ types
- test_is_implicit_lifetime<decltype(nullptr), true>();
test_is_implicit_lifetime<std::nullptr_t, true>();
test_is_implicit_lifetime<void, false>();
@@ -255,12 +254,6 @@ constexpr bool test() {
test_is_implicit_lifetime<std::pair<int, float>>();
test_is_implicit_lifetime<std::tuple<int, float>>();
- // Standard C types
-
- test_is_implicit_lifetime<_Complex float>();
- test_is_implicit_lifetime<_Complex double>();
- test_is_implicit_lifetime<_Complex long double>();
-
// Standard C23 types
#ifdef TEST_COMPILER_CLANG
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 516ab218885726..25bba30da612e6 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
@@ -24,9 +24,3 @@ static_assert(!std::is_implicit_lifetime<IncompleteStruct>::value);
// expected-error@*:* {{incomplete type 'IncompleteStruct' used in type trait expression}}
static_assert(!std::is_implicit_lifetime_v<IncompleteStruct>);
-
-// expected-error@*:* {{atomic types are not supported in '__builtin_is_implicit_lifetime'}}
-static_assert(!std::is_implicit_lifetime<_Atomic int>::value);
-
-// expected-error@*:* {{atomic types are not supported in '__builtin_is_implicit_lifetime'}}
-static_assert(!std::is_implicit_lifetime_v<_Atomic int>);
>From bf677ffc7ffd72b04f536092ac699b858a37dcb2 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 8 Sep 2024 18:06:35 +0300
Subject: [PATCH 07/13] Addressed more comments
---
.../meta.unary/meta.unary.prop/is_implicit_lifetime.pass.cpp | 1 -
1 file changed, 1 deletion(-)
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 bfcb5c4b51f3f4..65fd3cf02004e5 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
@@ -129,7 +129,6 @@ constexpr void test_is_implicit_lifetime() {
// Pointer types
test_is_implicit_lifetime<T*, true>();
- test_is_implicit_lifetime<T* __restrict, true>();
// Arrays
test_is_implicit_lifetime<T[], true>();
>From dab49b84c9b92cc0ba8f753577a73b83bc4c9d4f Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 7 Oct 2024 08:02:08 +0300
Subject: [PATCH 08/13] Used `types::for_each` in tests
---
.../is_implicit_lifetime.pass.cpp | 32 ++++++-------------
1 file changed, 9 insertions(+), 23 deletions(-)
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 65fd3cf02004e5..806bdf5aef08e7 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
@@ -22,6 +22,7 @@
#include <utility>
#include "test_macros.h"
+#include "type_algorithms.h"
enum Enum { EV };
enum SignedEnum : signed int {};
@@ -135,6 +136,13 @@ constexpr void test_is_implicit_lifetime() {
test_is_implicit_lifetime<T[94], true>();
}
+struct AritmeticTypesTest {
+ template <class T>
+ constexpr void operator()() {
+ test_is_implicit_lifetime<T>();
+ }
+};
+
constexpr bool test() {
// Standard fundamental C++ types
@@ -160,29 +168,7 @@ constexpr bool test() {
test_is_implicit_lifetime<char16_t>();
test_is_implicit_lifetime<char32_t>();
- test_is_implicit_lifetime<short>();
- test_is_implicit_lifetime<short int>();
- test_is_implicit_lifetime<signed short>();
- test_is_implicit_lifetime<signed short int>();
- test_is_implicit_lifetime<unsigned short>();
- test_is_implicit_lifetime<unsigned short int>();
- test_is_implicit_lifetime<int>();
- test_is_implicit_lifetime<signed>();
- test_is_implicit_lifetime<signed int>();
- test_is_implicit_lifetime<unsigned>();
- test_is_implicit_lifetime<unsigned int>();
- test_is_implicit_lifetime<long>();
- test_is_implicit_lifetime<long int>();
- test_is_implicit_lifetime<signed long>();
- test_is_implicit_lifetime<signed long int>();
- test_is_implicit_lifetime<unsigned long>();
- test_is_implicit_lifetime<unsigned long int>();
- test_is_implicit_lifetime<long long>();
- test_is_implicit_lifetime<long long int>();
- test_is_implicit_lifetime<signed long long>();
- test_is_implicit_lifetime<signed long long int>();
- test_is_implicit_lifetime<unsigned long long>();
- test_is_implicit_lifetime<unsigned long long int>();
+ types::for_each(types::arithmetic_types(), AritmeticTypesTest{});
test_is_implicit_lifetime<float>();
test_is_implicit_lifetime<double>();
>From a4c4bcaf8c0d6c686d1a02c29cd1a418ad88036d Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 7 Oct 2024 08:38:57 +0300
Subject: [PATCH 09/13] Fixed `module.modulemap`
---
libcxx/include/module.modulemap | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index dee9b0b88b7948..bb119722c55452 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -200,6 +200,10 @@ module std_core [system] {
header "__type_traits/is_fundamental.h"
export std_core.type_traits.integral_constant
}
+ module is_implicit_lifetime {
+ header "__type_traits/is_implicit_lifetime.h"
+ export std_core.type_traits.is_implicit_lifetime
+ }
module is_implicitly_default_constructible {
header "__type_traits/is_implicitly_default_constructible.h"
export std_core.type_traits.integral_constant
>From 11f94896aa3405e4116c7cea114d06672f3a3e7f Mon Sep 17 00:00:00 2001
From: Hristo Hristov <zingam at outlook.com>
Date: Mon, 7 Oct 2024 08:46:34 +0300
Subject: [PATCH 10/13] Update libcxx/docs/ReleaseNotes/20.rst
---
libcxx/docs/ReleaseNotes/20.rst | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/docs/ReleaseNotes/20.rst b/libcxx/docs/ReleaseNotes/20.rst
index 85060fdbe51ca6..dcb1102d81d641 100644
--- a/libcxx/docs/ReleaseNotes/20.rst
+++ b/libcxx/docs/ReleaseNotes/20.rst
@@ -44,7 +44,6 @@ Implemented Papers
- ``std::jthread`` and ``<stop_token>`` are not guarded behind ``-fexperimental-library`` anymore
- P2674R1: A trait for implicit lifetime types (`Github <https://github.com/llvm/llvm-project/issues/105259>`__)
-
Improvements and New Features
-----------------------------
>From 2b478fb20aab347f06d9ae6ab76a43c879ddfd60 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 8 Oct 2024 07:15:15 +0300
Subject: [PATCH 11/13] Test atomic
---
.../is_implicit_lifetime.pass.cpp | 27 +++++--------------
1 file changed, 7 insertions(+), 20 deletions(-)
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 806bdf5aef08e7..6eab6a4e014142 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
@@ -15,6 +15,7 @@
// template<class T> struct is_implicit_lifetime;
+#include <atomic>
#include <cassert>
#include <cstddef>
#include <tuple>
@@ -134,6 +135,12 @@ constexpr void test_is_implicit_lifetime() {
// Arrays
test_is_implicit_lifetime<T[], true>();
test_is_implicit_lifetime<T[94], true>();
+
+ if !consteval {
+ if constexpr (std::is_trivially_copyable_v<T>) {
+ test_is_implicit_lifetime<std::atomic<T>, true>();
+ }
+ }
}
struct AritmeticTypesTest {
@@ -152,28 +159,8 @@ constexpr bool test() {
test_is_implicit_lifetime<const void, false>();
test_is_implicit_lifetime<volatile void, false>();
- test_is_implicit_lifetime<bool>();
-
- test_is_implicit_lifetime<char>();
- test_is_implicit_lifetime<signed char>();
- test_is_implicit_lifetime<unsigned char>();
-
-#if !defined(TEST_HAS_NO_WIDE_CHARACTERS)
- test_is_implicit_lifetime<wchar_t>();
-#endif
-
-#if !defined(TEST_HAS_NO_CHAR8_T)
- test_is_implicit_lifetime<char8_t>();
-#endif
- test_is_implicit_lifetime<char16_t>();
- test_is_implicit_lifetime<char32_t>();
-
types::for_each(types::arithmetic_types(), AritmeticTypesTest{});
- test_is_implicit_lifetime<float>();
- test_is_implicit_lifetime<double>();
- test_is_implicit_lifetime<long double>();
-
test_is_implicit_lifetime<Enum>();
test_is_implicit_lifetime<SignedEnum>();
test_is_implicit_lifetime<UnsignedEnum>();
>From 647b10a0269b22cb7dc5e2976d5b97c532e3e57a Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 8 Oct 2024 07:17:20 +0300
Subject: [PATCH 12/13] Cleanup
---
.../meta.unary.prop/is_implicit_lifetime.pass.cpp | 7 -------
1 file changed, 7 deletions(-)
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 6eab6a4e014142..a6ab77158aae1d 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
@@ -15,7 +15,6 @@
// template<class T> struct is_implicit_lifetime;
-#include <atomic>
#include <cassert>
#include <cstddef>
#include <tuple>
@@ -135,12 +134,6 @@ constexpr void test_is_implicit_lifetime() {
// Arrays
test_is_implicit_lifetime<T[], true>();
test_is_implicit_lifetime<T[94], true>();
-
- if !consteval {
- if constexpr (std::is_trivially_copyable_v<T>) {
- test_is_implicit_lifetime<std::atomic<T>, true>();
- }
- }
}
struct AritmeticTypesTest {
>From 13e4470fe2d52f4b726a02d80c7660241acc0374 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 8 Oct 2024 19:55:52 +0300
Subject: [PATCH 13/13] Addressed review comment
---
libcxx/include/module.modulemap | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index bb119722c55452..22a1313498e73e 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -202,7 +202,7 @@ module std_core [system] {
}
module is_implicit_lifetime {
header "__type_traits/is_implicit_lifetime.h"
- export std_core.type_traits.is_implicit_lifetime
+ export std_core.type_traits.integral_constant
}
module is_implicitly_default_constructible {
header "__type_traits/is_implicitly_default_constructible.h"
More information about the libcxx-commits
mailing list