1 | // RUN: %clang_cc1 -verify %s -std=c++11 -Wno-defaulted-function-deleted |
2 | |
3 | struct Trivial {}; |
4 | |
5 | template<typename T> struct CopyAssign { |
6 | static T t; |
7 | void test() { |
8 | t = t; // expected-error +{{deleted}} |
9 | } |
10 | }; |
11 | template<typename T> struct MoveAssign { |
12 | static T t; |
13 | void test() { |
14 | // Overload resolution will ignore a defaulted, deleted move assignment, |
15 | // so check for it in a different way. |
16 | T &(T::*f)(T&&) = &T::operator=; // expected-error +{{deleted}} |
17 | } |
18 | }; |
19 | template<typename T> struct MoveOrCopyAssign { |
20 | static T t; |
21 | void test() { |
22 | t = static_cast<T&&>(t); // expected-error +{{copy assignment operator is implicitly deleted}} |
23 | } |
24 | }; |
25 | |
26 | struct NonTrivialCopyAssign { |
27 | NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &); |
28 | }; |
29 | struct NonTrivialMoveAssign { |
30 | NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&); |
31 | }; |
32 | struct AmbiguousCopyAssign { |
33 | AmbiguousCopyAssign &operator=(const AmbiguousCopyAssign &) volatile; |
34 | AmbiguousCopyAssign &operator=(const AmbiguousCopyAssign &) const; |
35 | }; |
36 | struct AmbiguousMoveAssign { |
37 | AmbiguousMoveAssign &operator=(const AmbiguousMoveAssign &&); |
38 | AmbiguousMoveAssign &operator=(volatile AmbiguousMoveAssign &&); |
39 | }; |
40 | struct DeletedCopyAssign { |
41 | DeletedCopyAssign &operator=(const DeletedCopyAssign &) = delete; // expected-note 2{{deleted}} |
42 | }; |
43 | struct DeletedMoveAssign { |
44 | DeletedMoveAssign &operator=(DeletedMoveAssign &&) = delete; // expected-note 2{{deleted}} |
45 | }; |
46 | class InaccessibleCopyAssign { |
47 | InaccessibleCopyAssign &operator=(const InaccessibleCopyAssign &); |
48 | }; |
49 | class InaccessibleMoveAssign { |
50 | InaccessibleMoveAssign &operator=(InaccessibleMoveAssign &&); |
51 | }; |
52 | class NonConstCopyAssign { |
53 | NonConstCopyAssign &operator=(NonConstCopyAssign &); |
54 | }; |
55 | |
56 | // A defaulted copy/move assignment operator for class X is defined as deleted |
57 | // if X has: |
58 | |
59 | // -- a variant member with a non-trivial corresponding assignment operator |
60 | // and X is a union-like class |
61 | struct A1 { |
62 | union { |
63 | NonTrivialCopyAssign x; // expected-note {{variant field 'x' has a non-trivial copy assign}} |
64 | }; |
65 | }; |
66 | template struct CopyAssign<A1>; // expected-note {{here}} |
67 | |
68 | struct A2 { |
69 | A2 &operator=(A2 &&) = default; // expected-note {{here}} |
70 | union { |
71 | NonTrivialMoveAssign x; // expected-note {{variant field 'x' has a non-trivial move assign}} |
72 | }; |
73 | }; |
74 | template struct MoveAssign<A2>; // expected-note {{here}} |
75 | |
76 | // -- a non-static const data member of (array of) non-class type |
77 | struct B1 { |
78 | const int a; // expected-note 2{{field 'a' is of const-qualified type}} |
79 | }; |
80 | struct B2 { |
81 | const void *const a[3][9][2]; // expected-note 2{{field 'a' is of const-qualified type 'const void *const [3][9][2]'}} |
82 | }; |
83 | struct B3 { |
84 | const void *a[3]; |
85 | }; |
86 | template struct CopyAssign<B1>; // expected-note {{here}} |
87 | template struct MoveAssign<B1>; // expected-note {{here}} |
88 | template struct CopyAssign<B2>; // expected-note {{here}} |
89 | template struct MoveAssign<B2>; // expected-note {{here}} |
90 | template struct CopyAssign<B3>; |
91 | template struct MoveAssign<B3>; |
92 | |
93 | // -- a non-static data member of reference type |
94 | struct C1 { |
95 | int &a; // expected-note 2{{field 'a' is of reference type 'int &'}} |
96 | }; |
97 | template struct CopyAssign<C1>; // expected-note {{here}} |
98 | template struct MoveAssign<C1>; // expected-note {{here}} |
99 | |
100 | // -- a non-static data member of class type M that cannot be copied/moved |
101 | struct D1 { |
102 | AmbiguousCopyAssign a; // expected-note {{field 'a' has multiple copy}} |
103 | }; |
104 | struct D2 { |
105 | D2 &operator=(D2 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}} |
106 | AmbiguousMoveAssign a; // expected-note {{field 'a' has multiple move}} |
107 | }; |
108 | struct D3 { |
109 | DeletedCopyAssign a; // expected-note {{field 'a' has a deleted copy}} |
110 | }; |
111 | struct D4 { |
112 | D4 &operator=(D4 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}} |
113 | DeletedMoveAssign a; // expected-note {{field 'a' has a deleted move}} |
114 | }; |
115 | struct D5 { |
116 | InaccessibleCopyAssign a; // expected-note {{field 'a' has an inaccessible copy}} |
117 | }; |
118 | struct D6 { |
119 | D6 &operator=(D6 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}} |
120 | InaccessibleMoveAssign a; // expected-note {{field 'a' has an inaccessible move}} |
121 | }; |
122 | struct D7 { |
123 | const Trivial a; // expected-note 3{{field 'a' has no }} |
124 | }; |
125 | struct D8 { |
126 | volatile Trivial a; // expected-note 3{{field 'a' has no }} |
127 | }; |
128 | template struct CopyAssign<D1>; // expected-note {{here}} |
129 | template struct MoveAssign<D2>; // expected-note {{here}} |
130 | template struct MoveOrCopyAssign<D2>; // expected-note {{here}} |
131 | template struct CopyAssign<D3>; // expected-note {{here}} |
132 | template struct MoveAssign<D4>; // expected-note {{here}} |
133 | template struct MoveOrCopyAssign<D4>; // expected-note {{here}} |
134 | template struct CopyAssign<D5>; // expected-note {{here}} |
135 | template struct MoveAssign<D6>; // expected-note {{here}} |
136 | template struct MoveOrCopyAssign<D6>; // expected-note {{here}} |
137 | template struct CopyAssign<D7>; // expected-note {{here}} |
138 | template struct MoveAssign<D7>; // expected-note {{here}} |
139 | template struct MoveOrCopyAssign<D7>; // expected-note {{here}} |
140 | template struct CopyAssign<D8>; // expected-note {{here}} |
141 | template struct MoveAssign<D8>; // expected-note {{here}} |
142 | template struct MoveOrCopyAssign<D8>; // expected-note {{here}} |
143 | |
144 | // -- a direct or virtual base that cannot be copied/moved |
145 | struct E1 : AmbiguousCopyAssign {}; // expected-note {{base class 'AmbiguousCopyAssign' has multiple copy}} |
146 | struct E2 : AmbiguousMoveAssign { // expected-note {{base class 'AmbiguousMoveAssign' has multiple move}} |
147 | E2 &operator=(E2 &&) = default; // expected-note {{here}} |
148 | }; |
149 | struct E3 : DeletedCopyAssign {}; // expected-note {{base class 'DeletedCopyAssign' has a deleted copy}} |
150 | struct E4 : DeletedMoveAssign { // expected-note {{base class 'DeletedMoveAssign' has a deleted move}} |
151 | E4 &operator=(E4 &&) = default; // expected-note {{here}} |
152 | }; |
153 | struct E5 : InaccessibleCopyAssign {}; // expected-note {{base class 'InaccessibleCopyAssign' has an inaccessible copy}} |
154 | struct E6 : InaccessibleMoveAssign { // expected-note {{base class 'InaccessibleMoveAssign' has an inaccessible move}} |
155 | E6 &operator=(E6 &&) = default; // expected-note {{here}} |
156 | }; |
157 | template struct CopyAssign<E1>; // expected-note {{here}} |
158 | template struct MoveAssign<E2>; // expected-note {{here}} |
159 | template struct CopyAssign<E3>; // expected-note {{here}} |
160 | template struct MoveAssign<E4>; // expected-note {{here}} |
161 | template struct CopyAssign<E5>; // expected-note {{here}} |
162 | template struct MoveAssign<E6>; // expected-note {{here}} |
163 | |
164 | namespace PR13381 { |
165 | struct S { |
166 | S &operator=(const S&); |
167 | S &operator=(const volatile S&) volatile = delete; // expected-note{{deleted here}} |
168 | }; |
169 | struct T { |
170 | volatile S s; // expected-note{{field 's' has a deleted copy assignment}} |
171 | }; |
172 | void g() { |
173 | T t; |
174 | t = T(); // expected-error{{object of type 'PR13381::T' cannot be assigned because its copy assignment operator is implicitly deleted}} |
175 | } |
176 | } |
177 | |
178 | namespace Mutable { |
179 | struct AmbiguousCopyAssign { |
180 | AmbiguousCopyAssign &operator=(const AmbiguousCopyAssign &); |
181 | AmbiguousCopyAssign &operator=(volatile AmbiguousCopyAssign &); |
182 | }; |
183 | struct X { |
184 | AmbiguousCopyAssign a; |
185 | }; |
186 | struct Y { |
187 | mutable AmbiguousCopyAssign a; // expected-note {{multiple copy assignment operators}} |
188 | }; |
189 | } |
190 | template struct CopyAssign<Mutable::X>; |
191 | template struct CopyAssign<Mutable::Y>; // expected-note {{here}} |
192 | |