244 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// REQUIRES: std-at-least-c++2310 11// These compilers don't support __builtin_is_implicit_lifetime yet.12// UNSUPPORTED: clang-19, gcc-15, apple-clang-1713 14// <type_traits>15 16// template<class T> struct is_implicit_lifetime;17 18#include <cassert>19#include <cstddef>20#include <expected>21#include <optional>22#include <tuple>23#include <type_traits>24#include <utility>25#include <variant>26 27#include "test_macros.h"28#include "type_algorithms.h"29 30enum Enum { EV };31enum SignedEnum : signed int {};32enum UnsignedEnum : unsigned int {};33 34enum class EnumClass { EV };35enum class SignedEnumClass : signed int {};36enum class UnsignedEnumClass : unsigned int {};37 38struct EmptyStruct {};39struct IncompleteStruct;40 41struct NoEligibleTrivialConstructor {42 NoEligibleTrivialConstructor() {};43 NoEligibleTrivialConstructor(const NoEligibleTrivialConstructor&) {}44 NoEligibleTrivialConstructor(NoEligibleTrivialConstructor&&) {}45};46 47struct OnlyDefaultConstructorIsTrivial {48 OnlyDefaultConstructorIsTrivial() = default;49 OnlyDefaultConstructorIsTrivial(const OnlyDefaultConstructorIsTrivial&) {}50 OnlyDefaultConstructorIsTrivial(OnlyDefaultConstructorIsTrivial&&) {}51};52 53struct AllConstructorsAreTrivial {54 AllConstructorsAreTrivial() = default;55 AllConstructorsAreTrivial(const AllConstructorsAreTrivial&) = default;56 AllConstructorsAreTrivial(AllConstructorsAreTrivial&&) = default;57};58 59struct InheritedNoEligibleTrivialConstructor : NoEligibleTrivialConstructor {60 using NoEligibleTrivialConstructor::NoEligibleTrivialConstructor;61};62 63struct InheritedOnlyDefaultConstructorIsTrivial : OnlyDefaultConstructorIsTrivial {64 using OnlyDefaultConstructorIsTrivial::OnlyDefaultConstructorIsTrivial;65};66 67struct InheritedAllConstructorsAreTrivial : AllConstructorsAreTrivial {68 using AllConstructorsAreTrivial::AllConstructorsAreTrivial;69};70 71struct UserDeclaredDestructor {72 ~UserDeclaredDestructor() = default;73};74 75struct UserProvidedDestructor {76 ~UserProvidedDestructor() {}77};78 79struct UserDeletedDestructorInAggregate {80 ~UserDeletedDestructorInAggregate() = delete;81};82 83struct UserDeletedDestructorInNonAggregate {84 virtual void NonAggregate();85 ~UserDeletedDestructorInNonAggregate() = delete;86};87 88struct DeletedDestructorViaBaseInAggregate : UserDeletedDestructorInAggregate {};89struct DeletedDestructorViaBaseInNonAggregate : UserDeletedDestructorInNonAggregate {};90 91template <bool B>92struct ConstrainedUserDeclaredDefaultConstructor {93 ConstrainedUserDeclaredDefaultConstructor()94 requires B95 = default;96 ConstrainedUserDeclaredDefaultConstructor(const ConstrainedUserDeclaredDefaultConstructor&) {}97};98 99template <bool B>100struct ConstrainedUserProvidedDestructor {101 ~ConstrainedUserProvidedDestructor() = default;102 ~ConstrainedUserProvidedDestructor()103 requires B104 {}105};106 107struct StructWithFlexibleArrayMember {108 int arr[];109};110 111struct StructWithZeroSizedArray {112 int arr[0];113};114 115// Test implicit-lifetime type116template <typename T, bool Expected>117constexpr void test_is_implicit_lifetime() {118 assert(std::is_implicit_lifetime<T>::value == Expected);119 assert(std::is_implicit_lifetime_v<T> == Expected);120}121 122// Test pointer, reference, array, etc. types123template <typename T>124constexpr void test_is_implicit_lifetime() {125 test_is_implicit_lifetime<T, true>();126 127 // cv-qualified128 test_is_implicit_lifetime<const T, true>();129 test_is_implicit_lifetime<volatile T, true>();130 131 test_is_implicit_lifetime<T&, false>();132 test_is_implicit_lifetime<T&&, false>();133 134 // Pointer types135 test_is_implicit_lifetime<T*, true>();136 137 // Arrays138 test_is_implicit_lifetime<T[], true>();139 test_is_implicit_lifetime<T[94], true>();140}141 142constexpr bool test() {143 // Standard fundamental C++ types144 145 test_is_implicit_lifetime<std::nullptr_t, true>();146 147 test_is_implicit_lifetime<void, false>();148 test_is_implicit_lifetime<const void, false>();149 test_is_implicit_lifetime<volatile void, false>();150 151 types::for_each(types::arithmetic_types(), []<typename T> { test_is_implicit_lifetime<T>(); });152 153 test_is_implicit_lifetime<Enum>();154 test_is_implicit_lifetime<SignedEnum>();155 test_is_implicit_lifetime<UnsignedEnum>();156 157 test_is_implicit_lifetime<EnumClass>();158 test_is_implicit_lifetime<SignedEnumClass>();159 test_is_implicit_lifetime<UnsignedEnumClass>();160 161 test_is_implicit_lifetime<void(), false>();162 test_is_implicit_lifetime<void()&, false>();163 test_is_implicit_lifetime<void() const, false>();164 test_is_implicit_lifetime<void (&)(), false>();165 test_is_implicit_lifetime<void (*)(), true>();166 167 // Implicit-lifetime class types168 169 test_is_implicit_lifetime<EmptyStruct>();170 test_is_implicit_lifetime<int EmptyStruct::*, true>(); // Pointer-to-member171 test_is_implicit_lifetime<int (EmptyStruct::*)(), true>();172 test_is_implicit_lifetime<int (EmptyStruct::*)() const, true>();173 test_is_implicit_lifetime<int (EmptyStruct::*)()&, true>();174 test_is_implicit_lifetime<int (EmptyStruct::*)()&&, true>();175 176 test_is_implicit_lifetime<IncompleteStruct[], true>();177 test_is_implicit_lifetime<IncompleteStruct[82], true>();178 179 test_is_implicit_lifetime<UserDeclaredDestructor>();180 181 test_is_implicit_lifetime<UserProvidedDestructor, false>();182 183 test_is_implicit_lifetime<NoEligibleTrivialConstructor, false>();184 185 test_is_implicit_lifetime<OnlyDefaultConstructorIsTrivial, true>();186 187 test_is_implicit_lifetime<AllConstructorsAreTrivial, true>();188 189 test_is_implicit_lifetime<InheritedNoEligibleTrivialConstructor, false>();190 191 test_is_implicit_lifetime<InheritedOnlyDefaultConstructorIsTrivial, true>();192 193 test_is_implicit_lifetime<InheritedAllConstructorsAreTrivial, true>();194 195 test_is_implicit_lifetime<UserDeletedDestructorInAggregate, true>();196 197 test_is_implicit_lifetime<UserDeletedDestructorInNonAggregate, false>();198 199 test_is_implicit_lifetime<DeletedDestructorViaBaseInAggregate, true>();200 201 test_is_implicit_lifetime<DeletedDestructorViaBaseInNonAggregate, false>();202 203 test_is_implicit_lifetime<ConstrainedUserDeclaredDefaultConstructor<true>, true>();204 test_is_implicit_lifetime<ConstrainedUserDeclaredDefaultConstructor<false>, false>();205 206 test_is_implicit_lifetime<ConstrainedUserProvidedDestructor<true>, false>();207 test_is_implicit_lifetime<ConstrainedUserProvidedDestructor<false>, true>();208 209 test_is_implicit_lifetime<StructWithFlexibleArrayMember, true>();210 211 test_is_implicit_lifetime<StructWithZeroSizedArray, true>();212 213 // C++ standard library types214 215 // These types are guaranteed to be implicit-lifetime.216 test_is_implicit_lifetime<std::expected<int, float>>();217 test_is_implicit_lifetime<std::optional<float>>();218 test_is_implicit_lifetime<std::variant<float, int>>();219 220#ifdef _LIBCPP_VERSION221 // These types should be implicit-lifetime, but they are not guaranteed to be so.222# ifndef _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR223 test_is_implicit_lifetime<std::pair<int, float>>();224# endif225 test_is_implicit_lifetime<std::tuple<int, float>>();226#endif227 228 // Standard C23 types229 230#ifdef TEST_COMPILER_CLANG231 test_is_implicit_lifetime<_BitInt(8)>();232 test_is_implicit_lifetime<_BitInt(128)>();233#endif234 235 return true;236}237 238int main(int, char**) {239 test();240 static_assert(test());241 242 return 0;243}244