1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %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