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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

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