//===----------------------------------------------------------------------===//
//
// 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"
#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 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>();
// Arrays
test_is_implicit_lifetime<T[], true>();
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
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>();
types::for_each(types::arithmetic_types(), AritmeticTypesTest{});
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 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;
}