1 | // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s |
2 | |
3 | struct Trivial {}; |
4 | struct NonTrivial { |
5 | NonTrivial(NonTrivial&&); // expected-note{{copy constructor is implicitly deleted}} |
6 | }; |
7 | struct DeletedCopy { |
8 | DeletedCopy(const DeletedCopy&) = delete; |
9 | }; |
10 | |
11 | // A defaulted move constructor for a class X is defined as deleted if X has: |
12 | |
13 | // -- a variant member with a non-trivial corresponding constructor |
14 | union DeletedNTVariant { |
15 | NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}} |
16 | DeletedNTVariant(DeletedNTVariant&&); |
17 | }; |
18 | DeletedNTVariant::DeletedNTVariant(DeletedNTVariant&&) = default; // expected-error{{would delete}} |
19 | |
20 | struct DeletedNTVariant2 { |
21 | union { |
22 | NonTrivial NT; // expected-note{{deleted because variant field 'NT' has a non-trivial move constructor}} |
23 | }; |
24 | DeletedNTVariant2(DeletedNTVariant2&&); |
25 | }; |
26 | DeletedNTVariant2::DeletedNTVariant2(DeletedNTVariant2&&) = default; // expected-error{{would delete}} |
27 | |
28 | // Note, move constructor is not a candidate because it is deleted. |
29 | template<typename T> struct DeletedNTVariant3 { // expected-note 2{{default}} expected-note 2{{copy}} |
30 | union { |
31 | T NT; |
32 | }; |
33 | }; |
34 | extern DeletedNTVariant3<NonTrivial> dntv3a(0); // expected-error {{no matching}} |
35 | extern DeletedNTVariant3<DeletedCopy> dntv3a(0); // expected-error {{no matching}} |
36 | |
37 | // -- a non-static data member of class type M (or array thereof) that cannot be |
38 | // copied because overload resolution results in an ambiguity or a function |
39 | // that is deleted or inaccessible |
40 | struct NoAccess { |
41 | NoAccess() = default; |
42 | private: |
43 | NoAccess(NoAccess&&); |
44 | |
45 | friend struct HasAccess; |
46 | }; |
47 | |
48 | struct HasNoAccess { |
49 | NoAccess NA; // expected-note{{deleted because field 'NA' has an inaccessible move constructor}} |
50 | HasNoAccess(HasNoAccess&&); |
51 | }; |
52 | HasNoAccess::HasNoAccess(HasNoAccess&&) = default; // expected-error{{would delete}} |
53 | |
54 | struct HasAccess { |
55 | NoAccess NA; |
56 | HasAccess(HasAccess&&); |
57 | }; |
58 | HasAccess::HasAccess(HasAccess&&) = default; |
59 | |
60 | struct Ambiguity { |
61 | Ambiguity(const Ambiguity&&); |
62 | Ambiguity(volatile Ambiguity&&); |
63 | }; |
64 | |
65 | struct IsAmbiguous { |
66 | Ambiguity A; // expected-note{{deleted because field 'A' has multiple move constructors}} |
67 | IsAmbiguous(IsAmbiguous&&); // expected-note{{copy constructor is implicitly deleted because 'IsAmbiguous' has a user-declared move constructor}} |
68 | }; |
69 | IsAmbiguous::IsAmbiguous(IsAmbiguous&&) = default; // expected-error{{would delete}} |
70 | |
71 | struct Deleted { |
72 | // FIXME: This diagnostic is slightly wrong: the constructor we select to move |
73 | // 'IA' is deleted, but we select the copy constructor (we ignore the move |
74 | // constructor, because it was defaulted and deleted). |
75 | IsAmbiguous IA; // expected-note{{deleted because field 'IA' has a deleted move constructor}} |
76 | Deleted(Deleted&&); |
77 | }; |
78 | Deleted::Deleted(Deleted&&) = default; // expected-error{{would delete}} |
79 | |
80 | // It's implied (but not stated) that this should also happen if overload |
81 | // resolution fails. |
82 | struct ConstMember { |
83 | const Trivial ct; |
84 | ConstMember(ConstMember&&); |
85 | }; |
86 | ConstMember::ConstMember(ConstMember&&) = default; // ok, calls copy ctor |
87 | struct ConstMoveOnlyMember { |
88 | // FIXME: This diagnostic is slightly wrong: the constructor we select to move |
89 | // 'cnt' is deleted, but we select the copy constructor, because the object is |
90 | // const. |
91 | const NonTrivial cnt; // expected-note{{deleted because field 'cnt' has a deleted move constructor}} |
92 | ConstMoveOnlyMember(ConstMoveOnlyMember&&); |
93 | }; |
94 | ConstMoveOnlyMember::ConstMoveOnlyMember(ConstMoveOnlyMember&&) = default; // expected-error{{would delete}} |
95 | struct VolatileMember { |
96 | volatile Trivial vt; // expected-note{{deleted because field 'vt' has no move constructor}} |
97 | VolatileMember(VolatileMember&&); |
98 | }; |
99 | VolatileMember::VolatileMember(VolatileMember&&) = default; // expected-error{{would delete}} |
100 | |
101 | // -- a direct or virtual base class B that cannot be moved because overload |
102 | // resolution results in an ambiguity or a function that is deleted or |
103 | // inaccessible |
104 | struct AmbiguousMoveBase : Ambiguity { // expected-note{{deleted because base class 'Ambiguity' has multiple move constructors}} |
105 | AmbiguousMoveBase(AmbiguousMoveBase&&); // expected-note{{copy constructor is implicitly deleted}} |
106 | }; |
107 | AmbiguousMoveBase::AmbiguousMoveBase(AmbiguousMoveBase&&) = default; // expected-error{{would delete}} |
108 | |
109 | struct DeletedMoveBase : AmbiguousMoveBase { // expected-note{{deleted because base class 'AmbiguousMoveBase' has a deleted move constructor}} |
110 | DeletedMoveBase(DeletedMoveBase&&); |
111 | }; |
112 | DeletedMoveBase::DeletedMoveBase(DeletedMoveBase&&) = default; // expected-error{{would delete}} |
113 | |
114 | struct InaccessibleMoveBase : NoAccess { // expected-note{{deleted because base class 'NoAccess' has an inaccessible move constructor}} |
115 | InaccessibleMoveBase(InaccessibleMoveBase&&); |
116 | }; |
117 | InaccessibleMoveBase::InaccessibleMoveBase(InaccessibleMoveBase&&) = default; // expected-error{{would delete}} |
118 | |
119 | // -- any direct or virtual base class or non-static data member of a type with |
120 | // a destructor that is deleted or inaccessible |
121 | struct NoAccessDtor { |
122 | NoAccessDtor(NoAccessDtor&&); // expected-note{{copy constructor is implicitly deleted because 'NoAccessDtor' has a user-declared move constructor}} |
123 | private: |
124 | ~NoAccessDtor(); |
125 | friend struct HasAccessDtor; |
126 | }; |
127 | |
128 | struct HasNoAccessDtor { |
129 | NoAccessDtor NAD; // expected-note {{deleted because field 'NAD' has an inaccessible destructor}} |
130 | HasNoAccessDtor(HasNoAccessDtor&&); |
131 | }; |
132 | HasNoAccessDtor::HasNoAccessDtor(HasNoAccessDtor&&) = default; // expected-error{{would delete}} |
133 | |
134 | struct HasAccessDtor { |
135 | NoAccessDtor NAD; |
136 | HasAccessDtor(HasAccessDtor&&); |
137 | }; |
138 | HasAccessDtor::HasAccessDtor(HasAccessDtor&&) = default; |
139 | |
140 | struct HasNoAccessDtorBase : NoAccessDtor { // expected-note{{copy constructor of 'HasNoAccessDtorBase' is implicitly deleted because base class 'NoAccessDtor' has a deleted copy constructor}} |
141 | }; |
142 | extern HasNoAccessDtorBase HNADBa; |
143 | HasNoAccessDtorBase HNADBb(HNADBa); // expected-error{{implicitly-deleted copy constructor}} |
144 | |
145 | // The restriction on rvalue reference members applies to only the copy |
146 | // constructor. |
147 | struct RValue { |
148 | int &&ri = 1; |
149 | RValue(RValue&&); |
150 | }; |
151 | RValue::RValue(RValue&&) = default; |
152 | |
153 | // -- a non-static data member or direct or virtual base class with a type that |
154 | // does not have a move constructor and is not trivially copyable |
155 | struct CopyOnly { |
156 | CopyOnly(const CopyOnly&); |
157 | }; |
158 | |
159 | struct NonMove { |
160 | CopyOnly CO; |
161 | NonMove(NonMove&&); |
162 | }; |
163 | NonMove::NonMove(NonMove&&) = default; // ok under DR1402 |
164 | |
165 | struct Moveable { |
166 | Moveable(); |
167 | Moveable(Moveable&&); |
168 | }; |
169 | |
170 | struct HasMove { |
171 | Moveable M; |
172 | HasMove(HasMove&&); |
173 | }; |
174 | HasMove::HasMove(HasMove&&) = default; |
175 | |
176 | namespace DR1402 { |
177 | struct member { |
178 | member(); |
179 | member(const member&); |
180 | member& operator=(const member&); |
181 | ~member(); |
182 | }; |
183 | |
184 | struct A { |
185 | member m_; |
186 | |
187 | A() = default; |
188 | A(const A&) = default; |
189 | A& operator=(const A&) = default; |
190 | A(A&&) = default; |
191 | A& operator=(A&&) = default; |
192 | ~A() = default; |
193 | }; |
194 | |
195 | // ok, A's explicitly-defaulted move operations copy m_. |
196 | void f() { |
197 | A a, b(a), c(static_cast<A&&>(a)); |
198 | a = b; |
199 | b = static_cast<A&&>(c); |
200 | } |
201 | } |
202 | |