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