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