[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
Wed Sep 4 07:01:51 PDT 2024


================
@@ -0,0 +1,321 @@
+//===----------------------------------------------------------------------===//
+//
+// 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-16, apple-clang-17
+// XFAIL: apple-clang
+
+// <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
+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() {
+  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[0], true>();
----------------
philnik777 wrote:

While these tests are nice for clang, I don't think we should test everything here. We don't define how these extensions interact with standard features and we don't claim any level of support for most of this. Quite to the contrary, we've had discussions about supporting some of these in the past and came to the conclusion that we don't want to support them. We're also not adding any additional testing, since these should already be tested by clang. If not, they can go into the clang test suite.

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


More information about the libcxx-commits mailing list