1 | // RUN: %check_clang_tidy --match-partial-fixes %s modernize-use-equals-default %t -- \ |
---|---|
2 | // RUN: -config="{CheckOptions: {modernize-use-equals-default.IgnoreMacros: false}}" \ |
3 | // RUN: -- -fno-delayed-template-parsing -fexceptions -Wno-error=return-type |
4 | |
5 | // Out of line definition. |
6 | struct OL { |
7 | OL(const OL &); |
8 | OL &operator=(const OL &); |
9 | int Field; |
10 | }; |
11 | OL::OL(const OL &Other) : Field(Other.Field) {} |
12 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default] |
13 | // CHECK-FIXES: OL::OL(const OL &Other) = default; |
14 | OL &OL::operator=(const OL &Other) { |
15 | Field = Other.Field; |
16 | return *this; |
17 | } |
18 | // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: use '= default' to define a trivial copy-assignment operator [modernize-use-equals-default] |
19 | // CHECK-FIXES: OL &OL::operator=(const OL &Other) = default; |
20 | |
21 | // Inline. |
22 | struct IL { |
23 | IL(const IL &Other) : Field(Other.Field) {} |
24 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' |
25 | // CHECK-FIXES: IL(const IL &Other) = default; |
26 | IL &operator=(const IL &Other) { |
27 | Field = Other.Field; |
28 | return *this; |
29 | } |
30 | // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use '= default' |
31 | // CHECK-FIXES: IL &operator=(const IL &Other) = default; |
32 | int Field; |
33 | }; |
34 | |
35 | // Skip unions. |
36 | union NU { |
37 | NU(const NU &Other) : Field(Other.Field) {} |
38 | // CHECK-FIXES: NU(const NU &Other) : |
39 | NU &operator=(const NU &Other) { |
40 | Field = Other.Field; |
41 | return *this; |
42 | } |
43 | // CHECK-FIXES: NU &operator=(const NU &Other) { |
44 | IL Field; |
45 | }; |
46 | |
47 | // Skip structs/classes containing anonymous unions. |
48 | struct SU { |
49 | SU(const SU &Other) : Field(Other.Field) {} |
50 | // CHECK-FIXES: SU(const SU &Other) : |
51 | SU &operator=(const SU &Other) { |
52 | Field = Other.Field; |
53 | return *this; |
54 | } |
55 | // CHECK-FIXES: SU &operator=(const SU &Other) { |
56 | union { |
57 | IL Field; |
58 | }; |
59 | }; |
60 | |
61 | // Wrong type. |
62 | struct WT { |
63 | WT(const IL &Other) {} |
64 | WT &operator=(const IL &); |
65 | }; |
66 | WT &WT::operator=(const IL &Other) { return *this; } |
67 | |
68 | // Qualifiers. |
69 | struct Qual { |
70 | Qual(const Qual &Other) : Field(Other.Field), Volatile(Other.Volatile), |
71 | Mutable(Other.Mutable), Reference(Other.Reference), |
72 | Const(Other.Const) {} |
73 | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default' |
74 | // CHECK-FIXES: Qual(const Qual &Other) |
75 | // CHECK-FIXES: = default; |
76 | |
77 | int Field; |
78 | volatile char Volatile; |
79 | mutable bool Mutable; |
80 | const OL &Reference; // This makes this class non-assignable. |
81 | const IL Const; // This also makes this class non-assignable. |
82 | static int Static; |
83 | }; |
84 | |
85 | // Wrong init arguments. |
86 | struct WI { |
87 | WI(const WI &Other) : Field1(Other.Field1), Field2(Other.Field1) {} |
88 | WI &operator=(const WI &); |
89 | int Field1, Field2; |
90 | }; |
91 | WI &WI::operator=(const WI &Other) { |
92 | Field1 = Other.Field1; |
93 | Field2 = Other.Field1; |
94 | return *this; |
95 | } |
96 | |
97 | // Missing field. |
98 | struct MF { |
99 | MF(const MF &Other) : Field1(Other.Field1), Field2(Other.Field2) {} |
100 | MF &operator=(const MF &); |
101 | int Field1, Field2, Field3; |
102 | }; |
103 | MF &MF::operator=(const MF &Other) { |
104 | Field1 = Other.Field1; |
105 | Field2 = Other.Field2; |
106 | return *this; |
107 | } |
108 | |
109 | struct Comments { |
110 | Comments(const Comments &Other) |
111 | /* don't delete */ : /* this comment */ Field(Other.Field) {} |
112 | // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default' |
113 | // CHECK-FIXES: /* don't delete */ = default; |
114 | int Field; |
115 | }; |
116 | |
117 | struct MoreComments { |
118 | MoreComments(const MoreComments &Other) /* this comment is OK */ |
119 | : Field(Other.Field) {} |
120 | // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default' |
121 | // CHECK-FIXES: MoreComments(const MoreComments &Other) /* this comment is OK */ |
122 | // CHECK-FIXES-NEXT: = default; |
123 | int Field; |
124 | }; |
125 | |
126 | struct ColonInComment { |
127 | ColonInComment(const ColonInComment &Other) /* : */ : Field(Other.Field) {} |
128 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' |
129 | // CHECK-FIXES: ColonInComment(const ColonInComment &Other) /* : */ = default; |
130 | int Field; |
131 | }; |
132 | |
133 | // No members or bases (in particular, no colon). |
134 | struct Empty { |
135 | Empty(const Empty &Other) {} |
136 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' |
137 | // CHECK-FIXES: Empty(const Empty &Other) = default; |
138 | Empty &operator=(const Empty &); |
139 | }; |
140 | Empty &Empty::operator=(const Empty &Other) { return *this; } |
141 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use '= default' |
142 | // CHECK-FIXES: Empty &Empty::operator=(const Empty &Other) = default; |
143 | |
144 | // Bit fields. |
145 | struct BF { |
146 | BF() = default; |
147 | BF(const BF &Other) : Field1(Other.Field1), Field2(Other.Field2), Field3(Other.Field3), |
148 | Field4(Other.Field4) {}; |
149 | // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default' |
150 | // CHECK-FIXES: BF(const BF &Other) {{$}} |
151 | // CHECK-FIXES: = default; |
152 | BF &operator=(const BF &); |
153 | |
154 | unsigned Field1 : 3; |
155 | int : 7; |
156 | char Field2 : 6; |
157 | int : 0; |
158 | int Field3 : 24; |
159 | unsigned char Field4; |
160 | }; |
161 | BF &BF::operator=(const BF &Other) { |
162 | Field1 = Other.Field1; |
163 | Field2 = Other.Field2; |
164 | Field3 = Other.Field3; |
165 | Field4 = Other.Field4; |
166 | return *this; |
167 | } |
168 | // CHECK-MESSAGES: :[[@LINE-7]]:9: warning: use '= default' |
169 | // CHECK-FIXES: BF &BF::operator=(const BF &Other) = default; |
170 | |
171 | // Base classes. |
172 | struct BC : IL, OL, BF { |
173 | BC(const BC &Other) : IL(Other), OL(Other), BF(Other) {} |
174 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' |
175 | // CHECK-FIXES: BC(const BC &Other) = default; |
176 | BC &operator=(const BC &Other); |
177 | }; |
178 | BC &BC::operator=(const BC &Other) { |
179 | IL::operator=(Other); |
180 | OL::operator=(Other); |
181 | BF::operator=(Other); |
182 | return *this; |
183 | } |
184 | // CHECK-MESSAGES: :[[@LINE-6]]:9: warning: use '= default' |
185 | // CHECK-FIXES: BC &BC::operator=(const BC &Other) = default; |
186 | |
187 | // Base classes with member. |
188 | struct BCWM : IL, OL { |
189 | BCWM(const BCWM &Other) : IL(Other), OL(Other), Bf(Other.Bf) {} |
190 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' |
191 | // CHECK-FIXES: BCWM(const BCWM &Other) = default; |
192 | BCWM &operator=(const BCWM &); |
193 | BF Bf; |
194 | }; |
195 | BCWM &BCWM::operator=(const BCWM &Other) { |
196 | IL::operator=(Other); |
197 | OL::operator=(Other); |
198 | Bf = Other.Bf; |
199 | return *this; |
200 | } |
201 | // CHECK-MESSAGES: :[[@LINE-6]]:13: warning: use '= default' |
202 | // CHECK-FIXES: BCWM &BCWM::operator=(const BCWM &Other) = default; |
203 | |
204 | // Missing base class. |
205 | struct MBC : IL, OL, BF { |
206 | MBC(const MBC &Other) : IL(Other), OL(Other) {} |
207 | MBC &operator=(const MBC &); |
208 | }; |
209 | MBC &MBC::operator=(const MBC &Other) { |
210 | IL::operator=(Other); |
211 | OL::operator=(Other); |
212 | return *this; |
213 | } |
214 | |
215 | // Base classes, incorrect parameter. |
216 | struct BCIP : BCWM, BF { |
217 | BCIP(const BCIP &Other) : BCWM(Other), BF(Other.Bf) {} |
218 | BCIP &operator=(const BCIP &); |
219 | }; |
220 | BCIP &BCIP::operator=(const BCIP &Other) { |
221 | BCWM::operator=(Other); |
222 | BF::operator=(Other: Other.Bf); |
223 | return *this; |
224 | } |
225 | |
226 | // Virtual base classes. |
227 | struct VA : virtual OL {}; |
228 | struct VB : virtual OL {}; |
229 | struct VBC : VA, VB, virtual OL { |
230 | // OL is the first thing that is going to be initialized, despite the fact |
231 | // that it is the last in the list of bases, because it is virtual and there |
232 | // is a virtual OL at the beginning of VA (which is the same). |
233 | VBC(const VBC &Other) : OL(Other), VA(Other), VB(Other) {} |
234 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' |
235 | // CHECK-FIXES: VBC(const VBC &Other) = default; |
236 | VBC &operator=(const VBC &Other); |
237 | }; |
238 | VBC &VBC::operator=(const VBC &Other) { |
239 | OL::operator=(Other); |
240 | VA::operator=(Other); |
241 | VB::operator=(Other); |
242 | return *this; |
243 | } |
244 | // CHECK-MESSAGES: :[[@LINE-6]]:11: warning: use '= default' |
245 | // CHECK-FIXES: VBC &VBC::operator=(const VBC &Other) = default; |
246 | |
247 | // Indirect base. |
248 | struct IB : VBC { |
249 | IB(const IB &Other) : OL(Other), VBC(Other) {} |
250 | IB &operator=(const IB &); |
251 | }; |
252 | IB &IB::operator=(const IB &Other) { |
253 | OL::operator=(Other); |
254 | VBC::operator=(Other); |
255 | return *this; |
256 | } |
257 | |
258 | // Class template. |
259 | template <class T> |
260 | struct Template { |
261 | Template() = default; |
262 | Template(const Template &Other) : Field(Other.Field) {} |
263 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' |
264 | // CHECK-FIXES: Template(const Template &Other) = default; |
265 | Template &operator=(const Template &Other); |
266 | void foo(const T &t); |
267 | int Field; |
268 | }; |
269 | template <class T> |
270 | Template<T> &Template<T>::operator=(const Template<T> &Other) { |
271 | Field = Other.Field; |
272 | return *this; |
273 | } |
274 | // CHECK-MESSAGES: :[[@LINE-4]]:27: warning: use '= default' |
275 | // CHECK-FIXES: Template<T> &Template<T>::operator=(const Template<T> &Other) = default; |
276 | |
277 | Template<int> T1; |
278 | |
279 | |
280 | // Dependent types. |
281 | template <class T> |
282 | struct DT1 { |
283 | DT1() = default; |
284 | DT1(const DT1 &Other) : Field(Other.Field) {} |
285 | DT1 &operator=(const DT1 &); |
286 | T Field; |
287 | }; |
288 | template <class T> |
289 | DT1<T> &DT1<T>::operator=(const DT1<T> &Other) { |
290 | Field = Other.Field; |
291 | return *this; |
292 | } |
293 | // CHECK-MESSAGES: :[[@LINE-4]]:17: warning: use '= default' |
294 | // CHECK-FIXES: DT1<T> &DT1<T>::operator=(const DT1<T> &Other) = default; |
295 | |
296 | DT1<int> Dt1; |
297 | |
298 | template <class T> |
299 | struct DT2 { |
300 | DT2() = default; |
301 | DT2(const DT2 &Other) : Field(Other.Field), Dependent(Other.Dependent) {} |
302 | DT2 &operator=(const DT2 &); |
303 | T Field; |
304 | typename T::TT Dependent; |
305 | }; |
306 | template <class T> |
307 | DT2<T> &DT2<T>::operator=(const DT2<T> &Other) { |
308 | Field = Other.Field; |
309 | Dependent = Other.Dependent; |
310 | return *this; |
311 | } |
312 | struct T { |
313 | typedef int TT; |
314 | }; |
315 | // CHECK-MESSAGES: :[[@LINE-8]]:17: warning: use '= default' |
316 | // CHECK-FIXES: DT2<T> &DT2<T>::operator=(const DT2<T> &Other) = default; |
317 | |
318 | DT2<T> Dt2; |
319 | |
320 | // Default arguments. |
321 | struct DA { |
322 | DA(int Int); |
323 | DA(const DA &Other = DA(0)) : Field1(Other.Field1), Field2(Other.Field2) {} |
324 | DA &operator=(const DA &); |
325 | int Field1; |
326 | char Field2; |
327 | }; |
328 | // Overloaded operator= cannot have a default argument. |
329 | DA &DA::operator=(const DA &Other) { |
330 | Field1 = Other.Field1; |
331 | Field2 = Other.Field2; |
332 | return *this; |
333 | } |
334 | // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: use '= default' |
335 | // CHECK-FIXES: DA &DA::operator=(const DA &Other) = default; |
336 | |
337 | struct DA2 { |
338 | // Can be used as copy-constructor but cannot be explicitly defaulted. |
339 | DA2(const DA &Other, int Def = 0) {} |
340 | }; |
341 | |
342 | // Default initialization. |
343 | struct DI { |
344 | DI(const DI &Other) : Field1(Other.Field1), Field2(Other.Field2) {} |
345 | int Field1; |
346 | int Field2 = 0; |
347 | int Fiedl3; |
348 | }; |
349 | |
350 | // Statement inside body. |
351 | void foo(); |
352 | struct SIB { |
353 | SIB(const SIB &Other) : Field(Other.Field) { foo(); } |
354 | SIB &operator=(const SIB &); |
355 | int Field; |
356 | }; |
357 | SIB &SIB::operator=(const SIB &Other) { |
358 | Field = Other.Field; |
359 | foo(); |
360 | return *this; |
361 | } |
362 | |
363 | // Comment inside body. |
364 | struct CIB { |
365 | CIB(const CIB &Other) : Field(Other.Field) { /* Don't erase this */ |
366 | } |
367 | // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default' |
368 | CIB &operator=(const CIB &); |
369 | int Field; |
370 | }; |
371 | CIB &CIB::operator=(const CIB &Other) { |
372 | Field = Other.Field; |
373 | // FIXME: don't erase this comment. |
374 | return *this; |
375 | } |
376 | // CHECK-MESSAGES: :[[@LINE-5]]:11: warning: use '= default' |
377 | // CHECK-FIXES: CIB &CIB::operator=(const CIB &Other) = default; |
378 | |
379 | // Take non-const reference as argument. |
380 | struct NCRef { |
381 | NCRef(NCRef &Other) : Field1(Other.Field1), Field2(Other.Field2) {} |
382 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' |
383 | // CHECK-FIXES: NCRef(NCRef &Other) = default; |
384 | NCRef &operator=(NCRef &); |
385 | int Field1, Field2; |
386 | }; |
387 | NCRef &NCRef::operator=(NCRef &Other) { |
388 | Field1 = Other.Field1; |
389 | Field2 = Other.Field2; |
390 | return *this; |
391 | } |
392 | // CHECK-MESSAGES: :[[@LINE-5]]:15: warning: use '= default' |
393 | // CHECK-FIXES: NCRef &NCRef::operator=(NCRef &Other) = default; |
394 | |
395 | // Already defaulted. |
396 | struct IAD { |
397 | IAD(const IAD &Other) = default; |
398 | IAD &operator=(const IAD &Other) = default; |
399 | }; |
400 | |
401 | struct OAD { |
402 | OAD(const OAD &Other); |
403 | OAD &operator=(const OAD &); |
404 | }; |
405 | OAD::OAD(const OAD &Other) = default; |
406 | OAD &OAD::operator=(const OAD &Other) = default; |
407 | |
408 | // Deleted. |
409 | struct ID { |
410 | ID(const ID &Other) = delete; |
411 | ID &operator=(const ID &Other) = delete; |
412 | }; |
413 | |
414 | // Non-reference parameter. |
415 | struct NRef { |
416 | NRef &operator=(NRef Other); |
417 | int Field1; |
418 | }; |
419 | NRef &NRef::operator=(NRef Other) { |
420 | Field1 = Other.Field1; |
421 | return *this; |
422 | } |
423 | |
424 | // RValue reference parameter. |
425 | struct RVR { |
426 | RVR(RVR &&Other) {} |
427 | RVR &operator=(RVR &&); |
428 | }; |
429 | RVR &RVR::operator=(RVR &&Other) { return *this; } |
430 | |
431 | // Similar function. |
432 | struct SF { |
433 | SF &foo(const SF &); |
434 | int Field1; |
435 | }; |
436 | SF &SF::foo(const SF &Other) { |
437 | Field1 = Other.Field1; |
438 | return *this; |
439 | } |
440 | |
441 | // No return. |
442 | struct NR { |
443 | NR &operator=(const NR &); |
444 | }; |
445 | NR &NR::operator=(const NR &Other) {} |
446 | |
447 | // Return misplaced. |
448 | struct RM { |
449 | RM &operator=(const RM &); |
450 | int Field; |
451 | }; |
452 | RM &RM::operator=(const RM &Other) { |
453 | return *this; |
454 | Field = Other.Field; |
455 | } |
456 | |
457 | // Wrong return value. |
458 | struct WRV { |
459 | WRV &operator=(WRV &); |
460 | }; |
461 | WRV &WRV::operator=(WRV &Other) { |
462 | return Other; |
463 | } |
464 | |
465 | // Wrong return type. |
466 | struct WRT : IL { |
467 | IL &operator=(const WRT &); |
468 | }; |
469 | IL &WRT::operator=(const WRT &Other) { |
470 | return *this; |
471 | } |
472 | |
473 | // Wrong return type. |
474 | struct WRTConstRef { |
475 | const WRTConstRef &operator = (const WRTConstRef &) { |
476 | return *this; |
477 | } |
478 | }; |
479 | |
480 | // Try-catch. |
481 | struct ITC { |
482 | ITC(const ITC &Other) |
483 | try : Field(Other.Field) { |
484 | } catch (...) { |
485 | } |
486 | ITC &operator=(const ITC &Other) try { |
487 | Field = Other.Field; |
488 | } catch (...) { |
489 | } |
490 | int Field; |
491 | }; |
492 | |
493 | struct OTC { |
494 | OTC(const OTC &); |
495 | OTC &operator=(const OTC &); |
496 | int Field; |
497 | }; |
498 | OTC::OTC(const OTC &Other) try : Field(Other.Field) { |
499 | } catch (...) { |
500 | } |
501 | OTC &OTC::operator=(const OTC &Other) try { |
502 | Field = Other.Field; |
503 | } catch (...) { |
504 | } |
505 | |
506 | // FIXME: the check is not able to detect exception specification. |
507 | // noexcept(true). |
508 | struct NET { |
509 | // This is the default. |
510 | //NET(const NET &Other) noexcept {} |
511 | NET &operator=(const NET &Other) noexcept; |
512 | }; |
513 | //NET &NET::operator=(const NET &Other) noexcept { return *this; } |
514 | |
515 | // noexcept(false). |
516 | struct NEF { |
517 | // This is the default. |
518 | //NEF(const NEF &Other) noexcept(false) {} |
519 | NEF &operator=(const NEF &Other) noexcept(false); |
520 | }; |
521 | //NEF &NEF::operator=(const NEF &Other) noexcept(false) { return *this; } |
522 | |
523 | #define STRUCT_WITH_COPY_CONSTRUCT(_base, _type) \ |
524 | struct _type { \ |
525 | _type(const _type &v) : value(v.value) {} \ |
526 | _base value; \ |
527 | }; |
528 | |
529 | STRUCT_WITH_COPY_CONSTRUCT(unsigned char, Hex8CopyConstruct) |
530 | // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy constructor |
531 | // CHECK-MESSAGES: :[[@LINE-6]]:44: note: |
532 | |
533 | #define STRUCT_WITH_COPY_ASSIGN(_base, _type) \ |
534 | struct _type { \ |
535 | _type &operator=(const _type &rhs) { \ |
536 | value = rhs.value; \ |
537 | return *this; \ |
538 | } \ |
539 | _base value; \ |
540 | }; |
541 | |
542 | STRUCT_WITH_COPY_ASSIGN(unsigned char, Hex8CopyAssign) |
543 | // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy-assignment operator |
544 | // CHECK-MESSAGES: :[[@LINE-9]]:40: note: |
545 | |
546 | // Use of braces |
547 | struct UOB{ |
548 | UOB(const UOB &Other):j{Other.j}{} |
549 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default] |
550 | // CHECK-FIXES: UOB(const UOB &Other)= default; |
551 | int j; |
552 | }; |
553 |
Definitions
- OL
- OL
- operator=
- IL
- IL
- operator=
- NU
- NU
- operator=
- SU
- SU
- operator=
- WT
- WT
- operator=
- Qual
- Qual
- WI
- WI
- operator=
- MF
- MF
- operator=
- Comments
- Comments
- MoreComments
- MoreComments
- ColonInComment
- ColonInComment
- Empty
- Empty
- operator=
- BF
- BF
- BF
- operator=
- BC
- BC
- operator=
- BCWM
- BCWM
- operator=
- MBC
- MBC
- operator=
- BCIP
- BCIP
- operator=
- VA
- VB
- VBC
- VBC
- operator=
- IB
- IB
- operator=
- Template
- Template
- Template
- operator=
- T1
- DT1
- DT1
- DT1
- operator=
- Dt1
- DT2
- DT2
- DT2
- operator=
- T
- Dt2
- DA
- DA
- operator=
- DA2
- DA2
- DI
- DI
- SIB
- SIB
- operator=
- CIB
- CIB
- operator=
- NCRef
- NCRef
- operator=
- IAD
- IAD
- operator=
- OAD
- OAD
- operator=
- ID
- ID
- operator=
- NRef
- operator=
- RVR
- RVR
- operator=
- SF
- foo
- NR
- operator=
- RM
- operator=
- WRV
- operator=
- WRT
- operator=
- WRTConstRef
- operator =
- ITC
- ITC
- operator=
- OTC
- OTC
- operator=
- NET
- NEF
- Hex8CopyConstruct
- Hex8CopyConstruct
- Hex8CopyAssign
- UOB
Improve your Profiling and Debugging skills
Find out more