p25-0x.cpp revision ac71351acdefc9de0c770c1d717e621ac9e684bf
1// RUN: %clang_cc1 -std=c++11 -verify %s 2 3template<typename T, bool B> struct trivially_assignable_check { 4 static_assert(B == __has_trivial_assign(T), ""); 5 static_assert(B == __is_trivially_assignable(T&, T), ""); 6 static_assert(B == __is_trivially_assignable(T&, const T &), ""); 7 static_assert(B == __is_trivially_assignable(T&, T &&), ""); 8 static_assert(B == __is_trivially_assignable(T&&, T), ""); 9 static_assert(B == __is_trivially_assignable(T&&, const T &), ""); 10 static_assert(B == __is_trivially_assignable(T&&, T &&), ""); 11 typedef void type; 12}; 13template<typename T> using trivially_assignable = 14 typename trivially_assignable_check<T, true>::type; 15template<typename T> using not_trivially_assignable = 16 typename trivially_assignable_check<T, false>::type; 17 18struct Trivial {}; 19using _ = trivially_assignable<Trivial>; 20 21// A copy/move assignment operator for class X is trivial if it is not user-provided, 22struct UserProvided { 23 UserProvided &operator=(const UserProvided &); 24}; 25using _ = not_trivially_assignable<UserProvided>; 26 27// its declared parameter type is the same as if it had been implicitly 28// declared, 29struct NonConstCopy { 30 NonConstCopy &operator=(NonConstCopy &) = default; 31}; 32using _ = not_trivially_assignable<NonConstCopy>; 33 34// class X has no virtual functions 35struct VFn { 36 virtual void f(); 37}; 38using _ = not_trivially_assignable<VFn>; 39 40// and no virtual base classes 41struct VBase : virtual Trivial {}; 42using _ = not_trivially_assignable<VBase>; 43 44// and the assignment operator selected to copy/move each [direct subobject] is trivial 45struct TemplateCtor { 46 template<typename T> TemplateCtor operator=(T &); 47}; 48using _ = trivially_assignable<TemplateCtor>; 49struct TemplateCtorMember { 50 TemplateCtor tc; 51}; 52using _ = trivially_assignable<TemplateCtorMember>; 53struct MutableTemplateCtorMember { 54 mutable TemplateCtor mtc; 55}; 56// FIXME: This is wrong! The "trivial" copy constructor calls the templated 57// constructor for the mutable member. 58static_assert(!__is_trivially_assignable(MutableTemplateCtorMember, const MutableTemplateCtorMember &), ""); // expected-error {{}} 59static_assert(__is_trivially_assignable(MutableTemplateCtorMember, MutableTemplateCtorMember &&), ""); 60 61// Both trivial and non-trivial special members. 62struct TNT { 63 TNT &operator=(const TNT &) = default; // trivial 64 TNT &operator=(TNT &); // non-trivial 65 66 TNT &operator=(TNT &&) = default; // trivial 67 TNT &operator=(const TNT &&); // non-trivial 68}; 69 70static_assert(!__has_trivial_assign(TNT), "lie deliberately for gcc compatibility"); 71static_assert(__is_trivially_assignable(TNT, TNT), ""); 72static_assert(!__is_trivially_assignable(TNT, TNT &), ""); 73static_assert(__is_trivially_assignable(TNT, const TNT &), ""); 74static_assert(!__is_trivially_assignable(TNT, volatile TNT &), ""); 75static_assert(__is_trivially_assignable(TNT, TNT &&), ""); 76static_assert(!__is_trivially_assignable(TNT, const TNT &&), ""); 77static_assert(!__is_trivially_assignable(TNT, volatile TNT &&), ""); 78 79// This has only trivial special members. 80struct DerivedFromTNT : TNT {}; 81 82static_assert(__has_trivial_assign(DerivedFromTNT), ""); 83static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT), ""); 84static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &), ""); 85static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &), ""); 86static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &), ""); 87static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &&), ""); 88static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &&), ""); 89static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &&), ""); 90 91// This has only trivial special members. 92struct TNTMember { 93 TNT tnt; 94}; 95 96static_assert(__has_trivial_assign(TNTMember), ""); 97static_assert(__is_trivially_assignable(TNTMember, TNTMember), ""); 98static_assert(__is_trivially_assignable(TNTMember, TNTMember &), ""); 99static_assert(__is_trivially_assignable(TNTMember, const TNTMember &), ""); 100static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &), ""); 101static_assert(__is_trivially_assignable(TNTMember, TNTMember &&), ""); 102static_assert(__is_trivially_assignable(TNTMember, const TNTMember &&), ""); 103static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &&), ""); 104 105struct NCCTNT : NonConstCopy, TNT {}; 106 107static_assert(!__has_trivial_assign(NCCTNT), ""); 108static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT), ""); 109static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &), ""); 110static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &), ""); 111static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &), ""); 112static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &&), ""); 113static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &&), ""); 114static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &&), ""); 115 116struct MultipleTrivial { 117 // All four of these are trivial. 118 MultipleTrivial &operator=(const MultipleTrivial &) & = default; 119 MultipleTrivial &operator=(const MultipleTrivial &) && = default; 120 MultipleTrivial &operator=(MultipleTrivial &&) & = default; 121 MultipleTrivial &operator=(MultipleTrivial &&) && = default; 122}; 123 124using _ = trivially_assignable<MultipleTrivial>; 125 126struct RefQualifier { 127 RefQualifier &operator=(const RefQualifier &) & = default; 128 RefQualifier &operator=(const RefQualifier &) &&; 129 RefQualifier &operator=(RefQualifier &&) &; 130 RefQualifier &operator=(RefQualifier &&) && = default; 131}; 132struct DerivedFromRefQualifier : RefQualifier { 133 // Both of these call the trivial copy operation. 134 DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) & = default; 135 DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) && = default; 136 // Both of these call the non-trivial move operation. 137 DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) & = default; 138 DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) && = default; 139}; 140static_assert(__is_trivially_assignable(DerivedFromRefQualifier&, const DerivedFromRefQualifier&), ""); 141static_assert(__is_trivially_assignable(DerivedFromRefQualifier&&, const DerivedFromRefQualifier&), ""); 142static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&, DerivedFromRefQualifier&&), ""); 143static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&&, DerivedFromRefQualifier&&), ""); 144