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 
test_basic_exclusion()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 
test_deletion_exclusion()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 
test_contains_rref()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 
test(T t)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
test2(CopyAndMove cm)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 
move(T t)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