[libcxx-commits] [libcxx] [libc++][type_traits] P2674R1: A trait for implicit lifetime types (PR #106870)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Sun Sep 8 06:30:59 PDT 2024


================
@@ -0,0 +1,279 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// 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
+
+// <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];
+};
+
+// Test implicit-lifetime type
+template <typename T, bool Expected>
+constexpr void test_is_implicit_lifetime() {
+  assert(std::is_implicit_lifetime<T>::value == Expected);
+  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[94], true>();
+}
+
+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<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>();
+
+  // 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>();
----------------
philnik777 wrote:

We don't have any kind of support for `_Complex`, and I'm not even sure what that would look like.

https://github.com/llvm/llvm-project/pull/106870


More information about the libcxx-commits mailing list