1 // RUN: %check_clang_tidy %s modernize-use-equals-default %t -- \
2 // RUN: -config="{CheckOptions: {modernize-use-equals-default.IgnoreMacros: false}}" \
3 // RUN: -- -fno-delayed-template-parsing -fexceptions
4
5 // Out of line definition.
6 struct OL {
7 OL(const OL &);
8 OL &operator=(const OL &);
9 int Field;
10 };
OL(const OL & Other)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;
operator =(const OL & Other)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 {
ILIL23 IL(const IL &Other) : Field(Other.Field) {}
24 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
25 // CHECK-FIXES: IL(const IL &Other) = default;
operator =IL26 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 {
NU(const NU & Other)37 NU(const NU &Other) : Field(Other.Field) {}
38 // CHECK-FIXES: NU(const NU &Other) :
operator =(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 {
SUSU49 SU(const SU &Other) : Field(Other.Field) {}
50 // CHECK-FIXES: SU(const SU &Other) :
operator =SU51 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 {
WTWT63 WT(const IL &Other) {}
64 WT &operator=(const IL &);
65 };
operator =(const IL & Other)66 WT &WT::operator=(const IL &Other) { return *this; }
67
68 // Qualifiers.
69 struct Qual {
QualQual70 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 {
WIWI87 WI(const WI &Other) : Field1(Other.Field1), Field2(Other.Field1) {}
88 WI &operator=(const WI &);
89 int Field1, Field2;
90 };
operator =(const WI & Other)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 {
MFMF99 MF(const MF &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
100 MF &operator=(const MF &);
101 int Field1, Field2, Field3;
102 };
operator =(const MF & Other)103 MF &MF::operator=(const MF &Other) {
104 Field1 = Other.Field1;
105 Field2 = Other.Field2;
106 return *this;
107 }
108
109 struct Comments {
CommentsComments110 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 {
MoreCommentsMoreComments118 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 {
ColonInCommentColonInComment127 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 {
EmptyEmpty135 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 };
operator =(const Empty & Other)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;
BFBF147 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 };
operator =(const BF & Other)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 {
BCBC173 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 };
operator =(const BC & Other)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 {
BCWMBCWM189 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 };
operator =(const BCWM & Other)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 {
MBCMBC206 MBC(const MBC &Other) : IL(Other), OL(Other) {}
207 MBC &operator=(const MBC &);
208 };
operator =(const MBC & Other)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 {
BCIPBCIP217 BCIP(const BCIP &Other) : BCWM(Other), BF(Other.Bf) {}
218 BCIP &operator=(const BCIP &);
219 };
operator =(const BCIP & Other)220 BCIP &BCIP::operator=(const BCIP &Other) {
221 BCWM::operator=(Other);
222 BF::operator=(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).
VBCVBC233 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 };
operator =(const VBC & Other)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 {
IBIB249 IB(const IB &Other) : OL(Other), VBC(Other) {}
250 IB &operator=(const IB &);
251 };
operator =(const IB & Other)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;
TemplateTemplate262 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>
operator =(const Template<T> & Other)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;
DT1DT1284 DT1(const DT1 &Other) : Field(Other.Field) {}
285 DT1 &operator=(const DT1 &);
286 T Field;
287 };
288 template <class T>
operator =(const DT1<T> & Other)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;
DT2DT2301 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>
operator =(const DT2<T> & Other)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);
DADA323 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.
operator =(const DA & Other)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.
DA2DA2339 DA2(const DA &Other, int Def = 0) {}
340 };
341
342 // Default initialization.
343 struct DI {
DIDI344 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 {
SIBSIB353 SIB(const SIB &Other) : Field(Other.Field) { foo(); }
354 SIB &operator=(const SIB &);
355 int Field;
356 };
operator =(const SIB & Other)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 {
CIBCIB365 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 };
operator =(const CIB & Other)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 {
NCRefNCRef381 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 };
operator =(NCRef & Other)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 };
operator =(NRef Other)419 NRef &NRef::operator=(NRef Other) {
420 Field1 = Other.Field1;
421 return *this;
422 }
423
424 // RValue reference parameter.
425 struct RVR {
RVRRVR426 RVR(RVR &&Other) {}
427 RVR &operator=(RVR &&);
428 };
operator =(RVR && Other)429 RVR &RVR::operator=(RVR &&Other) { return *this; }
430
431 // Similar function.
432 struct SF {
433 SF &foo(const SF &);
434 int Field1;
435 };
foo(const SF & Other)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 };
operator =(const NR & Other)445 NR &NR::operator=(const NR &Other) {}
446
447 // Return misplaced.
448 struct RM {
449 RM &operator=(const RM &);
450 int Field;
451 };
operator =(const RM & Other)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 };
operator =(WRV & Other)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 };
operator =(const WRT & Other)469 IL &WRT::operator=(const WRT &Other) {
470 return *this;
471 }
472
473 // Wrong return type.
474 struct WRTConstRef {
operator =WRTConstRef475 const WRTConstRef &operator = (const WRTConstRef &) {
476 return *this;
477 }
478 };
479
480 // Try-catch.
481 struct ITC {
ITCITC482 ITC(const ITC &Other)
483 try : Field(Other.Field) {
484 } catch (...) {
485 }
operator =ITC486 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 };
OTC(const OTC & Other)498 OTC::OTC(const OTC &Other) try : Field(Other.Field) {
499 } catch (...) {
500 }
operator =(const OTC & Other)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{
UOBUOB548 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