diff options
Diffstat (limited to 'test/CXX/special/class.copy/implicit-move.cpp')
-rw-r--r-- | test/CXX/special/class.copy/implicit-move.cpp | 147 |
1 files changed, 106 insertions, 41 deletions
diff --git a/test/CXX/special/class.copy/implicit-move.cpp b/test/CXX/special/class.copy/implicit-move.cpp index 3337412..23ecf2e 100644 --- a/test/CXX/special/class.copy/implicit-move.cpp +++ b/test/CXX/special/class.copy/implicit-move.cpp @@ -190,49 +190,114 @@ namespace DR1402 { NonTrivialMoveAssignVBase &operator=(NonTrivialMoveAssignVBase &&) = default; }; - // A non-movable, non-trivially-copyable class type as a subobject inhibits - // the declaration of a move operation. - struct NoMove1 { NonTrivialCopyCtor ntcc; }; // expected-note 2{{'const DR1402::NoMove1 &'}} - struct NoMove2 { NonTrivialCopyAssign ntcc; }; // expected-note 2{{'const DR1402::NoMove2 &'}} - struct NoMove3 : NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove3 &'}} - struct NoMove4 : NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove4 &'}} - struct NoMove5 : virtual NonTrivialCopyCtor {}; // expected-note 2{{'const DR1402::NoMove5 &'}} - struct NoMove6 : virtual NonTrivialCopyAssign {}; // expected-note 2{{'const DR1402::NoMove6 &'}} - struct NoMove7 : NonTrivialCopyCtorVBase {}; // expected-note 2{{'const DR1402::NoMove7 &'}} - struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note 2{{'const DR1402::NoMove8 &'}} - - // A non-trivially-move-assignable virtual base class inhibits the declaration - // of a move assignment (which might move-assign the base class multiple - // times). + // DR1402: A non-movable, non-trivially-copyable class type as a subobject no + // longer inhibits the declaration of a move operation. + struct NoMove1 { NonTrivialCopyCtor ntcc; }; + struct NoMove2 { NonTrivialCopyAssign ntcc; }; + struct NoMove3 : NonTrivialCopyCtor {}; + struct NoMove4 : NonTrivialCopyAssign {}; + struct NoMove5 : virtual NonTrivialCopyCtor {}; + struct NoMove6 : virtual NonTrivialCopyAssign {}; + struct NoMove7 : NonTrivialCopyCtorVBase {}; + struct NoMove8 : NonTrivialCopyAssignVBase {}; + + // DR1402: A non-trivially-move-assignable virtual base class no longer + // inhibits the declaration of a move assignment (even though it might + // move-assign the base class multiple times). struct NoMove9 : NonTrivialMoveAssign {}; - struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note {{'const DR1402::NoMove10 &'}} - struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'const DR1402::NoMove11 &'}} - - struct Test { - friend NoMove1::NoMove1(NoMove1 &&); // expected-error {{no matching function}} - friend NoMove2::NoMove2(NoMove2 &&); // expected-error {{no matching function}} - friend NoMove3::NoMove3(NoMove3 &&); // expected-error {{no matching function}} - friend NoMove4::NoMove4(NoMove4 &&); // expected-error {{no matching function}} - friend NoMove5::NoMove5(NoMove5 &&); // expected-error {{no matching function}} - friend NoMove6::NoMove6(NoMove6 &&); // expected-error {{no matching function}} - friend NoMove7::NoMove7(NoMove7 &&); // expected-error {{no matching function}} - friend NoMove8::NoMove8(NoMove8 &&); // expected-error {{no matching function}} - friend NoMove9::NoMove9(NoMove9 &&); - friend NoMove10::NoMove10(NoMove10 &&); - friend NoMove11::NoMove11(NoMove11 &&); - - friend NoMove1 &NoMove1::operator=(NoMove1 &&); // expected-error {{no matching function}} - friend NoMove2 &NoMove2::operator=(NoMove2 &&); // expected-error {{no matching function}} - friend NoMove3 &NoMove3::operator=(NoMove3 &&); // expected-error {{no matching function}} - friend NoMove4 &NoMove4::operator=(NoMove4 &&); // expected-error {{no matching function}} - friend NoMove5 &NoMove5::operator=(NoMove5 &&); // expected-error {{no matching function}} - friend NoMove6 &NoMove6::operator=(NoMove6 &&); // expected-error {{no matching function}} - friend NoMove7 &NoMove7::operator=(NoMove7 &&); // expected-error {{no matching function}} - friend NoMove8 &NoMove8::operator=(NoMove8 &&); // expected-error {{no matching function}} - friend NoMove9 &NoMove9::operator=(NoMove9 &&); - friend NoMove10 &NoMove10::operator=(NoMove10 &&); // expected-error {{no matching function}} - friend NoMove11 &NoMove11::operator=(NoMove11 &&); // expected-error {{no matching function}} + struct NoMove10 : virtual NonTrivialMoveAssign {}; + struct NoMove11 : NonTrivialMoveAssignVBase {}; + + template<typename T> void test(T t) { + (void)T(static_cast<T&&>(t)); // ok + t = static_cast<T&&>(t); // ok + } + template void test(NoMove1); + template void test(NoMove2); + template void test(NoMove3); + template void test(NoMove4); + template void test(NoMove5); + template void test(NoMove6); + template void test(NoMove7); + template void test(NoMove8); + template void test(NoMove9); + template void test(NoMove10); + template void test(NoMove11); + + struct CopyOnly { + CopyOnly(const CopyOnly&); + CopyOnly &operator=(const CopyOnly&); }; + struct MoveOnly { + MoveOnly(MoveOnly&&); // expected-note {{user-declared move}} + MoveOnly &operator=(MoveOnly&&); + }; + template void test(CopyOnly); // ok, copies + template void test(MoveOnly); // ok, moves + struct CopyAndMove { // expected-note {{implicitly deleted}} + CopyOnly co; + MoveOnly mo; // expected-note {{deleted copy}} + }; + template void test(CopyAndMove); // ok, copies co, moves mo + void test2(CopyAndMove cm) { + (void)CopyAndMove(cm); // expected-error {{deleted}} + cm = cm; // expected-error {{deleted}} + } + + namespace VbaseMove { + struct A {}; + struct B { B &operator=(B&&); }; + struct C { C &operator=(const C&); }; + struct D { B b; }; + + template<typename T, unsigned I, bool NonTrivialMove = false> + struct E : virtual T {}; + + template<typename T, unsigned I> + struct E<T, I, true> : virtual T { E &operator=(E&&); }; + + template<typename T> + struct F : + E<T, 0>, // expected-note-re 2{{'[BD]' is a virtual base class of base class 'E<}} + E<T, 1> {}; // expected-note-re 2{{'[BD]' is a virtual base class of base class 'E<}} + + template<typename T> + struct G : E<T, 0, true>, E<T, 0> {}; + + template<typename T> + struct H : E<T, 0, true>, E<T, 1, true> {}; + + template<typename T> + struct I : E<T, 0>, T {}; + + template<typename T> + struct J : + E<T, 0>, // expected-note-re 2{{'[BD]' is a virtual base class of base class 'E<}} + virtual T {}; // expected-note-re 2{{virtual base class '[BD]' declared here}} + + template<typename T> void move(T t) { t = static_cast<T&&>(t); } + // expected-warning-re@-1 4{{defaulted move assignment operator of .* will move assign virtual base class '[BD]' multiple times}} + template void move(F<A>); + template void move(F<B>); // expected-note {{in instantiation of}} + template void move(F<C>); + template void move(F<D>); // expected-note {{in instantiation of}} + template void move(G<A>); + template void move(G<B>); + template void move(G<C>); + template void move(G<D>); + template void move(H<A>); + template void move(H<B>); + template void move(H<C>); + template void move(H<D>); + template void move(I<A>); + template void move(I<B>); + template void move(I<C>); + template void move(I<D>); + template void move(J<A>); + template void move(J<B>); // expected-note {{in instantiation of}} + template void move(J<C>); + template void move(J<D>); // expected-note {{in instantiation of}} + } } namespace PR12625 { |