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.
6struct OL {
7 OL(const OL &);
8 OL &operator=(const OL &);
9 int Field;
10};
11OL::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;
14OL &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.
22struct 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.
36union 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.
48struct 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.
62struct WT {
63 WT(const IL &Other) {}
64 WT &operator=(const IL &);
65};
66WT &WT::operator=(const IL &Other) { return *this; }
67
68// Qualifiers.
69struct 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.
86struct WI {
87 WI(const WI &Other) : Field1(Other.Field1), Field2(Other.Field1) {}
88 WI &operator=(const WI &);
89 int Field1, Field2;
90};
91WI &WI::operator=(const WI &Other) {
92 Field1 = Other.Field1;
93 Field2 = Other.Field1;
94 return *this;
95}
96
97// Missing field.
98struct MF {
99 MF(const MF &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
100 MF &operator=(const MF &);
101 int Field1, Field2, Field3;
102};
103MF &MF::operator=(const MF &Other) {
104 Field1 = Other.Field1;
105 Field2 = Other.Field2;
106 return *this;
107}
108
109struct 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
117struct 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
126struct 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).
134struct 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};
140Empty &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.
145struct 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};
161BF &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.
172struct 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};
178BC &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.
188struct 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};
195BCWM &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.
205struct MBC : IL, OL, BF {
206 MBC(const MBC &Other) : IL(Other), OL(Other) {}
207 MBC &operator=(const MBC &);
208};
209MBC &MBC::operator=(const MBC &Other) {
210 IL::operator=(Other);
211 OL::operator=(Other);
212 return *this;
213}
214
215// Base classes, incorrect parameter.
216struct BCIP : BCWM, BF {
217 BCIP(const BCIP &Other) : BCWM(Other), BF(Other.Bf) {}
218 BCIP &operator=(const BCIP &);
219};
220BCIP &BCIP::operator=(const BCIP &Other) {
221 BCWM::operator=(Other);
222 BF::operator=(Other: Other.Bf);
223 return *this;
224}
225
226// Virtual base classes.
227struct VA : virtual OL {};
228struct VB : virtual OL {};
229struct 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};
238VBC &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.
248struct IB : VBC {
249 IB(const IB &Other) : OL(Other), VBC(Other) {}
250 IB &operator=(const IB &);
251};
252IB &IB::operator=(const IB &Other) {
253 OL::operator=(Other);
254 VBC::operator=(Other);
255 return *this;
256}
257
258// Class template.
259template <class T>
260struct 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};
269template <class T>
270Template<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
277Template<int> T1;
278
279
280// Dependent types.
281template <class T>
282struct DT1 {
283 DT1() = default;
284 DT1(const DT1 &Other) : Field(Other.Field) {}
285 DT1 &operator=(const DT1 &);
286 T Field;
287};
288template <class T>
289DT1<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
296DT1<int> Dt1;
297
298template <class T>
299struct 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};
306template <class T>
307DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
308 Field = Other.Field;
309 Dependent = Other.Dependent;
310 return *this;
311}
312struct 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
318DT2<T> Dt2;
319
320// Default arguments.
321struct 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.
329DA &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
337struct 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.
343struct 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.
351void foo();
352struct SIB {
353 SIB(const SIB &Other) : Field(Other.Field) { foo(); }
354 SIB &operator=(const SIB &);
355 int Field;
356};
357SIB &SIB::operator=(const SIB &Other) {
358 Field = Other.Field;
359 foo();
360 return *this;
361}
362
363// Comment inside body.
364struct 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};
371CIB &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.
380struct 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};
387NCRef &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.
396struct IAD {
397 IAD(const IAD &Other) = default;
398 IAD &operator=(const IAD &Other) = default;
399};
400
401struct OAD {
402 OAD(const OAD &Other);
403 OAD &operator=(const OAD &);
404};
405OAD::OAD(const OAD &Other) = default;
406OAD &OAD::operator=(const OAD &Other) = default;
407
408// Deleted.
409struct ID {
410 ID(const ID &Other) = delete;
411 ID &operator=(const ID &Other) = delete;
412};
413
414// Non-reference parameter.
415struct NRef {
416 NRef &operator=(NRef Other);
417 int Field1;
418};
419NRef &NRef::operator=(NRef Other) {
420 Field1 = Other.Field1;
421 return *this;
422}
423
424// RValue reference parameter.
425struct RVR {
426 RVR(RVR &&Other) {}
427 RVR &operator=(RVR &&);
428};
429RVR &RVR::operator=(RVR &&Other) { return *this; }
430
431// Similar function.
432struct SF {
433 SF &foo(const SF &);
434 int Field1;
435};
436SF &SF::foo(const SF &Other) {
437 Field1 = Other.Field1;
438 return *this;
439}
440
441// No return.
442struct NR {
443 NR &operator=(const NR &);
444};
445NR &NR::operator=(const NR &Other) {}
446
447// Return misplaced.
448struct RM {
449 RM &operator=(const RM &);
450 int Field;
451};
452RM &RM::operator=(const RM &Other) {
453 return *this;
454 Field = Other.Field;
455}
456
457// Wrong return value.
458struct WRV {
459 WRV &operator=(WRV &);
460};
461WRV &WRV::operator=(WRV &Other) {
462 return Other;
463}
464
465// Wrong return type.
466struct WRT : IL {
467 IL &operator=(const WRT &);
468};
469IL &WRT::operator=(const WRT &Other) {
470 return *this;
471}
472
473// Wrong return type.
474struct WRTConstRef {
475 const WRTConstRef &operator = (const WRTConstRef &) {
476 return *this;
477 }
478};
479
480// Try-catch.
481struct 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
493struct OTC {
494 OTC(const OTC &);
495 OTC &operator=(const OTC &);
496 int Field;
497};
498OTC::OTC(const OTC &Other) try : Field(Other.Field) {
499} catch (...) {
500}
501OTC &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).
508struct 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).
516struct 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
529STRUCT_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
542STRUCT_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
547struct 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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp