aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/special/class.copy/p11.0x.move.cpp
blob: 1dce27a8329019646c61a4513c04dac0d427ff10 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s

struct Trivial {};
struct NonTrivial {
  NonTrivial(NonTrivial&&);
};

// A defaulted move constructor for a class X is defined as deleted if X has:

// -- a variant member with a non-trivial corresponding constructor
union DeletedNTVariant {
  NonTrivial NT;
  DeletedNTVariant(DeletedNTVariant&&);
};
DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}}

struct DeletedNTVariant2 {
  union {
    NonTrivial NT;
  };
  DeletedNTVariant2(DeletedNTVariant2&&);
};
DeletedNTVariant2::DeletedNTVariant2(DeletedNTVariant2&&) = default; // expected-error{{would delete}}

// -- a non-static data member of class type M (or array thereof) that cannot be
//    copied because overload resolution results in an ambiguity or a function
//    that is deleted or inaccessible
struct NoAccess {
  NoAccess() = default;
private:
  NoAccess(NoAccess&&);

  friend struct HasAccess;
};

struct HasNoAccess {
  NoAccess NA;
  HasNoAccess(HasNoAccess&&);
};
HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}}

struct HasAccess {
  NoAccess NA;
  HasAccess(HasAccess&&);
};
HasAccess::HasAccess(HasAccess&&) = default;

struct Ambiguity {
  Ambiguity(const Ambiguity&&);
  Ambiguity(volatile Ambiguity&&);
};

struct IsAmbiguous {
  Ambiguity A;
  IsAmbiguous(IsAmbiguous&&);
};
IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}}

struct Deleted {
  IsAmbiguous IA;
  Deleted(Deleted&&);
};
Deleted::Deleted(Deleted&&) = default; // expected-error{{would delete}}

// It's implied (but not stated) that this should also happen if overload
// resolution fails.
struct ConstMember {
  const Trivial ct;
  ConstMember(ConstMember&&);
};
ConstMember::ConstMember(ConstMember&&) = default; // ok, calls copy ctor
struct ConstMoveOnlyMember {
  const NonTrivial cnt;
  ConstMoveOnlyMember(ConstMoveOnlyMember&&);
};
ConstMoveOnlyMember::ConstMoveOnlyMember(ConstMoveOnlyMember&&) = default; // expected-error{{would delete}}
struct VolatileMember {
  volatile Trivial vt;
  VolatileMember(VolatileMember&&);
};
VolatileMember::VolatileMember(VolatileMember&&) = default; // expected-error{{would delete}}

// -- a direct or virtual base class B that cannot be moved because overload
//    resolution results in an ambiguity or a function that is deleted or
//    inaccessible
struct AmbiguousMoveBase : Ambiguity {
  AmbiguousMoveBase(AmbiguousMoveBase&&);
};
AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}}

struct DeletedMoveBase : AmbiguousMoveBase {
  DeletedMoveBase(DeletedMoveBase&&);
};
DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}}

struct InaccessibleMoveBase : NoAccess {
  InaccessibleMoveBase(InaccessibleMoveBase&&);
};
InaccessibleMoveBase::InaccessibleMoveBase(InaccessibleMoveBase&&) = default; // expected-error{{would delete}}

// -- any direct or virtual base class or non-static data member of a type with
//    a destructor that is deleted or inaccessible
struct NoAccessDtor {
  NoAccessDtor(NoAccessDtor&&); // expected-note{{copy constructor is implicitly deleted because 'NoAccessDtor' has a user-declared move constructor}}
private:
  ~NoAccessDtor();
  friend struct HasAccessDtor;
};

struct HasNoAccessDtor {
  NoAccessDtor NAD;
  HasNoAccessDtor(HasNoAccessDtor&&);
};
HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}}

struct HasAccessDtor {
  NoAccessDtor NAD;
  HasAccessDtor(HasAccessDtor&&);
};
HasAccessDtor::HasAccessDtor(HasAccessDtor&&) = default;

struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has a deleted copy constructor}}
};
extern HasNoAccessDtorBase HNADBa;
HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}}

// The restriction on rvalue reference members applies to only the copy
// constructor.
struct RValue {
  int &&ri = 1; // expected-warning {{binding reference member 'ri' to a temporary}} expected-note {{here}}
  RValue(RValue&&);
};
RValue::RValue(RValue&&) = default;

// -- a non-static data member or direct or virtual base class with a type that
//    does not have a move constructor and is not trivially copyable
struct CopyOnly {
  CopyOnly(const CopyOnly&);
};

struct NonMove {
  CopyOnly CO;
  NonMove(NonMove&&);
};
NonMove::NonMove(NonMove&&) = default; // ok under DR1402

struct Moveable {
  Moveable();
  Moveable(Moveable&&);
};

struct HasMove {
  Moveable M;
  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);
  }
}