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