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