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