1 | // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base %s |
2 | |
3 | // Tests for implicit (non-)declaration of move constructor and |
4 | // assignment: p9, p11, p20, p23. |
5 | |
6 | // This class, used as a member, allows to distinguish move from copy because |
7 | // move operations are no-throw, copy operations aren't. |
8 | struct ThrowingCopy { |
9 | ThrowingCopy() noexcept; |
10 | ThrowingCopy(ThrowingCopy &&) noexcept; |
11 | ThrowingCopy(const ThrowingCopy &) noexcept(false); |
12 | ThrowingCopy & operator =(ThrowingCopy &&) noexcept; |
13 | ThrowingCopy & operator =(const ThrowingCopy &) noexcept(false); |
14 | }; |
15 | |
16 | struct HasCopyConstructor { |
17 | ThrowingCopy tc; |
18 | HasCopyConstructor() noexcept; |
19 | HasCopyConstructor(const HasCopyConstructor &) noexcept(false); |
20 | }; |
21 | |
22 | struct HasCopyAssignment { |
23 | ThrowingCopy tc; |
24 | HasCopyAssignment() noexcept; |
25 | HasCopyAssignment & operator =(const HasCopyAssignment &) noexcept(false); |
26 | }; |
27 | |
28 | struct HasMoveConstructor { |
29 | ThrowingCopy tc; |
30 | HasMoveConstructor() noexcept; |
31 | HasMoveConstructor(HasMoveConstructor &&) noexcept; // expected-note {{copy assignment operator is implicitly deleted because 'HasMoveConstructor' has a user-declared move constructor}} |
32 | }; |
33 | |
34 | struct HasMoveAssignment { // expected-note {{implicit copy constructor}} |
35 | ThrowingCopy tc; |
36 | HasMoveAssignment() noexcept; |
37 | HasMoveAssignment & operator =(HasMoveAssignment &&) noexcept; |
38 | }; |
39 | |
40 | struct HasDestructor { |
41 | ThrowingCopy tc; |
42 | HasDestructor() noexcept; |
43 | ~HasDestructor() noexcept; |
44 | }; |
45 | |
46 | void test_basic_exclusion() { |
47 | static_assert(!noexcept(HasCopyConstructor((HasCopyConstructor()))), ""); |
48 | HasCopyConstructor hcc; |
49 | static_assert(!noexcept(hcc = HasCopyConstructor()), ""); |
50 | |
51 | static_assert(!noexcept(HasCopyAssignment((HasCopyAssignment()))), ""); |
52 | HasCopyAssignment hca; |
53 | static_assert(!noexcept(hca = HasCopyAssignment()), ""); |
54 | |
55 | static_assert(noexcept(HasMoveConstructor((HasMoveConstructor()))), ""); |
56 | HasMoveConstructor hmc; |
57 | hmc = HasMoveConstructor(); // expected-error {{object of type 'HasMoveConstructor' cannot be assigned because its copy assignment operator is implicitly deleted}} |
58 | |
59 | (HasMoveAssignment(HasMoveAssignment())); // expected-error {{uses deleted function}} |
60 | HasMoveAssignment hma; |
61 | static_assert(noexcept(hma = HasMoveAssignment()), ""); |
62 | |
63 | static_assert(!noexcept(HasDestructor((HasDestructor()))), ""); |
64 | HasDestructor hd; |
65 | static_assert(!noexcept(hd = HasDestructor()), ""); |
66 | } |
67 | |
68 | struct PrivateMove { |
69 | PrivateMove() noexcept; |
70 | PrivateMove(const PrivateMove &) noexcept(false); |
71 | PrivateMove & operator =(const PrivateMove &) noexcept(false); |
72 | private: |
73 | PrivateMove(PrivateMove &&) noexcept; |
74 | PrivateMove & operator =(PrivateMove &&) noexcept; |
75 | }; |
76 | |
77 | struct InheritsPrivateMove : PrivateMove {}; |
78 | struct ContainsPrivateMove { |
79 | PrivateMove pm; |
80 | }; |
81 | |
82 | struct PrivateDestructor { |
83 | PrivateDestructor() noexcept; |
84 | PrivateDestructor(const PrivateDestructor &) noexcept(false); |
85 | PrivateDestructor(PrivateDestructor &&) noexcept; |
86 | private: |
87 | ~PrivateDestructor() noexcept; |
88 | }; |
89 | |
90 | struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{base class 'PrivateDestructor' has an inaccessible destructor}} |
91 | struct ContainsPrivateDestructor { |
92 | PrivateDestructor pd; // expected-note{{field 'pd' has an inaccessible destructor}} |
93 | }; |
94 | |
95 | struct NonTrivialCopyOnly { |
96 | NonTrivialCopyOnly() noexcept; |
97 | NonTrivialCopyOnly(const NonTrivialCopyOnly &) noexcept(false); |
98 | NonTrivialCopyOnly & operator =(const NonTrivialCopyOnly &) noexcept(false); |
99 | }; |
100 | |
101 | struct InheritsNonTrivialCopyOnly : NonTrivialCopyOnly {}; |
102 | struct ContainsNonTrivialCopyOnly { |
103 | NonTrivialCopyOnly ntco; |
104 | }; |
105 | |
106 | struct ContainsConst { |
107 | const int i; |
108 | ContainsConst() noexcept; |
109 | ContainsConst & operator =(ContainsConst &); // expected-note {{not viable}} |
110 | }; |
111 | |
112 | struct ContainsRef { |
113 | int &i; |
114 | ContainsRef() noexcept; |
115 | ContainsRef & operator =(ContainsRef &); // expected-note {{not viable}} |
116 | }; |
117 | |
118 | struct Base { |
119 | Base & operator =(Base &); |
120 | }; |
121 | struct DirectVirtualBase : virtual Base {}; // expected-note {{copy assignment operator) not viable}} |
122 | struct IndirectVirtualBase : DirectVirtualBase {}; // expected-note {{copy assignment operator) not viable}} |
123 | |
124 | void test_deletion_exclusion() { |
125 | // FIXME: How to test the union thing? |
126 | |
127 | static_assert(!noexcept(InheritsPrivateMove(InheritsPrivateMove())), ""); |
128 | static_assert(!noexcept(ContainsPrivateMove(ContainsPrivateMove())), ""); |
129 | InheritsPrivateMove ipm; |
130 | static_assert(!noexcept(ipm = InheritsPrivateMove()), ""); |
131 | ContainsPrivateMove cpm; |
132 | static_assert(!noexcept(cpm = ContainsPrivateMove()), ""); |
133 | |
134 | (InheritsPrivateDestructor(InheritsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}} |
135 | (ContainsPrivateDestructor(ContainsPrivateDestructor())); // expected-error {{call to implicitly-deleted default constructor}} |
136 | |
137 | static_assert(!noexcept(InheritsNonTrivialCopyOnly(InheritsNonTrivialCopyOnly())), ""); |
138 | static_assert(!noexcept(ContainsNonTrivialCopyOnly(ContainsNonTrivialCopyOnly())), ""); |
139 | InheritsNonTrivialCopyOnly intco; |
140 | static_assert(!noexcept(intco = InheritsNonTrivialCopyOnly()), ""); |
141 | ContainsNonTrivialCopyOnly cntco; |
142 | static_assert(!noexcept(cntco = ContainsNonTrivialCopyOnly()), ""); |
143 | |
144 | ContainsConst cc; |
145 | cc = ContainsConst(); // expected-error {{no viable}} |
146 | |
147 | ContainsRef cr; |
148 | cr = ContainsRef(); // expected-error {{no viable}} |
149 | |
150 | DirectVirtualBase dvb; |
151 | dvb = DirectVirtualBase(); // expected-error {{no viable}} |
152 | |
153 | IndirectVirtualBase ivb; |
154 | ivb = IndirectVirtualBase(); // expected-error {{no viable}} |
155 | } |
156 | |
157 | struct ContainsRValueRef { |
158 | int&& ri; |
159 | ContainsRValueRef() noexcept; |
160 | }; |
161 | |
162 | void test_contains_rref() { |
163 | (ContainsRValueRef(ContainsRValueRef())); |
164 | } |
165 | |
166 | |
167 | namespace DR1402 { |
168 | struct NonTrivialCopyCtor { |
169 | NonTrivialCopyCtor(const NonTrivialCopyCtor &); |
170 | }; |
171 | struct NonTrivialCopyAssign { |
172 | NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &); |
173 | }; |
174 | |
175 | struct NonTrivialCopyCtorVBase : virtual NonTrivialCopyCtor { |
176 | NonTrivialCopyCtorVBase(NonTrivialCopyCtorVBase &&); |
177 | NonTrivialCopyCtorVBase &operator=(NonTrivialCopyCtorVBase &&) = default; |
178 | }; |
179 | struct NonTrivialCopyAssignVBase : virtual NonTrivialCopyAssign { |
180 | NonTrivialCopyAssignVBase(NonTrivialCopyAssignVBase &&); |
181 | NonTrivialCopyAssignVBase &operator=(NonTrivialCopyAssignVBase &&) = default; |
182 | }; |
183 | |
184 | struct NonTrivialMoveAssign { |
185 | NonTrivialMoveAssign(NonTrivialMoveAssign&&); |
186 | NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&); |
187 | }; |
188 | struct NonTrivialMoveAssignVBase : virtual NonTrivialMoveAssign { |
189 | NonTrivialMoveAssignVBase(NonTrivialMoveAssignVBase &&); |
190 | NonTrivialMoveAssignVBase &operator=(NonTrivialMoveAssignVBase &&) = default; |
191 | }; |
192 | |
193 | // DR1402: A non-movable, non-trivially-copyable class type as a subobject no |
194 | // longer inhibits the declaration of a move operation. |
195 | struct NoMove1 { NonTrivialCopyCtor ntcc; }; |
196 | struct NoMove2 { NonTrivialCopyAssign ntcc; }; |
197 | struct NoMove3 : NonTrivialCopyCtor {}; |
198 | struct NoMove4 : NonTrivialCopyAssign {}; |
199 | struct NoMove5 : virtual NonTrivialCopyCtor {}; |
200 | struct NoMove6 : virtual NonTrivialCopyAssign {}; |
201 | struct NoMove7 : NonTrivialCopyCtorVBase {}; |
202 | struct NoMove8 : NonTrivialCopyAssignVBase {}; |
203 | |
204 | // DR1402: A non-trivially-move-assignable virtual base class no longer |
205 | // inhibits the declaration of a move assignment (even though it might |
206 | // move-assign the base class multiple times). |
207 | struct NoMove9 : NonTrivialMoveAssign {}; |
208 | struct NoMove10 : virtual NonTrivialMoveAssign {}; |
209 | struct NoMove11 : NonTrivialMoveAssignVBase {}; |
210 | |
211 | template<typename T> void test(T t) { |
212 | (void)T(static_cast<T&&>(t)); // ok |
213 | t = static_cast<T&&>(t); // ok |
214 | } |
215 | template void test(NoMove1); |
216 | template void test(NoMove2); |
217 | template void test(NoMove3); |
218 | template void test(NoMove4); |
219 | template void test(NoMove5); |
220 | template void test(NoMove6); |
221 | template void test(NoMove7); |
222 | template void test(NoMove8); |
223 | template void test(NoMove9); |
224 | template void test(NoMove10); |
225 | template void test(NoMove11); |
226 | |
227 | struct CopyOnly { |
228 | CopyOnly(const CopyOnly&); |
229 | CopyOnly &operator=(const CopyOnly&); |
230 | }; |
231 | struct MoveOnly { |
232 | MoveOnly(MoveOnly&&); // expected-note {{user-declared move}} |
233 | MoveOnly &operator=(MoveOnly&&); |
234 | }; |
235 | template void test(CopyOnly); // ok, copies |
236 | template void test(MoveOnly); // ok, moves |
237 | struct CopyAndMove { // expected-note {{implicitly deleted}} |
238 | CopyOnly co; |
239 | MoveOnly mo; // expected-note {{deleted copy}} |
240 | }; |
241 | template void test(CopyAndMove); // ok, copies co, moves mo |
242 | void test2(CopyAndMove cm) { |
243 | (void)CopyAndMove(cm); // expected-error {{deleted}} |
244 | cm = cm; // expected-error {{deleted}} |
245 | } |
246 | |
247 | namespace VbaseMove { |
248 | struct A {}; |
249 | struct B { B &operator=(B&&); }; |
250 | struct C { C &operator=(const C&); }; |
251 | struct D { B b; }; |
252 | |
253 | template<typename T, unsigned I, bool NonTrivialMove = false> |
254 | struct E : virtual T {}; |
255 | |
256 | template<typename T, unsigned I> |
257 | struct E<T, I, true> : virtual T { E &operator=(E&&); }; |
258 | |
259 | template<typename T> |
260 | struct F : |
261 | E<T, 0>, // expected-note-re 2{{'{{[BD]}}' is a virtual base class of base class 'E<}} |
262 | E<T, 1> {}; // expected-note-re 2{{'{{[BD]}}' is a virtual base class of base class 'E<}} |
263 | |
264 | template<typename T> |
265 | struct G : E<T, 0, true>, E<T, 0> {}; |
266 | |
267 | template<typename T> |
268 | struct H : E<T, 0, true>, E<T, 1, true> {}; |
269 | |
270 | template<typename T> |
271 | struct I : E<T, 0>, T {}; |
272 | |
273 | template<typename T> |
274 | struct J : |
275 | E<T, 0>, // expected-note-re 2{{'{{[BD]}}' is a virtual base class of base class 'E<}} |
276 | virtual T {}; // expected-note-re 2{{virtual base class '{{[BD]}}' declared here}} |
277 | |
278 | template<typename T> void move(T t) { t = static_cast<T&&>(t); } |
279 | // expected-warning-re@-1 4{{defaulted move assignment operator of {{.*}} will move assign virtual base class '{{[BD]}}' multiple times}} |
280 | template void move(F<A>); |
281 | template void move(F<B>); // expected-note {{in instantiation of}} |
282 | template void move(F<C>); |
283 | template void move(F<D>); // expected-note {{in instantiation of}} |
284 | template void move(G<A>); |
285 | template void move(G<B>); |
286 | template void move(G<C>); |
287 | template void move(G<D>); |
288 | template void move(H<A>); |
289 | template void move(H<B>); |
290 | template void move(H<C>); |
291 | template void move(H<D>); |
292 | template void move(I<A>); |
293 | template void move(I<B>); |
294 | template void move(I<C>); |
295 | template void move(I<D>); |
296 | template void move(J<A>); |
297 | template void move(J<B>); // expected-note {{in instantiation of}} |
298 | template void move(J<C>); |
299 | template void move(J<D>); // expected-note {{in instantiation of}} |
300 | } |
301 | } |
302 | |
303 | namespace PR12625 { |
304 | struct X; // expected-note {{forward decl}} |
305 | struct Y { |
306 | X x; // expected-error {{incomplete}} |
307 | } y = Y(); |
308 | } |
309 | |