summaryrefslogtreecommitdiffstats
path: root/test/CXX
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-02 18:40:40 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-02 18:40:40 +0000
commit1c931be1873f8c20cdcb5060c84570cd3359aa02 (patch)
tree886c500aa195ae79f93bda1ccc8dceeac6321190 /test/CXX
parent582b395ea4d5dfe353e2132a470d39efe2f84a54 (diff)
Implement DR1402: if a field or base class is not movable, the derived class's
move constructor/move assignment operator are not declared, rather than being defined as deleted, so move operations on the derived class fall back to copying rather than moving. If a move operation on the derived class is explicitly defaulted, the unmovable subobject will be copied instead of being moved. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153883 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CXX')
-rw-r--r--test/CXX/special/class.copy/implicit-move.cpp72
-rw-r--r--test/CXX/special/class.copy/p11.0x.move.cpp29
2 files changed, 100 insertions, 1 deletions
diff --git a/test/CXX/special/class.copy/implicit-move.cpp b/test/CXX/special/class.copy/implicit-move.cpp
index 9ff6f48fad..9cb4215cd0 100644
--- a/test/CXX/special/class.copy/implicit-move.cpp
+++ b/test/CXX/special/class.copy/implicit-move.cpp
@@ -162,3 +162,75 @@ struct ContainsRValueRef {
void test_contains_rref() {
(ContainsRValueRef(ContainsRValueRef()));
}
+
+
+namespace DR1402 {
+ struct NonTrivialCopyCtor {
+ NonTrivialCopyCtor(const NonTrivialCopyCtor &);
+ };
+ struct NonTrivialCopyAssign {
+ NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &);
+ };
+
+ struct NonTrivialCopyCtorVBase : virtual NonTrivialCopyCtor {
+ NonTrivialCopyCtorVBase(NonTrivialCopyCtorVBase &&);
+ NonTrivialCopyCtorVBase &operator=(NonTrivialCopyCtorVBase &&) = default;
+ };
+ struct NonTrivialCopyAssignVBase : virtual NonTrivialCopyAssign {
+ NonTrivialCopyAssignVBase(NonTrivialCopyAssignVBase &&);
+ NonTrivialCopyAssignVBase &operator=(NonTrivialCopyAssignVBase &&) = default;
+ };
+
+ struct NonTrivialMoveAssign {
+ NonTrivialMoveAssign(NonTrivialMoveAssign&&);
+ NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&);
+ };
+ struct NonTrivialMoveAssignVBase : virtual NonTrivialMoveAssign {
+ NonTrivialMoveAssignVBase(NonTrivialMoveAssignVBase &&);
+ 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{{'DR1402::NoMove7 &'}}
+ struct NoMove8 : NonTrivialCopyAssignVBase {}; // expected-note 2{{'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).
+ struct NoMove9 : NonTrivialMoveAssign {};
+ struct NoMove10 : virtual NonTrivialMoveAssign {}; // expected-note {{'DR1402::NoMove10 &'}}
+ struct NoMove11 : NonTrivialMoveAssignVBase {}; // expected-note {{'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}}
+ };
+}
diff --git a/test/CXX/special/class.copy/p11.0x.move.cpp b/test/CXX/special/class.copy/p11.0x.move.cpp
index 3e9cc6b662..ff9478be8b 100644
--- a/test/CXX/special/class.copy/p11.0x.move.cpp
+++ b/test/CXX/special/class.copy/p11.0x.move.cpp
@@ -123,7 +123,7 @@ struct NonMove {
CopyOnly CO;
NonMove(NonMove&&);
};
-NonMove::NonMove(NonMove&&) = default; // expected-error{{would delete}}
+NonMove::NonMove(NonMove&&) = default; // ok under DR1402
struct Moveable {
Moveable();
@@ -135,3 +135,30 @@ struct HasMove {
HasMove(HasMove&&);
};
HasMove::HasMove(HasMove&&) = default;
+
+namespace DR1402 {
+ struct member {
+ member();
+ member(const member&);
+ member& operator=(const member&);
+ ~member();
+ };
+
+ struct A {
+ member m_;
+
+ A() = default;
+ A(const A&) = default;
+ A& operator=(const A&) = default;
+ A(A&&) = default;
+ A& operator=(A&&) = default;
+ ~A() = default;
+ };
+
+ // ok, A's explicitly-defaulted move operations copy m_.
+ void f() {
+ A a, b(a), c(static_cast<A&&>(a));
+ a = b;
+ b = static_cast<A&&>(c);
+ }
+}