309 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base %s2 3// Tests for implicit (non-)declaration of move constructor and4// assignment: p9, p11, p20, p23.5 6// This class, used as a member, allows to distinguish move from copy because7// move operations are no-throw, copy operations aren't.8struct 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 16struct HasCopyConstructor {17 ThrowingCopy tc;18 HasCopyConstructor() noexcept;19 HasCopyConstructor(const HasCopyConstructor &) noexcept(false);20};21 22struct HasCopyAssignment {23 ThrowingCopy tc;24 HasCopyAssignment() noexcept;25 HasCopyAssignment & operator =(const HasCopyAssignment &) noexcept(false);26};27 28struct 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 34struct HasMoveAssignment { // expected-note {{implicit copy constructor}}35 ThrowingCopy tc;36 HasMoveAssignment() noexcept;37 HasMoveAssignment & operator =(HasMoveAssignment &&) noexcept;38};39 40struct HasDestructor {41 ThrowingCopy tc;42 HasDestructor() noexcept;43 ~HasDestructor() noexcept;44};45 46void 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 68struct PrivateMove {69 PrivateMove() noexcept;70 PrivateMove(const PrivateMove &) noexcept(false);71 PrivateMove & operator =(const PrivateMove &) noexcept(false);72private:73 PrivateMove(PrivateMove &&) noexcept;74 PrivateMove & operator =(PrivateMove &&) noexcept;75};76 77struct InheritsPrivateMove : PrivateMove {};78struct ContainsPrivateMove {79 PrivateMove pm;80};81 82struct PrivateDestructor {83 PrivateDestructor() noexcept;84 PrivateDestructor(const PrivateDestructor &) noexcept(false);85 PrivateDestructor(PrivateDestructor &&) noexcept;86private:87 ~PrivateDestructor() noexcept;88};89 90struct InheritsPrivateDestructor : PrivateDestructor {}; // expected-note{{base class 'PrivateDestructor' has an inaccessible destructor}}91struct ContainsPrivateDestructor {92 PrivateDestructor pd; // expected-note{{field 'pd' has an inaccessible destructor}}93};94 95struct NonTrivialCopyOnly {96 NonTrivialCopyOnly() noexcept;97 NonTrivialCopyOnly(const NonTrivialCopyOnly &) noexcept(false);98 NonTrivialCopyOnly & operator =(const NonTrivialCopyOnly &) noexcept(false);99};100 101struct InheritsNonTrivialCopyOnly : NonTrivialCopyOnly {};102struct ContainsNonTrivialCopyOnly {103 NonTrivialCopyOnly ntco;104};105 106struct ContainsConst {107 const int i;108 ContainsConst() noexcept;109 ContainsConst & operator =(ContainsConst &); // expected-note {{not viable}}110};111 112struct ContainsRef {113 int &i;114 ContainsRef() noexcept;115 ContainsRef & operator =(ContainsRef &); // expected-note {{not viable}}116};117 118struct Base {119 Base & operator =(Base &);120};121struct DirectVirtualBase : virtual Base {}; // expected-note {{copy assignment operator) not viable}}122struct IndirectVirtualBase : DirectVirtualBase {}; // expected-note {{copy assignment operator) not viable}}123 124void 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 157struct ContainsRValueRef {158 int&& ri;159 ContainsRValueRef() noexcept;160};161 162void test_contains_rref() {163 (ContainsRValueRef(ContainsRValueRef()));164}165 166 167namespace 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 no194 // 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 longer205 // inhibits the declaration of a move assignment (even though it might206 // 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)); // ok213 t = static_cast<T&&>(t); // ok214 }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, copies236 template void test(MoveOnly); // ok, moves237 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 mo242 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 303namespace PR12625 {304 struct X; // expected-note {{forward decl}}305 struct Y {306 X x; // expected-error {{incomplete}}307 } y = Y();308}309