//===----------------------------------------------------------------------===// // // 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 __builtin_is_implicit_lifetime yet. // UNSUPPORTED: clang-19, gcc-15, apple-clang-17 // // template struct is_implicit_lifetime; #include #include #include #include #include #include #include #include #include "test_macros.h" #include "type_algorithms.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 NoEligibleTrivialConstructor { NoEligibleTrivialConstructor() {}; NoEligibleTrivialConstructor(const NoEligibleTrivialConstructor&) {} NoEligibleTrivialConstructor(NoEligibleTrivialConstructor&&) {} }; struct OnlyDefaultConstructorIsTrivial { OnlyDefaultConstructorIsTrivial() = default; OnlyDefaultConstructorIsTrivial(const OnlyDefaultConstructorIsTrivial&) {} OnlyDefaultConstructorIsTrivial(OnlyDefaultConstructorIsTrivial&&) {} }; struct AllConstructorsAreTrivial { AllConstructorsAreTrivial() = default; AllConstructorsAreTrivial(const AllConstructorsAreTrivial&) = default; AllConstructorsAreTrivial(AllConstructorsAreTrivial&&) = default; }; struct InheritedNoEligibleTrivialConstructor : NoEligibleTrivialConstructor { using NoEligibleTrivialConstructor::NoEligibleTrivialConstructor; }; struct InheritedOnlyDefaultConstructorIsTrivial : OnlyDefaultConstructorIsTrivial { using OnlyDefaultConstructorIsTrivial::OnlyDefaultConstructorIsTrivial; }; struct InheritedAllConstructorsAreTrivial : AllConstructorsAreTrivial { using AllConstructorsAreTrivial::AllConstructorsAreTrivial; }; 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 struct ConstrainedUserDeclaredDefaultConstructor { ConstrainedUserDeclaredDefaultConstructor() requires B = default; ConstrainedUserDeclaredDefaultConstructor(const ConstrainedUserDeclaredDefaultConstructor&) {} }; template struct ConstrainedUserProvidedDestructor { ~ConstrainedUserProvidedDestructor() = default; ~ConstrainedUserProvidedDestructor() requires B {} }; struct StructWithFlexibleArrayMember { int arr[]; }; struct StructWithZeroSizedArray { int arr[0]; }; // Test implicit-lifetime type template constexpr void test_is_implicit_lifetime() { assert(std::is_implicit_lifetime::value == Expected); assert(std::is_implicit_lifetime_v == Expected); } // Test pointer, reference, array, etc. types template constexpr void test_is_implicit_lifetime() { test_is_implicit_lifetime(); // cv-qualified test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); // Pointer types test_is_implicit_lifetime(); // Arrays test_is_implicit_lifetime(); test_is_implicit_lifetime(); } constexpr bool test() { // Standard fundamental C++ types test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); types::for_each(types::arithmetic_types(), [] { test_is_implicit_lifetime(); }); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); // Implicit-lifetime class types test_is_implicit_lifetime(); test_is_implicit_lifetime(); // Pointer-to-member test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); test_is_implicit_lifetime, true>(); test_is_implicit_lifetime, false>(); test_is_implicit_lifetime, false>(); test_is_implicit_lifetime, true>(); test_is_implicit_lifetime(); test_is_implicit_lifetime(); // C++ standard library types // These types are guaranteed to be implicit-lifetime. test_is_implicit_lifetime>(); test_is_implicit_lifetime>(); test_is_implicit_lifetime>(); #ifdef _LIBCPP_VERSION // These types should be implicit-lifetime, but they are not guaranteed to be so. # ifndef _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR test_is_implicit_lifetime>(); # endif test_is_implicit_lifetime>(); #endif // Standard C23 types #ifdef TEST_COMPILER_CLANG test_is_implicit_lifetime<_BitInt(8)>(); test_is_implicit_lifetime<_BitInt(128)>(); #endif return true; } int main(int, char**) { test(); static_assert(test()); return 0; }