1 | // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-defaulted-function-deleted |
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 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 | |
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 | |