1// RUN: %check_clang_tidy %s performance-noexcept-move-constructor %t -- -- -fexceptions
2
3namespace std
4{
5 template <typename T>
6 struct is_nothrow_move_constructible
7 {
8 static constexpr bool value = __is_nothrow_constructible(T, __add_rvalue_reference(T));
9 };
10} // namespace std
11
12struct Empty
13{};
14
15struct IntWrapper {
16 int value;
17};
18
19template <typename T>
20struct FalseT {
21 static constexpr bool value = false;
22};
23
24template <typename T>
25struct TrueT {
26 static constexpr bool value = true;
27};
28
29struct ThrowOnAnything {
30 ThrowOnAnything() noexcept(false);
31 ThrowOnAnything(ThrowOnAnything&&) noexcept(false);
32 ThrowOnAnything& operator=(ThrowOnAnything &&) noexcept(false);
33 ~ThrowOnAnything() noexcept(false);
34};
35
36class A {
37 A(A &&);
38 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
39 // CHECK-FIXES: A(A &&) noexcept ;
40 A &operator=(A &&);
41 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]
42 // CHECK-FIXES: A &operator=(A &&) noexcept ;
43};
44
45struct B {
46 static constexpr bool kFalse = false;
47 B(B &&) noexcept(kFalse);
48 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
49 B &operator=(B &&) noexcept(kFalse);
50 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]
51};
52
53template <typename>
54struct C {
55 C(C &&);
56 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
57 // CHECK-FIXES: C(C &&) noexcept ;
58 C& operator=(C &&);
59 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]
60 // CHECK-FIXES: C& operator=(C &&) noexcept ;
61};
62
63struct D {
64 static constexpr bool kFalse = false;
65 D(D &&) noexcept(kFalse) = default;
66 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
67 D& operator=(D &&) noexcept(kFalse) = default;
68 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]
69};
70
71template <typename>
72struct E {
73 static constexpr bool kFalse = false;
74 E(E &&) noexcept(kFalse);
75 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
76 E& operator=(E &&) noexcept(kFalse);
77 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false'
78};
79
80template <typename>
81struct F {
82 static constexpr bool kFalse = false;
83 F(F &&) noexcept(kFalse) = default;
84 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
85 F& operator=(F &&) noexcept(kFalse) = default;
86 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]
87};
88
89struct G {
90 G(G &&) = default;
91 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
92 // CHECK-FIXES: G(G &&) noexcept = default;
93 G& operator=(G &&) = default;
94 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]
95 // CHECK-FIXES: G& operator=(G &&) noexcept = default;
96
97 ThrowOnAnything field;
98};
99
100void throwing_function() noexcept(false) {}
101
102struct H {
103 H(H &&) noexcept(noexcept(throwing_function()));
104 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
105 H &operator=(H &&) noexcept(noexcept(throwing_function()));
106 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]
107};
108
109template <typename>
110struct I {
111 I(I &&) noexcept(noexcept(throwing_function()));
112 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
113 I &operator=(I &&) noexcept(noexcept(throwing_function()));
114 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]
115};
116
117template <typename T> struct TemplatedType {
118 static void f() {}
119};
120
121template <> struct TemplatedType<int> {
122 static void f() noexcept {}
123};
124
125struct J {
126 J(J &&) noexcept(noexcept(TemplatedType<double>::f()));
127 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: noexcept specifier on the move constructor evaluates to 'false' [performance-noexcept-move-constructor]
128 J &operator=(J &&) noexcept(noexcept(TemplatedType<double>::f()));
129 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: noexcept specifier on the move assignment operator evaluates to 'false' [performance-noexcept-move-constructor]
130};
131
132struct K : public ThrowOnAnything {
133 K(K &&) = default;
134 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
135 // CHECK-FIXES: K(K &&) noexcept = default;
136 K &operator=(K &&) = default;
137 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]
138 // CHECK-FIXES: K &operator=(K &&) noexcept = default;
139};
140
141struct InheritFromThrowOnAnything : public ThrowOnAnything
142{};
143
144struct L {
145 L(L &&) = default;
146 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
147 // CHECK-FIXES: L(L &&) noexcept = default;
148 L &operator=(L &&) = default;
149 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]
150 // CHECK-FIXES: L &operator=(L &&) noexcept = default;
151
152 InheritFromThrowOnAnything IFF;
153};
154
155struct M : public InheritFromThrowOnAnything {
156 M(M &&) = default;
157 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
158 // CHECK-FIXES: M(M &&) noexcept = default;
159 M &operator=(M &&) = default;
160 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]
161 // CHECK-FIXES: M &operator=(M &&) noexcept = default;
162};
163
164struct N : public IntWrapper, ThrowOnAnything {
165 N(N &&) = default;
166 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
167 // CHECK-FIXES: N(N &&) noexcept = default;
168 N &operator=(N &&) = default;
169 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]
170 // CHECK-FIXES: N &operator=(N &&) noexcept = default;
171};
172
173struct O : virtual IntWrapper, ThrowOnAnything {
174 O(O &&) = default;
175 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: move constructors should be marked noexcept [performance-noexcept-move-constructor]
176 // CHECK-FIXES: O(O &&) noexcept = default;
177 O &operator=(O &&) = default;
178 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: move assignment operators should be marked noexcept [performance-noexcept-move-constructor]
179 // CHECK-FIXES: O &operator=(O &&) noexcept = default;
180};
181
182class OK {};
183
184void f() {
185 OK a;
186 a = OK();
187}
188
189struct OK1 {
190 OK1(const OK1 &);
191 OK1(OK1 &&) noexcept;
192 OK1 &operator=(OK1 &&) noexcept;
193 void f();
194 void g() noexcept;
195};
196
197struct OK2 {
198 static constexpr bool kTrue = true;
199
200 OK2(OK2 &&) noexcept(true) {}
201 OK2 &operator=(OK2 &&) noexcept(kTrue) { return *this; }
202};
203
204struct OK4 {
205 OK4(OK4 &&) noexcept(false) {}
206 OK4 &operator=(OK4 &&) = delete;
207};
208
209struct OK3 {
210 OK3(OK3 &&) noexcept = default;
211 OK3 &operator=(OK3 &&) noexcept = default;
212};
213
214struct OK5 {
215 OK5(OK5 &&) noexcept(true) = default;
216 OK5 &operator=(OK5 &&) noexcept(true) = default;
217};
218
219struct OK6 {
220 OK6(OK6 &&) = default;
221 OK6& operator=(OK6 &&) = default;
222};
223
224template <typename>
225struct OK7 {
226 OK7(OK7 &&) = default;
227 OK7& operator=(OK7 &&) = default;
228};
229
230template <typename>
231struct OK8 {
232 OK8(OK8 &&) noexcept = default;
233 OK8& operator=(OK8 &&) noexcept = default;
234};
235
236template <typename>
237struct OK9 {
238 OK9(OK9 &&) noexcept(true) = default;
239 OK9& operator=(OK9 &&) noexcept(true) = default;
240};
241
242template <typename>
243struct OK10 {
244 OK10(OK10 &&) noexcept(false) = default;
245 OK10& operator=(OK10 &&) noexcept(false) = default;
246};
247
248template <typename>
249struct OK11 {
250 OK11(OK11 &&) = delete;
251 OK11& operator=(OK11 &&) = delete;
252};
253
254void noexcept_function() noexcept {}
255
256struct OK12 {
257 OK12(OK12 &&) noexcept(noexcept(noexcept_function()));
258 OK12 &operator=(OK12 &&) noexcept(noexcept(noexcept_function));
259};
260
261struct OK13 {
262 OK13(OK13 &&) noexcept(noexcept(noexcept_function)) = default;
263 OK13 &operator=(OK13 &&) noexcept(noexcept(noexcept_function)) = default;
264};
265
266template <typename>
267struct OK14 {
268 OK14(OK14 &&) noexcept(noexcept(TemplatedType<int>::f()));
269 OK14 &operator=(OK14 &&) noexcept(noexcept(TemplatedType<int>::f()));
270};
271
272struct OK15 {
273 OK15(OK15 &&) = default;
274 OK15 &operator=(OK15 &&) = default;
275
276 int member;
277};
278
279template <typename>
280struct OK16 {
281 OK16(OK16 &&) = default;
282 OK16 &operator=(OK16 &&) = default;
283
284 int member;
285};
286
287struct OK17 {
288 OK17(OK17 &&) = default;
289 OK17 &operator=(OK17 &&) = default;
290
291 OK empty_field;
292};
293
294template <typename>
295struct OK18 {
296 OK18(OK18 &&) = default;
297 OK18 &operator=(OK18 &&) = default;
298
299 OK empty_field;
300};
301
302struct OK19 : public OK {
303 OK19(OK19 &&) = default;
304 OK19 &operator=(OK19 &&) = default;
305};
306
307struct OK20 : virtual OK {
308 OK20(OK20 &&) = default;
309 OK20 &operator=(OK20 &&) = default;
310};
311
312template <typename T>
313struct OK21 : public T {
314 OK21() = default;
315 OK21(OK21 &&) = default;
316 OK21 &operator=(OK21 &&) = default;
317};
318
319template <typename T>
320struct OK22 : virtual T {
321 OK22() = default;
322 OK22(OK22 &&) = default;
323 OK22 &operator=(OK22 &&) = default;
324};
325
326template <typename T>
327struct OK23 {
328 OK23() = default;
329 OK23(OK23 &&) = default;
330 OK23 &operator=(OK23 &&) = default;
331
332 T member;
333};
334
335void testTemplates() {
336 OK21<Empty> value(OK21<Empty>{});
337 value = OK21<Empty>{};
338
339 OK22<Empty> value2{OK22<Empty>{}};
340 value2 = OK22<Empty>{};
341
342 OK23<Empty> value3{OK23<Empty>{}};
343 value3 =OK23<Empty>{};
344}
345
346struct OK24 : public Empty, OK1 {
347 OK24(OK24 &&) = default;
348 OK24 &operator=(OK24 &&) = default;
349};
350
351struct OK25 : virtual Empty, OK1 {
352 OK25(OK25 &&) = default;
353 OK25 &operator=(OK25 &&) = default;
354};
355
356struct OK26 : public Empty, IntWrapper {
357 OK26(OK26 &&) = default;
358 OK26 &operator=(OK26 &&) = default;
359};
360
361template <typename T>
362struct OK27 : public T {
363 OK27(OK27 &&) = default;
364 OK27 &operator=(OK27 &&) = default;
365};
366
367template <typename T>
368struct OK28 : virtual T {
369 OK28(OK28 &&) = default;
370 OK28 &operator=(OK28 &&) = default;
371};
372
373template <typename T>
374struct OK29 {
375 OK29(OK29 &&) = default;
376 OK29 &operator=(OK29 &&) = default;
377
378 T member;
379};
380
381struct OK30 {
382 OK30(OK30 &&) noexcept(TrueT<OK30>::value) = default;
383 OK30& operator=(OK30 &&) noexcept(TrueT<OK30>::value) = default;
384};
385
386template <typename>
387struct OK31 {
388 OK31(OK31 &&) noexcept(TrueT<int>::value) = default;
389 OK31& operator=(OK31 &&) noexcept(TrueT<int>::value) = default;
390};
391
392namespace gh68101
393{
394 template <typename T>
395 class Container {
396 public:
397 Container(Container&&) noexcept(std::is_nothrow_move_constructible<T>::value);
398 };
399} // namespace gh68101
400

source code of clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp