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_assignable_check { 6*67e74705SXin Li static_assert(B == __has_trivial_assign(T), ""); 7*67e74705SXin Li static_assert(B == __is_trivially_assignable(T&, T), ""); 8*67e74705SXin Li static_assert(B == __is_trivially_assignable(T&, const T &), ""); 9*67e74705SXin Li static_assert(B == __is_trivially_assignable(T&, T &&), ""); 10*67e74705SXin Li static_assert(B == __is_trivially_assignable(T&&, T), ""); 11*67e74705SXin Li static_assert(B == __is_trivially_assignable(T&&, const T &), ""); 12*67e74705SXin Li static_assert(B == __is_trivially_assignable(T&&, T &&), ""); 13*67e74705SXin Li typedef void type; 14*67e74705SXin Li }; 15*67e74705SXin Li template<typename T> using trivially_assignable = 16*67e74705SXin Li typename trivially_assignable_check<T, true>::type; 17*67e74705SXin Li template<typename T> using not_trivially_assignable = 18*67e74705SXin Li typename trivially_assignable_check<T, false>::type; 19*67e74705SXin Li 20*67e74705SXin Li struct Trivial {}; 21*67e74705SXin Li using _ = trivially_assignable<Trivial>; 22*67e74705SXin Li 23*67e74705SXin Li // A copy/move assignment operator for class X is trivial if it is not user-provided, 24*67e74705SXin Li struct UserProvided { 25*67e74705SXin Li UserProvided &operator=(const UserProvided &); 26*67e74705SXin Li }; 27*67e74705SXin Li using _ = not_trivially_assignable<UserProvided>; 28*67e74705SXin Li 29*67e74705SXin Li // its declared parameter type is the same as if it had been implicitly 30*67e74705SXin Li // declared, 31*67e74705SXin Li struct NonConstCopy { 32*67e74705SXin Li NonConstCopy &operator=(NonConstCopy &) = default; 33*67e74705SXin Li }; 34*67e74705SXin Li using _ = not_trivially_assignable<NonConstCopy>; 35*67e74705SXin Li 36*67e74705SXin Li // class X has no virtual functions 37*67e74705SXin Li struct VFn { 38*67e74705SXin Li virtual void f(); 39*67e74705SXin Li }; 40*67e74705SXin Li using _ = not_trivially_assignable<VFn>; 41*67e74705SXin Li 42*67e74705SXin Li // and no virtual base classes 43*67e74705SXin Li struct VBase : virtual Trivial {}; 44*67e74705SXin Li using _ = not_trivially_assignable<VBase>; 45*67e74705SXin Li 46*67e74705SXin Li // and the assignment operator selected to copy/move each [direct subobject] is trivial 47*67e74705SXin Li struct TemplateCtor { 48*67e74705SXin Li template<typename T> TemplateCtor operator=(T &); 49*67e74705SXin Li }; 50*67e74705SXin Li using _ = trivially_assignable<TemplateCtor>; 51*67e74705SXin Li struct TemplateCtorMember { 52*67e74705SXin Li TemplateCtor tc; 53*67e74705SXin Li }; 54*67e74705SXin Li using _ = trivially_assignable<TemplateCtorMember>; 55*67e74705SXin Li struct MutableTemplateCtorMember { 56*67e74705SXin Li mutable TemplateCtor mtc; 57*67e74705SXin Li }; 58*67e74705SXin Li static_assert(!__is_trivially_assignable(MutableTemplateCtorMember, const MutableTemplateCtorMember &), ""); 59*67e74705SXin Li static_assert(__is_trivially_assignable(MutableTemplateCtorMember, MutableTemplateCtorMember &&), ""); 60*67e74705SXin Li 61*67e74705SXin Li // Both trivial and non-trivial special members. 62*67e74705SXin Li struct TNT { 63*67e74705SXin Li TNT &operator=(const TNT &) = default; // trivial 64*67e74705SXin Li TNT &operator=(TNT &); // non-trivial 65*67e74705SXin Li 66*67e74705SXin Li TNT &operator=(TNT &&) = default; // trivial 67*67e74705SXin Li TNT &operator=(const TNT &&); // non-trivial 68*67e74705SXin Li }; 69*67e74705SXin Li 70*67e74705SXin Li static_assert(!__has_trivial_assign(TNT), "lie deliberately for gcc compatibility"); 71*67e74705SXin Li static_assert(__is_trivially_assignable(TNT, TNT), ""); 72*67e74705SXin Li static_assert(!__is_trivially_assignable(TNT, TNT &), ""); 73*67e74705SXin Li static_assert(__is_trivially_assignable(TNT, const TNT &), ""); 74*67e74705SXin Li static_assert(!__is_trivially_assignable(TNT, volatile TNT &), ""); 75*67e74705SXin Li static_assert(__is_trivially_assignable(TNT, TNT &&), ""); 76*67e74705SXin Li static_assert(!__is_trivially_assignable(TNT, const TNT &&), ""); 77*67e74705SXin Li static_assert(!__is_trivially_assignable(TNT, volatile TNT &&), ""); 78*67e74705SXin Li 79*67e74705SXin Li // This has only trivial special members. 80*67e74705SXin Li struct DerivedFromTNT : TNT {}; 81*67e74705SXin Li 82*67e74705SXin Li static_assert(__has_trivial_assign(DerivedFromTNT), ""); 83*67e74705SXin Li static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT), ""); 84*67e74705SXin Li static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &), ""); 85*67e74705SXin Li static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &), ""); 86*67e74705SXin Li static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &), ""); 87*67e74705SXin Li static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &&), ""); 88*67e74705SXin Li static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &&), ""); 89*67e74705SXin Li static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &&), ""); 90*67e74705SXin Li 91*67e74705SXin Li // This has only trivial special members. 92*67e74705SXin Li struct TNTMember { 93*67e74705SXin Li TNT tnt; 94*67e74705SXin Li }; 95*67e74705SXin Li 96*67e74705SXin Li static_assert(__has_trivial_assign(TNTMember), ""); 97*67e74705SXin Li static_assert(__is_trivially_assignable(TNTMember, TNTMember), ""); 98*67e74705SXin Li static_assert(__is_trivially_assignable(TNTMember, TNTMember &), ""); 99*67e74705SXin Li static_assert(__is_trivially_assignable(TNTMember, const TNTMember &), ""); 100*67e74705SXin Li static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &), ""); 101*67e74705SXin Li static_assert(__is_trivially_assignable(TNTMember, TNTMember &&), ""); 102*67e74705SXin Li static_assert(__is_trivially_assignable(TNTMember, const TNTMember &&), ""); 103*67e74705SXin Li static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &&), ""); 104*67e74705SXin Li 105*67e74705SXin Li struct NCCTNT : NonConstCopy, TNT {}; 106*67e74705SXin Li 107*67e74705SXin Li static_assert(!__has_trivial_assign(NCCTNT), ""); 108*67e74705SXin Li static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT), ""); 109*67e74705SXin Li static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &), ""); 110*67e74705SXin Li static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &), ""); 111*67e74705SXin Li static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &), ""); 112*67e74705SXin Li static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &&), ""); 113*67e74705SXin Li static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &&), ""); 114*67e74705SXin Li static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &&), ""); 115*67e74705SXin Li 116*67e74705SXin Li struct MultipleTrivial { 117*67e74705SXin Li // All four of these are trivial. 118*67e74705SXin Li MultipleTrivial &operator=(const MultipleTrivial &) & = default; 119*67e74705SXin Li MultipleTrivial &operator=(const MultipleTrivial &) && = default; 120*67e74705SXin Li MultipleTrivial &operator=(MultipleTrivial &&) & = default; 121*67e74705SXin Li MultipleTrivial &operator=(MultipleTrivial &&) && = default; 122*67e74705SXin Li }; 123*67e74705SXin Li 124*67e74705SXin Li using _ = trivially_assignable<MultipleTrivial>; 125*67e74705SXin Li 126*67e74705SXin Li struct RefQualifier { 127*67e74705SXin Li RefQualifier &operator=(const RefQualifier &) & = default; 128*67e74705SXin Li RefQualifier &operator=(const RefQualifier &) &&; 129*67e74705SXin Li RefQualifier &operator=(RefQualifier &&) &; 130*67e74705SXin Li RefQualifier &operator=(RefQualifier &&) && = default; 131*67e74705SXin Li }; 132*67e74705SXin Li struct DerivedFromRefQualifier : RefQualifier { 133*67e74705SXin Li // Both of these call the trivial copy operation. 134*67e74705SXin Li DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) & = default; 135*67e74705SXin Li DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) && = default; 136*67e74705SXin Li // Both of these call the non-trivial move operation. 137*67e74705SXin Li DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) & = default; 138*67e74705SXin Li DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) && = default; 139*67e74705SXin Li }; 140*67e74705SXin Li static_assert(__is_trivially_assignable(DerivedFromRefQualifier&, const DerivedFromRefQualifier&), ""); 141*67e74705SXin Li static_assert(__is_trivially_assignable(DerivedFromRefQualifier&&, const DerivedFromRefQualifier&), ""); 142*67e74705SXin Li static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&, DerivedFromRefQualifier&&), ""); 143*67e74705SXin Li static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&&, DerivedFromRefQualifier&&), ""); 144*67e74705SXin Li 145*67e74705SXin Li struct TemplateAssignNoMove { 146*67e74705SXin Li TemplateAssignNoMove &operator=(const TemplateAssignNoMove &) = default; 147*67e74705SXin Li template<typename T> TemplateAssignNoMove &operator=(T &&); 148*67e74705SXin Li }; 149*67e74705SXin Li static_assert(__is_trivially_assignable(TemplateAssignNoMove, const TemplateAssignNoMove &), ""); 150*67e74705SXin Li static_assert(!__is_trivially_assignable(TemplateAssignNoMove, TemplateAssignNoMove &&), ""); 151*67e74705SXin Li 152*67e74705SXin Li struct UseTemplateAssignNoMove { 153*67e74705SXin Li TemplateAssignNoMove tanm; 154*67e74705SXin Li }; 155*67e74705SXin Li static_assert(__is_trivially_assignable(UseTemplateAssignNoMove, const UseTemplateAssignNoMove &), ""); 156*67e74705SXin Li static_assert(!__is_trivially_assignable(UseTemplateAssignNoMove, UseTemplateAssignNoMove &&), ""); 157*67e74705SXin Li 158*67e74705SXin Li struct TemplateAssignNoMoveSFINAE { 159*67e74705SXin Li TemplateAssignNoMoveSFINAE &operator=(const TemplateAssignNoMoveSFINAE &) = default; 160*67e74705SXin Li template<typename T, typename U = typename T::error> TemplateAssignNoMoveSFINAE &operator=(T &&); 161*67e74705SXin Li }; 162*67e74705SXin Li static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, const TemplateAssignNoMoveSFINAE &), ""); 163*67e74705SXin Li static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, TemplateAssignNoMoveSFINAE &&), ""); 164*67e74705SXin Li 165*67e74705SXin Li struct UseTemplateAssignNoMoveSFINAE { 166*67e74705SXin Li TemplateAssignNoMoveSFINAE tanm; 167*67e74705SXin Li }; 168*67e74705SXin Li static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, const UseTemplateAssignNoMoveSFINAE &), ""); 169*67e74705SXin Li static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, UseTemplateAssignNoMoveSFINAE &&), ""); 170*67e74705SXin Li 171*67e74705SXin Li namespace TrivialityDependsOnImplicitDeletion { 172*67e74705SXin Li struct PrivateMove { 173*67e74705SXin Li PrivateMove &operator=(const PrivateMove &) = default; 174*67e74705SXin Li private: 175*67e74705SXin Li PrivateMove &operator=(PrivateMove &&); 176*67e74705SXin Li friend class Access; 177*67e74705SXin Li }; 178*67e74705SXin Li static_assert(__is_trivially_assignable(PrivateMove, const PrivateMove &), ""); 179*67e74705SXin Li static_assert(!__is_trivially_assignable(PrivateMove, PrivateMove &&), ""); 180*67e74705SXin Li 181*67e74705SXin Li struct NoAccess { 182*67e74705SXin Li PrivateMove pm; 183*67e74705SXin Li // NoAccess's move would be deleted, so is suppressed, 184*67e74705SXin Li // so moves of it use PrivateMove's copy ctor, which is trivial. 185*67e74705SXin Li }; 186*67e74705SXin Li static_assert(__is_trivially_assignable(NoAccess, const NoAccess &), ""); 187*67e74705SXin Li static_assert(__is_trivially_assignable(NoAccess, NoAccess &&), ""); 188*67e74705SXin Li struct TopNoAccess : NoAccess {}; 189*67e74705SXin Li static_assert(__is_trivially_assignable(TopNoAccess, const TopNoAccess &), ""); 190*67e74705SXin Li static_assert(__is_trivially_assignable(TopNoAccess, TopNoAccess &&), ""); 191*67e74705SXin Li 192*67e74705SXin Li struct Access { 193*67e74705SXin Li PrivateMove pm; 194*67e74705SXin Li // NoAccess's move would *not* be deleted, so is *not* suppressed, 195*67e74705SXin Li // so moves of it use PrivateMove's move ctor, which is not trivial. 196*67e74705SXin Li }; 197*67e74705SXin Li static_assert(__is_trivially_assignable(Access, const Access &), ""); 198*67e74705SXin Li static_assert(!__is_trivially_assignable(Access, Access &&), ""); 199*67e74705SXin Li struct TopAccess : Access {}; 200*67e74705SXin Li static_assert(__is_trivially_assignable(TopAccess, const TopAccess &), ""); 201*67e74705SXin Li static_assert(!__is_trivially_assignable(TopAccess, TopAccess &&), ""); 202*67e74705SXin Li } 203