1// RUN: %clang_cc1 -std=c++11 -verify %s 2 3// expected-no-diagnostics 4 5template<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}; 12template<typename T> using trivially_copyable = 13 typename trivially_copyable_check<T, true>::type; 14template<typename T> using not_trivially_copyable = 15 typename trivially_copyable_check<T, false>::type; 16 17struct Trivial {}; 18using _ = trivially_copyable<Trivial>; 19 20// A copy/move constructor for class X is trivial if it is not user-provided, 21struct UserProvided { 22 UserProvided(const UserProvided &); 23}; 24using _ = not_trivially_copyable<UserProvided>; 25 26// its declared parameter type is the same as if it had been implicitly 27// declared, 28struct NonConstCopy { 29 NonConstCopy(NonConstCopy &) = default; 30}; 31using _ = not_trivially_copyable<NonConstCopy>; 32 33// class X has no virtual functions 34struct VFn { 35 virtual void f(); 36}; 37using _ = not_trivially_copyable<VFn>; 38 39// and no virtual base classes 40struct VBase : virtual Trivial {}; 41using _ = not_trivially_copyable<VBase>; 42 43// and the constructor selected to copy/move each [direct subobject] is trivial 44struct TemplateCtor { 45 template<typename T> TemplateCtor(T &); 46}; 47using _ = trivially_copyable<TemplateCtor>; 48struct TemplateCtorMember { 49 TemplateCtor tc; 50}; 51using _ = trivially_copyable<TemplateCtorMember>; 52 53// We can select a non-trivial copy ctor even if there is a trivial one. 54struct MutableTemplateCtorMember { 55 mutable TemplateCtor mtc; 56}; 57static_assert(!__is_trivially_constructible(MutableTemplateCtorMember, const MutableTemplateCtorMember &), ""); 58static_assert(__is_trivially_constructible(MutableTemplateCtorMember, MutableTemplateCtorMember &&), ""); 59struct MutableTemplateCtorMember2 { 60 MutableTemplateCtorMember2(const MutableTemplateCtorMember2 &) = default; 61 MutableTemplateCtorMember2(MutableTemplateCtorMember2 &&) = default; 62 mutable TemplateCtor mtc; 63}; 64static_assert(!__is_trivially_constructible(MutableTemplateCtorMember2, const MutableTemplateCtorMember2 &), ""); 65static_assert(__is_trivially_constructible(MutableTemplateCtorMember2, MutableTemplateCtorMember2 &&), ""); 66 67// Both trivial and non-trivial special members. 68struct 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 76static_assert(!__has_trivial_copy(TNT), "lie deliberately for gcc compatibility"); 77static_assert(__is_trivially_constructible(TNT, TNT), ""); 78static_assert(!__is_trivially_constructible(TNT, TNT &), ""); 79static_assert(__is_trivially_constructible(TNT, const TNT &), ""); 80static_assert(!__is_trivially_constructible(TNT, volatile TNT &), ""); 81static_assert(__is_trivially_constructible(TNT, TNT &&), ""); 82static_assert(!__is_trivially_constructible(TNT, const TNT &&), ""); 83static_assert(!__is_trivially_constructible(TNT, volatile TNT &&), ""); 84 85// This has only trivial special members. 86struct DerivedFromTNT : TNT {}; 87 88static_assert(__has_trivial_copy(DerivedFromTNT), ""); 89static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT), ""); 90static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &), ""); 91static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &), ""); 92static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &), ""); 93static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &&), ""); 94static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &&), ""); 95static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &&), ""); 96 97// This has only trivial special members. 98struct TNTMember { 99 TNT tnt; 100}; 101 102static_assert(__has_trivial_copy(TNTMember), ""); 103static_assert(__is_trivially_constructible(TNTMember, TNTMember), ""); 104static_assert(__is_trivially_constructible(TNTMember, TNTMember &), ""); 105static_assert(__is_trivially_constructible(TNTMember, const TNTMember &), ""); 106static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &), ""); 107static_assert(__is_trivially_constructible(TNTMember, TNTMember &&), ""); 108static_assert(__is_trivially_constructible(TNTMember, const TNTMember &&), ""); 109static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &&), ""); 110 111struct NCCTNT : NonConstCopy, TNT {}; 112 113static_assert(!__has_trivial_copy(NCCTNT), ""); 114static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT), ""); 115static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &), ""); 116static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &), ""); 117static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &), ""); 118static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &&), ""); 119static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &&), ""); 120static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &&), ""); 121 122struct TemplateCtorNoMove { 123 TemplateCtorNoMove(const TemplateCtorNoMove &) = default; 124 template<typename T> TemplateCtorNoMove(T &&); 125}; 126static_assert(__is_trivially_constructible(TemplateCtorNoMove, const TemplateCtorNoMove &), ""); 127static_assert(!__is_trivially_constructible(TemplateCtorNoMove, TemplateCtorNoMove &&), ""); 128 129struct UseTemplateCtorNoMove { 130 TemplateCtorNoMove tcnm; 131}; 132static_assert(__is_trivially_constructible(UseTemplateCtorNoMove, const UseTemplateCtorNoMove &), ""); 133static_assert(!__is_trivially_constructible(UseTemplateCtorNoMove, UseTemplateCtorNoMove &&), ""); 134 135struct TemplateCtorNoMoveSFINAE { 136 TemplateCtorNoMoveSFINAE(const TemplateCtorNoMoveSFINAE &) = default; 137 template<typename T, typename U = typename T::error> TemplateCtorNoMoveSFINAE(T &&); 138}; 139static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, const TemplateCtorNoMoveSFINAE &), ""); 140static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, TemplateCtorNoMoveSFINAE &&), ""); 141 142struct UseTemplateCtorNoMoveSFINAE { 143 TemplateCtorNoMoveSFINAE tcnm; 144}; 145static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, const UseTemplateCtorNoMoveSFINAE &), ""); 146static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, UseTemplateCtorNoMoveSFINAE &&), ""); 147 148namespace 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 is deleted, so moves of it use PrivateMove's copy ctor, 161 // 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 181namespace 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