236 lines · cpp
1// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins -Wno-defaulted-function-deleted2// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins -Wno-defaulted-function-deleted -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=143 4// expected-no-diagnostics5 6template<typename T, bool B> struct trivially_copyable_check {7 static_assert(B == __has_trivial_copy(T), "");8 static_assert(B == __is_trivially_constructible(T, T), "");9 static_assert(B == __is_trivially_constructible(T, const T &), "");10 static_assert(B == __is_trivially_constructible(T, T &&), "");11 typedef void type;12};13template<typename T> using trivially_copyable =14 typename trivially_copyable_check<T, true>::type;15template<typename T> using not_trivially_copyable =16 typename trivially_copyable_check<T, false>::type;17 18struct Trivial {};19using _ = trivially_copyable<Trivial>;20 21// A copy/move constructor for class X is trivial if it is not user-provided,22struct UserProvided {23 UserProvided(const UserProvided &);24};25using _ = not_trivially_copyable<UserProvided>;26 27// its declared parameter type is the same as if it had been implicitly28// declared,29struct NonConstCopy {30 NonConstCopy(NonConstCopy &) = default;31};32#if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 1433// Up until (and including) Clang 14, non-const copy constructors were not trivial because of dr217134using _ = not_trivially_copyable<NonConstCopy>;35#else36// In the latest Clang version, all defaulted constructors are trivial, even if non-const, because37// dr2171 is fixed.38static_assert(__has_trivial_copy(NonConstCopy), "");39static_assert(__is_trivially_constructible(NonConstCopy, NonConstCopy &), "");40static_assert(!__is_trivially_constructible(NonConstCopy, NonConstCopy), "");41static_assert(!__is_trivially_constructible(NonConstCopy, const NonConstCopy &), "");42static_assert(!__is_trivially_constructible(NonConstCopy, NonConstCopy &&), "");43 44struct DefaultedSpecialMembers {45 DefaultedSpecialMembers(const DefaultedSpecialMembers &) = default;46 DefaultedSpecialMembers(DefaultedSpecialMembers &) = default;47 DefaultedSpecialMembers(DefaultedSpecialMembers &&) = default;48};49using _ = trivially_copyable<DefaultedSpecialMembers>;50#endif51 52// class X has no virtual functions53struct VFn {54 virtual void f();55};56using _ = not_trivially_copyable<VFn>;57 58// and no virtual base classes59struct VBase : virtual Trivial {};60using _ = not_trivially_copyable<VBase>;61 62// and the constructor selected to copy/move each [direct subobject] is trivial63struct TemplateCtor {64 template<typename T> TemplateCtor(T &);65};66using _ = trivially_copyable<TemplateCtor>;67struct TemplateCtorMember {68 TemplateCtor tc;69};70using _ = trivially_copyable<TemplateCtorMember>;71 72// We can select a non-trivial copy ctor even if there is a trivial one.73struct MutableTemplateCtorMember {74 mutable TemplateCtor mtc;75};76static_assert(!__is_trivially_constructible(MutableTemplateCtorMember, const MutableTemplateCtorMember &), "");77static_assert(__is_trivially_constructible(MutableTemplateCtorMember, MutableTemplateCtorMember &&), "");78struct MutableTemplateCtorMember2 {79 MutableTemplateCtorMember2(const MutableTemplateCtorMember2 &) = default;80 MutableTemplateCtorMember2(MutableTemplateCtorMember2 &&) = default;81 mutable TemplateCtor mtc;82};83static_assert(!__is_trivially_constructible(MutableTemplateCtorMember2, const MutableTemplateCtorMember2 &), "");84static_assert(__is_trivially_constructible(MutableTemplateCtorMember2, MutableTemplateCtorMember2 &&), "");85 86// Both trivial and non-trivial special members.87struct TNT {88 TNT(const TNT &) = default; // trivial89 TNT(TNT &); // non-trivial90 91 TNT(TNT &&) = default; // trivial92 TNT(const TNT &&); // non-trivial93};94 95static_assert(!__has_trivial_copy(TNT), "lie deliberately for gcc compatibility");96static_assert(__is_trivially_constructible(TNT, TNT), "");97static_assert(!__is_trivially_constructible(TNT, TNT &), "");98static_assert(__is_trivially_constructible(TNT, const TNT &), "");99static_assert(!__is_trivially_constructible(TNT, volatile TNT &), "");100static_assert(__is_trivially_constructible(TNT, TNT &&), "");101static_assert(!__is_trivially_constructible(TNT, const TNT &&), "");102static_assert(!__is_trivially_constructible(TNT, volatile TNT &&), "");103 104// This has only trivial special members.105struct DerivedFromTNT : TNT {};106 107static_assert(__has_trivial_copy(DerivedFromTNT), "");108static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT), "");109static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &), "");110static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &), "");111static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &), "");112static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &&), "");113static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &&), "");114static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &&), "");115 116// This has only trivial special members.117struct TNTMember {118 TNT tnt;119};120 121static_assert(__has_trivial_copy(TNTMember), "");122static_assert(__is_trivially_constructible(TNTMember, TNTMember), "");123static_assert(__is_trivially_constructible(TNTMember, TNTMember &), "");124static_assert(__is_trivially_constructible(TNTMember, const TNTMember &), "");125static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &), "");126static_assert(__is_trivially_constructible(TNTMember, TNTMember &&), "");127static_assert(__is_trivially_constructible(TNTMember, const TNTMember &&), "");128static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &&), "");129 130struct NCCTNT : NonConstCopy, TNT {};131 132static_assert(!__has_trivial_copy(NCCTNT), "");133static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT), "");134static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &), "");135static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &), "");136static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &), "");137static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &&), "");138static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &&), "");139static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &&), "");140 141struct TemplateCtorNoMove {142 TemplateCtorNoMove(const TemplateCtorNoMove &) = default;143 template<typename T> TemplateCtorNoMove(T &&);144};145static_assert(__is_trivially_constructible(TemplateCtorNoMove, const TemplateCtorNoMove &), "");146static_assert(!__is_trivially_constructible(TemplateCtorNoMove, TemplateCtorNoMove &&), "");147 148struct UseTemplateCtorNoMove {149 TemplateCtorNoMove tcnm;150};151static_assert(__is_trivially_constructible(UseTemplateCtorNoMove, const UseTemplateCtorNoMove &), "");152static_assert(!__is_trivially_constructible(UseTemplateCtorNoMove, UseTemplateCtorNoMove &&), "");153 154struct TemplateCtorNoMoveSFINAE {155 TemplateCtorNoMoveSFINAE(const TemplateCtorNoMoveSFINAE &) = default;156 template<typename T, typename U = typename T::error> TemplateCtorNoMoveSFINAE(T &&);157};158static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, const TemplateCtorNoMoveSFINAE &), "");159static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, TemplateCtorNoMoveSFINAE &&), "");160 161struct UseTemplateCtorNoMoveSFINAE {162 TemplateCtorNoMoveSFINAE tcnm;163};164static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, const UseTemplateCtorNoMoveSFINAE &), "");165static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, UseTemplateCtorNoMoveSFINAE &&), "");166 167namespace TrivialityDependsOnImplicitDeletion {168 struct PrivateMove {169 PrivateMove(const PrivateMove &) = default;170 private:171 PrivateMove(PrivateMove &&);172 friend class Access;173 };174 static_assert(__is_trivially_constructible(PrivateMove, const PrivateMove &), "");175 static_assert(!__is_trivially_constructible(PrivateMove, PrivateMove &&), "");176 177 struct NoAccess {178 PrivateMove pm;179 // NoAccess's move is deleted, so moves of it use PrivateMove's copy ctor,180 // which is trivial.181 };182 static_assert(__is_trivially_constructible(NoAccess, const NoAccess &), "");183 static_assert(__is_trivially_constructible(NoAccess, NoAccess &&), "");184 struct TopNoAccess : NoAccess {};185 static_assert(__is_trivially_constructible(TopNoAccess, const TopNoAccess &), "");186 static_assert(__is_trivially_constructible(TopNoAccess, TopNoAccess &&), "");187 188 struct Access {189 PrivateMove pm;190 // NoAccess's move would *not* be deleted, so is *not* suppressed,191 // so moves of it use PrivateMove's move ctor, which is not trivial.192 };193 static_assert(__is_trivially_constructible(Access, const Access &), "");194 static_assert(!__is_trivially_constructible(Access, Access &&), "");195 struct TopAccess : Access {};196 static_assert(__is_trivially_constructible(TopAccess, const TopAccess &), "");197 static_assert(!__is_trivially_constructible(TopAccess, TopAccess &&), "");198}199 200namespace TrivialityDependsOnDestructor {201 class HasInaccessibleDestructor { ~HasInaccessibleDestructor() = default; };202 struct HasImplicitlyDeletedDestructor : HasInaccessibleDestructor {};203 struct HasImplicitlyDeletedCopyCtor : HasImplicitlyDeletedDestructor {204 HasImplicitlyDeletedCopyCtor() = default;205 template<typename T> HasImplicitlyDeletedCopyCtor(T &&);206 // Copy ctor is deleted but trivial.207 // Move ctor is suppressed.208 HasImplicitlyDeletedCopyCtor(const HasImplicitlyDeletedCopyCtor&) = default;209 HasImplicitlyDeletedCopyCtor(HasImplicitlyDeletedCopyCtor&&) = default;210 };211 struct Test : HasImplicitlyDeletedCopyCtor {212 Test(const Test&) = default;213 Test(Test&&) = default;214 };215 // Implicit copy ctor calls deleted trivial copy ctor.216 static_assert(__has_trivial_copy(Test), "");217 // This is false because the destructor is deleted.218 static_assert(!__is_trivially_constructible(Test, const Test &), "");219 // Implicit move ctor calls template ctor.220 static_assert(!__is_trivially_constructible(Test, Test &&), "");221 222 struct HasAccessibleDestructor { ~HasAccessibleDestructor() = default; };223 struct HasImplicitlyDefaultedDestructor : HasAccessibleDestructor {};224 struct HasImplicitlyDefaultedCopyCtor : HasImplicitlyDefaultedDestructor {225 template<typename T> HasImplicitlyDefaultedCopyCtor(T &&);226 // Copy ctor is trivial.227 // Move ctor is trivial.228 };229 struct Test2 : HasImplicitlyDefaultedCopyCtor {};230 // Implicit copy ctor calls trivial copy ctor.231 static_assert(__has_trivial_copy(Test2), "");232 static_assert(__is_trivially_constructible(Test2, const Test2 &), "");233 // Implicit move ctor calls trivial move ctor.234 static_assert(__is_trivially_constructible(Test2, Test2 &&), "");235}236