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