xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default-copy.cpp (revision 8009bbec59d1c5d47ae06c431647ebee6d886ff2)
189a1d03eSRichard // RUN: %check_clang_tidy %s modernize-use-equals-default %t -- \
2e8a3ddafSNathan James // RUN:   -config="{CheckOptions: {modernize-use-equals-default.IgnoreMacros: false}}" \
389a1d03eSRichard // RUN:   -- -fno-delayed-template-parsing -fexceptions
489a1d03eSRichard 
589a1d03eSRichard // Out of line definition.
689a1d03eSRichard struct OL {
789a1d03eSRichard   OL(const OL &);
889a1d03eSRichard   OL &operator=(const OL &);
989a1d03eSRichard   int Field;
1089a1d03eSRichard };
OL(const OL & Other)1189a1d03eSRichard OL::OL(const OL &Other) : Field(Other.Field) {}
1289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default]
1389a1d03eSRichard // CHECK-FIXES: OL::OL(const OL &Other)  = default;
operator =(const OL & Other)1489a1d03eSRichard OL &OL::operator=(const OL &Other) {
1589a1d03eSRichard   Field = Other.Field;
1689a1d03eSRichard   return *this;
1789a1d03eSRichard }
1889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: use '= default' to define a trivial copy-assignment operator [modernize-use-equals-default]
1989a1d03eSRichard // CHECK-FIXES: OL &OL::operator=(const OL &Other) = default;
2089a1d03eSRichard 
2189a1d03eSRichard // Inline.
2289a1d03eSRichard struct IL {
ILIL2389a1d03eSRichard   IL(const IL &Other) : Field(Other.Field) {}
2489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
2589a1d03eSRichard   // CHECK-FIXES: IL(const IL &Other)  = default;
operator =IL2689a1d03eSRichard   IL &operator=(const IL &Other) {
2789a1d03eSRichard     Field = Other.Field;
2889a1d03eSRichard     return *this;
2989a1d03eSRichard   }
3089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: use '= default'
3189a1d03eSRichard   // CHECK-FIXES: IL &operator=(const IL &Other) = default;
3289a1d03eSRichard   int Field;
3389a1d03eSRichard };
3489a1d03eSRichard 
35083e3a17SAlexander Shaposhnikov // Skip unions.
36083e3a17SAlexander Shaposhnikov union NU {
NU(const NU & Other)37083e3a17SAlexander Shaposhnikov   NU(const NU &Other) : Field(Other.Field) {}
38083e3a17SAlexander Shaposhnikov   // CHECK-FIXES: NU(const NU &Other) :
operator =(const NU & Other)39083e3a17SAlexander Shaposhnikov   NU &operator=(const NU &Other) {
40083e3a17SAlexander Shaposhnikov     Field = Other.Field;
41083e3a17SAlexander Shaposhnikov     return *this;
42083e3a17SAlexander Shaposhnikov   }
43083e3a17SAlexander Shaposhnikov   // CHECK-FIXES: NU &operator=(const NU &Other) {
44083e3a17SAlexander Shaposhnikov   IL Field;
45083e3a17SAlexander Shaposhnikov };
46083e3a17SAlexander Shaposhnikov 
4744503482SAlexander Shaposhnikov // Skip structs/classes containing anonymous unions.
4844503482SAlexander Shaposhnikov struct SU {
SUSU4944503482SAlexander Shaposhnikov   SU(const SU &Other) : Field(Other.Field) {}
5044503482SAlexander Shaposhnikov   // CHECK-FIXES: SU(const SU &Other) :
operator =SU5144503482SAlexander Shaposhnikov   SU &operator=(const SU &Other) {
5244503482SAlexander Shaposhnikov     Field = Other.Field;
5344503482SAlexander Shaposhnikov     return *this;
5444503482SAlexander Shaposhnikov   }
5544503482SAlexander Shaposhnikov   // CHECK-FIXES: SU &operator=(const SU &Other) {
5644503482SAlexander Shaposhnikov   union {
5744503482SAlexander Shaposhnikov     IL Field;
5844503482SAlexander Shaposhnikov   };
5944503482SAlexander Shaposhnikov };
6044503482SAlexander Shaposhnikov 
6189a1d03eSRichard // Wrong type.
6289a1d03eSRichard struct WT {
WTWT6389a1d03eSRichard   WT(const IL &Other) {}
6489a1d03eSRichard   WT &operator=(const IL &);
6589a1d03eSRichard };
operator =(const IL & Other)6689a1d03eSRichard WT &WT::operator=(const IL &Other) { return *this; }
6789a1d03eSRichard 
6889a1d03eSRichard // Qualifiers.
6989a1d03eSRichard struct Qual {
QualQual7089a1d03eSRichard   Qual(const Qual &Other) : Field(Other.Field), Volatile(Other.Volatile),
7189a1d03eSRichard                             Mutable(Other.Mutable), Reference(Other.Reference),
7289a1d03eSRichard                             Const(Other.Const) {}
7389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
7489a1d03eSRichard   // CHECK-FIXES: Qual(const Qual &Other)
7589a1d03eSRichard   // CHECK-FIXES:                          = default;
7689a1d03eSRichard 
7789a1d03eSRichard   int Field;
7889a1d03eSRichard   volatile char Volatile;
7989a1d03eSRichard   mutable bool Mutable;
8089a1d03eSRichard   const OL &Reference; // This makes this class non-assignable.
8189a1d03eSRichard   const IL Const;      // This also makes this class non-assignable.
8289a1d03eSRichard   static int Static;
8389a1d03eSRichard };
8489a1d03eSRichard 
8589a1d03eSRichard // Wrong init arguments.
8689a1d03eSRichard struct WI {
WIWI8789a1d03eSRichard   WI(const WI &Other) : Field1(Other.Field1), Field2(Other.Field1) {}
8889a1d03eSRichard   WI &operator=(const WI &);
8989a1d03eSRichard   int Field1, Field2;
9089a1d03eSRichard };
operator =(const WI & Other)9189a1d03eSRichard WI &WI::operator=(const WI &Other) {
9289a1d03eSRichard   Field1 = Other.Field1;
9389a1d03eSRichard   Field2 = Other.Field1;
9489a1d03eSRichard   return *this;
9589a1d03eSRichard }
9689a1d03eSRichard 
9789a1d03eSRichard // Missing field.
9889a1d03eSRichard struct MF {
MFMF9989a1d03eSRichard   MF(const MF &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
10089a1d03eSRichard   MF &operator=(const MF &);
10189a1d03eSRichard   int Field1, Field2, Field3;
10289a1d03eSRichard };
operator =(const MF & Other)10389a1d03eSRichard MF &MF::operator=(const MF &Other) {
10489a1d03eSRichard   Field1 = Other.Field1;
10589a1d03eSRichard   Field2 = Other.Field2;
10689a1d03eSRichard   return *this;
10789a1d03eSRichard }
10889a1d03eSRichard 
10989a1d03eSRichard struct Comments {
CommentsComments11089a1d03eSRichard   Comments(const Comments &Other)
11189a1d03eSRichard       /* don't delete */ : /* this comment */ Field(Other.Field) {}
11289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
11389a1d03eSRichard   // CHECK-FIXES: /* don't delete */  = default;
11489a1d03eSRichard   int Field;
11589a1d03eSRichard };
11689a1d03eSRichard 
11789a1d03eSRichard struct MoreComments {
MoreCommentsMoreComments11889a1d03eSRichard   MoreComments(const MoreComments &Other) /* this comment is OK */
11989a1d03eSRichard       : Field(Other.Field) {}
12089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
12189a1d03eSRichard   // CHECK-FIXES: MoreComments(const MoreComments &Other) /* this comment is OK */
12289a1d03eSRichard   // CHECK-FIXES-NEXT: = default;
12389a1d03eSRichard   int Field;
12489a1d03eSRichard };
12589a1d03eSRichard 
12689a1d03eSRichard struct ColonInComment {
ColonInCommentColonInComment12789a1d03eSRichard   ColonInComment(const ColonInComment &Other) /* : */ : Field(Other.Field) {}
12889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
12989a1d03eSRichard   // CHECK-FIXES: ColonInComment(const ColonInComment &Other) /* : */  = default;
13089a1d03eSRichard   int Field;
13189a1d03eSRichard };
13289a1d03eSRichard 
13389a1d03eSRichard // No members or bases (in particular, no colon).
13489a1d03eSRichard struct Empty {
EmptyEmpty13589a1d03eSRichard   Empty(const Empty &Other) {}
13689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
13789a1d03eSRichard   // CHECK-FIXES: Empty(const Empty &Other) = default;
13889a1d03eSRichard   Empty &operator=(const Empty &);
13989a1d03eSRichard };
operator =(const Empty & Other)14089a1d03eSRichard Empty &Empty::operator=(const Empty &Other) { return *this; }
14189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use '= default'
14289a1d03eSRichard // CHECK-FIXES: Empty &Empty::operator=(const Empty &Other) = default;
14389a1d03eSRichard 
14489a1d03eSRichard // Bit fields.
14589a1d03eSRichard struct BF {
14689a1d03eSRichard   BF() = default;
BFBF14789a1d03eSRichard   BF(const BF &Other) : Field1(Other.Field1), Field2(Other.Field2), Field3(Other.Field3),
14889a1d03eSRichard                         Field4(Other.Field4) {};
14989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
15089a1d03eSRichard   // CHECK-FIXES: BF(const BF &Other) {{$}}
15189a1d03eSRichard   // CHECK-FIXES:                     = default;
15289a1d03eSRichard   BF &operator=(const BF &);
15389a1d03eSRichard 
15489a1d03eSRichard   unsigned Field1 : 3;
15589a1d03eSRichard   int : 7;
15689a1d03eSRichard   char Field2 : 6;
15789a1d03eSRichard   int : 0;
15889a1d03eSRichard   int Field3 : 24;
15989a1d03eSRichard   unsigned char Field4;
16089a1d03eSRichard };
operator =(const BF & Other)16189a1d03eSRichard BF &BF::operator=(const BF &Other) {
16289a1d03eSRichard   Field1 = Other.Field1;
16389a1d03eSRichard   Field2 = Other.Field2;
16489a1d03eSRichard   Field3 = Other.Field3;
16589a1d03eSRichard   Field4 = Other.Field4;
16689a1d03eSRichard   return *this;
16789a1d03eSRichard }
16889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-7]]:9: warning: use '= default'
16989a1d03eSRichard // CHECK-FIXES: BF &BF::operator=(const BF &Other) = default;
17089a1d03eSRichard 
17189a1d03eSRichard // Base classes.
17289a1d03eSRichard struct BC : IL, OL, BF {
BCBC17389a1d03eSRichard   BC(const BC &Other) : IL(Other), OL(Other), BF(Other) {}
17489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
17589a1d03eSRichard   // CHECK-FIXES: BC(const BC &Other)  = default;
17689a1d03eSRichard   BC &operator=(const BC &Other);
17789a1d03eSRichard };
operator =(const BC & Other)17889a1d03eSRichard BC &BC::operator=(const BC &Other) {
17989a1d03eSRichard   IL::operator=(Other);
18089a1d03eSRichard   OL::operator=(Other);
18189a1d03eSRichard   BF::operator=(Other);
18289a1d03eSRichard   return *this;
18389a1d03eSRichard }
18489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-6]]:9: warning: use '= default'
18589a1d03eSRichard // CHECK-FIXES: BC &BC::operator=(const BC &Other) = default;
18689a1d03eSRichard 
18789a1d03eSRichard // Base classes with member.
18889a1d03eSRichard struct BCWM : IL, OL {
BCWMBCWM18989a1d03eSRichard   BCWM(const BCWM &Other) : IL(Other), OL(Other), Bf(Other.Bf) {}
19089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
19189a1d03eSRichard   // CHECK-FIXES: BCWM(const BCWM &Other)  = default;
19289a1d03eSRichard   BCWM &operator=(const BCWM &);
19389a1d03eSRichard   BF Bf;
19489a1d03eSRichard };
operator =(const BCWM & Other)19589a1d03eSRichard BCWM &BCWM::operator=(const BCWM &Other) {
19689a1d03eSRichard   IL::operator=(Other);
19789a1d03eSRichard   OL::operator=(Other);
19889a1d03eSRichard   Bf = Other.Bf;
19989a1d03eSRichard   return *this;
20089a1d03eSRichard }
20189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-6]]:13: warning: use '= default'
20289a1d03eSRichard // CHECK-FIXES: BCWM &BCWM::operator=(const BCWM &Other) = default;
20389a1d03eSRichard 
20489a1d03eSRichard // Missing base class.
20589a1d03eSRichard struct MBC : IL, OL, BF {
MBCMBC20689a1d03eSRichard   MBC(const MBC &Other) : IL(Other), OL(Other) {}
20789a1d03eSRichard   MBC &operator=(const MBC &);
20889a1d03eSRichard };
operator =(const MBC & Other)20989a1d03eSRichard MBC &MBC::operator=(const MBC &Other) {
21089a1d03eSRichard   IL::operator=(Other);
21189a1d03eSRichard   OL::operator=(Other);
21289a1d03eSRichard   return *this;
21389a1d03eSRichard }
21489a1d03eSRichard 
21589a1d03eSRichard // Base classes, incorrect parameter.
21689a1d03eSRichard struct BCIP : BCWM, BF {
BCIPBCIP21789a1d03eSRichard   BCIP(const BCIP &Other) : BCWM(Other), BF(Other.Bf) {}
21889a1d03eSRichard   BCIP &operator=(const BCIP &);
21989a1d03eSRichard };
operator =(const BCIP & Other)22089a1d03eSRichard BCIP &BCIP::operator=(const BCIP &Other) {
22189a1d03eSRichard   BCWM::operator=(Other);
22289a1d03eSRichard   BF::operator=(Other.Bf);
22389a1d03eSRichard   return *this;
22489a1d03eSRichard }
22589a1d03eSRichard 
22689a1d03eSRichard // Virtual base classes.
22789a1d03eSRichard struct VA : virtual OL {};
22889a1d03eSRichard struct VB : virtual OL {};
22989a1d03eSRichard struct VBC : VA, VB, virtual OL {
23089a1d03eSRichard   // OL is the first thing that is going to be initialized, despite the fact
23189a1d03eSRichard   // that it is the last in the list of bases, because it is virtual and there
23289a1d03eSRichard   // is a virtual OL at the beginning of VA (which is the same).
VBCVBC23389a1d03eSRichard   VBC(const VBC &Other) : OL(Other), VA(Other), VB(Other) {}
23489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
23589a1d03eSRichard   // CHECK-FIXES: VBC(const VBC &Other)  = default;
23689a1d03eSRichard   VBC &operator=(const VBC &Other);
23789a1d03eSRichard };
operator =(const VBC & Other)23889a1d03eSRichard VBC &VBC::operator=(const VBC &Other) {
23989a1d03eSRichard   OL::operator=(Other);
24089a1d03eSRichard   VA::operator=(Other);
24189a1d03eSRichard   VB::operator=(Other);
24289a1d03eSRichard   return *this;
24389a1d03eSRichard }
24489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-6]]:11: warning: use '= default'
24589a1d03eSRichard // CHECK-FIXES: VBC &VBC::operator=(const VBC &Other) = default;
24689a1d03eSRichard 
24789a1d03eSRichard // Indirect base.
24889a1d03eSRichard struct IB : VBC {
IBIB24989a1d03eSRichard   IB(const IB &Other) : OL(Other), VBC(Other) {}
25089a1d03eSRichard   IB &operator=(const IB &);
25189a1d03eSRichard };
operator =(const IB & Other)25289a1d03eSRichard IB &IB::operator=(const IB &Other) {
25389a1d03eSRichard   OL::operator=(Other);
25489a1d03eSRichard   VBC::operator=(Other);
25589a1d03eSRichard   return *this;
25689a1d03eSRichard }
25789a1d03eSRichard 
25889a1d03eSRichard // Class template.
25989a1d03eSRichard template <class T>
26089a1d03eSRichard struct Template {
26189a1d03eSRichard   Template() = default;
TemplateTemplate26289a1d03eSRichard   Template(const Template &Other) : Field(Other.Field) {}
263*8009bbecSKrystian Stasiowski   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
264*8009bbecSKrystian Stasiowski   // CHECK-FIXES: Template(const Template &Other)  = default;
26589a1d03eSRichard   Template &operator=(const Template &Other);
26689a1d03eSRichard   void foo(const T &t);
26789a1d03eSRichard   int Field;
26889a1d03eSRichard };
26989a1d03eSRichard template <class T>
operator =(const Template<T> & Other)27089a1d03eSRichard Template<T> &Template<T>::operator=(const Template<T> &Other) {
27189a1d03eSRichard   Field = Other.Field;
27289a1d03eSRichard   return *this;
27389a1d03eSRichard }
274*8009bbecSKrystian Stasiowski // CHECK-MESSAGES: :[[@LINE-4]]:27: warning: use '= default'
275*8009bbecSKrystian Stasiowski // CHECK-FIXES: Template<T> &Template<T>::operator=(const Template<T> &Other) = default;
276*8009bbecSKrystian Stasiowski 
27789a1d03eSRichard Template<int> T1;
27889a1d03eSRichard 
279*8009bbecSKrystian Stasiowski 
28089a1d03eSRichard // Dependent types.
28189a1d03eSRichard template <class T>
28289a1d03eSRichard struct DT1 {
28389a1d03eSRichard   DT1() = default;
DT1DT128489a1d03eSRichard   DT1(const DT1 &Other) : Field(Other.Field) {}
28589a1d03eSRichard   DT1 &operator=(const DT1 &);
28689a1d03eSRichard   T Field;
28789a1d03eSRichard };
28889a1d03eSRichard template <class T>
operator =(const DT1<T> & Other)28989a1d03eSRichard DT1<T> &DT1<T>::operator=(const DT1<T> &Other) {
29089a1d03eSRichard   Field = Other.Field;
29189a1d03eSRichard   return *this;
29289a1d03eSRichard }
293*8009bbecSKrystian Stasiowski // CHECK-MESSAGES: :[[@LINE-4]]:17: warning: use '= default'
294*8009bbecSKrystian Stasiowski // CHECK-FIXES: DT1<T> &DT1<T>::operator=(const DT1<T> &Other) = default;
295*8009bbecSKrystian Stasiowski 
29689a1d03eSRichard DT1<int> Dt1;
29789a1d03eSRichard 
29889a1d03eSRichard template <class T>
29989a1d03eSRichard struct DT2 {
30089a1d03eSRichard   DT2() = default;
DT2DT230189a1d03eSRichard   DT2(const DT2 &Other) : Field(Other.Field), Dependent(Other.Dependent) {}
30289a1d03eSRichard   DT2 &operator=(const DT2 &);
30389a1d03eSRichard   T Field;
30489a1d03eSRichard   typename T::TT Dependent;
30589a1d03eSRichard };
30689a1d03eSRichard template <class T>
operator =(const DT2<T> & Other)30789a1d03eSRichard DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
30889a1d03eSRichard   Field = Other.Field;
30989a1d03eSRichard   Dependent = Other.Dependent;
31089a1d03eSRichard   return *this;
31189a1d03eSRichard }
31289a1d03eSRichard struct T {
31389a1d03eSRichard   typedef int TT;
31489a1d03eSRichard };
315*8009bbecSKrystian Stasiowski // CHECK-MESSAGES: :[[@LINE-8]]:17: warning: use '= default'
316*8009bbecSKrystian Stasiowski // CHECK-FIXES: DT2<T> &DT2<T>::operator=(const DT2<T> &Other) = default;
317*8009bbecSKrystian Stasiowski 
31889a1d03eSRichard DT2<T> Dt2;
31989a1d03eSRichard 
32089a1d03eSRichard // Default arguments.
32189a1d03eSRichard struct DA {
32289a1d03eSRichard   DA(int Int);
DADA32389a1d03eSRichard   DA(const DA &Other = DA(0)) : Field1(Other.Field1), Field2(Other.Field2) {}
32489a1d03eSRichard   DA &operator=(const DA &);
32589a1d03eSRichard   int Field1;
32689a1d03eSRichard   char Field2;
32789a1d03eSRichard };
32889a1d03eSRichard // Overloaded operator= cannot have a default argument.
operator =(const DA & Other)32989a1d03eSRichard DA &DA::operator=(const DA &Other) {
33089a1d03eSRichard   Field1 = Other.Field1;
33189a1d03eSRichard   Field2 = Other.Field2;
33289a1d03eSRichard   return *this;
33389a1d03eSRichard }
33489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: use '= default'
33589a1d03eSRichard // CHECK-FIXES: DA &DA::operator=(const DA &Other) = default;
33689a1d03eSRichard 
33789a1d03eSRichard struct DA2 {
33889a1d03eSRichard   // Can be used as copy-constructor but cannot be explicitly defaulted.
DA2DA233989a1d03eSRichard   DA2(const DA &Other, int Def = 0) {}
34089a1d03eSRichard };
34189a1d03eSRichard 
34289a1d03eSRichard // Default initialization.
34389a1d03eSRichard struct DI {
DIDI34489a1d03eSRichard   DI(const DI &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
34589a1d03eSRichard   int Field1;
34689a1d03eSRichard   int Field2 = 0;
34789a1d03eSRichard   int Fiedl3;
34889a1d03eSRichard };
34989a1d03eSRichard 
35089a1d03eSRichard // Statement inside body.
35189a1d03eSRichard void foo();
35289a1d03eSRichard struct SIB {
SIBSIB35389a1d03eSRichard   SIB(const SIB &Other) : Field(Other.Field) { foo(); }
35489a1d03eSRichard   SIB &operator=(const SIB &);
35589a1d03eSRichard   int Field;
35689a1d03eSRichard };
operator =(const SIB & Other)35789a1d03eSRichard SIB &SIB::operator=(const SIB &Other) {
35889a1d03eSRichard   Field = Other.Field;
35989a1d03eSRichard   foo();
36089a1d03eSRichard   return *this;
36189a1d03eSRichard }
36289a1d03eSRichard 
36389a1d03eSRichard // Comment inside body.
36489a1d03eSRichard struct CIB {
CIBCIB36589a1d03eSRichard   CIB(const CIB &Other) : Field(Other.Field) { /* Don't erase this */
36689a1d03eSRichard   }
36789a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
36889a1d03eSRichard   CIB &operator=(const CIB &);
36989a1d03eSRichard   int Field;
37089a1d03eSRichard };
operator =(const CIB & Other)37189a1d03eSRichard CIB &CIB::operator=(const CIB &Other) {
37289a1d03eSRichard   Field = Other.Field;
37389a1d03eSRichard   // FIXME: don't erase this comment.
37489a1d03eSRichard   return *this;
37589a1d03eSRichard }
37689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:11: warning: use '= default'
37789a1d03eSRichard // CHECK-FIXES: CIB &CIB::operator=(const CIB &Other) = default;
37889a1d03eSRichard 
37989a1d03eSRichard // Take non-const reference as argument.
38089a1d03eSRichard struct NCRef {
NCRefNCRef38189a1d03eSRichard   NCRef(NCRef &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
38289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
38389a1d03eSRichard   // CHECK-FIXES: NCRef(NCRef &Other)  = default;
38489a1d03eSRichard   NCRef &operator=(NCRef &);
38589a1d03eSRichard   int Field1, Field2;
38689a1d03eSRichard };
operator =(NCRef & Other)38789a1d03eSRichard NCRef &NCRef::operator=(NCRef &Other) {
38889a1d03eSRichard   Field1 = Other.Field1;
38989a1d03eSRichard   Field2 = Other.Field2;
39089a1d03eSRichard   return *this;
39189a1d03eSRichard }
39289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:15: warning: use '= default'
39389a1d03eSRichard // CHECK-FIXES: NCRef &NCRef::operator=(NCRef &Other) = default;
39489a1d03eSRichard 
39589a1d03eSRichard // Already defaulted.
39689a1d03eSRichard struct IAD {
39789a1d03eSRichard   IAD(const IAD &Other) = default;
39889a1d03eSRichard   IAD &operator=(const IAD &Other) = default;
39989a1d03eSRichard };
40089a1d03eSRichard 
40189a1d03eSRichard struct OAD {
40289a1d03eSRichard   OAD(const OAD &Other);
40389a1d03eSRichard   OAD &operator=(const OAD &);
40489a1d03eSRichard };
40589a1d03eSRichard OAD::OAD(const OAD &Other) = default;
40689a1d03eSRichard OAD &OAD::operator=(const OAD &Other) = default;
40789a1d03eSRichard 
40889a1d03eSRichard // Deleted.
40989a1d03eSRichard struct ID {
41089a1d03eSRichard   ID(const ID &Other) = delete;
41189a1d03eSRichard   ID &operator=(const ID &Other) = delete;
41289a1d03eSRichard };
41389a1d03eSRichard 
41489a1d03eSRichard // Non-reference parameter.
41589a1d03eSRichard struct NRef {
41689a1d03eSRichard   NRef &operator=(NRef Other);
41789a1d03eSRichard   int Field1;
41889a1d03eSRichard };
operator =(NRef Other)41989a1d03eSRichard NRef &NRef::operator=(NRef Other) {
42089a1d03eSRichard   Field1 = Other.Field1;
42189a1d03eSRichard   return *this;
42289a1d03eSRichard }
42389a1d03eSRichard 
42489a1d03eSRichard // RValue reference parameter.
42589a1d03eSRichard struct RVR {
RVRRVR42689a1d03eSRichard   RVR(RVR &&Other) {}
42789a1d03eSRichard   RVR &operator=(RVR &&);
42889a1d03eSRichard };
operator =(RVR && Other)42989a1d03eSRichard RVR &RVR::operator=(RVR &&Other) { return *this; }
43089a1d03eSRichard 
43189a1d03eSRichard // Similar function.
43289a1d03eSRichard struct SF {
43389a1d03eSRichard   SF &foo(const SF &);
43489a1d03eSRichard   int Field1;
43589a1d03eSRichard };
foo(const SF & Other)43689a1d03eSRichard SF &SF::foo(const SF &Other) {
43789a1d03eSRichard   Field1 = Other.Field1;
43889a1d03eSRichard   return *this;
43989a1d03eSRichard }
44089a1d03eSRichard 
44189a1d03eSRichard // No return.
44289a1d03eSRichard struct NR {
44389a1d03eSRichard   NR &operator=(const NR &);
44489a1d03eSRichard };
operator =(const NR & Other)44589a1d03eSRichard NR &NR::operator=(const NR &Other) {}
44689a1d03eSRichard 
44789a1d03eSRichard // Return misplaced.
44889a1d03eSRichard struct RM {
44989a1d03eSRichard   RM &operator=(const RM &);
45089a1d03eSRichard   int Field;
45189a1d03eSRichard };
operator =(const RM & Other)45289a1d03eSRichard RM &RM::operator=(const RM &Other) {
45389a1d03eSRichard   return *this;
45489a1d03eSRichard   Field = Other.Field;
45589a1d03eSRichard }
45689a1d03eSRichard 
45789a1d03eSRichard // Wrong return value.
45889a1d03eSRichard struct WRV {
45989a1d03eSRichard   WRV &operator=(WRV &);
46089a1d03eSRichard };
operator =(WRV & Other)46189a1d03eSRichard WRV &WRV::operator=(WRV &Other) {
46289a1d03eSRichard   return Other;
46389a1d03eSRichard }
46489a1d03eSRichard 
46589a1d03eSRichard // Wrong return type.
46689a1d03eSRichard struct WRT : IL {
46789a1d03eSRichard   IL &operator=(const WRT &);
46889a1d03eSRichard };
operator =(const WRT & Other)46989a1d03eSRichard IL &WRT::operator=(const WRT &Other) {
47089a1d03eSRichard   return *this;
47189a1d03eSRichard }
47289a1d03eSRichard 
473a7395b86SAlexander Shaposhnikov // Wrong return type.
474a7395b86SAlexander Shaposhnikov struct WRTConstRef {
operator =WRTConstRef475a7395b86SAlexander Shaposhnikov   const WRTConstRef &operator = (const WRTConstRef &) {
476a7395b86SAlexander Shaposhnikov     return *this;
477a7395b86SAlexander Shaposhnikov   }
478a7395b86SAlexander Shaposhnikov };
479a7395b86SAlexander Shaposhnikov 
48089a1d03eSRichard // Try-catch.
48189a1d03eSRichard struct ITC {
ITCITC48289a1d03eSRichard   ITC(const ITC &Other)
48389a1d03eSRichard   try : Field(Other.Field) {
48489a1d03eSRichard   } catch (...) {
48589a1d03eSRichard   }
operator =ITC48689a1d03eSRichard   ITC &operator=(const ITC &Other) try {
48789a1d03eSRichard     Field = Other.Field;
48889a1d03eSRichard   } catch (...) {
48989a1d03eSRichard   }
49089a1d03eSRichard   int Field;
49189a1d03eSRichard };
49289a1d03eSRichard 
49389a1d03eSRichard struct OTC {
49489a1d03eSRichard   OTC(const OTC &);
49589a1d03eSRichard   OTC &operator=(const OTC &);
49689a1d03eSRichard   int Field;
49789a1d03eSRichard };
OTC(const OTC & Other)49889a1d03eSRichard OTC::OTC(const OTC &Other) try : Field(Other.Field) {
49989a1d03eSRichard } catch (...) {
50089a1d03eSRichard }
operator =(const OTC & Other)50189a1d03eSRichard OTC &OTC::operator=(const OTC &Other) try {
50289a1d03eSRichard   Field = Other.Field;
50389a1d03eSRichard } catch (...) {
50489a1d03eSRichard }
50589a1d03eSRichard 
50689a1d03eSRichard // FIXME: the check is not able to detect exception specification.
50789a1d03eSRichard // noexcept(true).
50889a1d03eSRichard struct NET {
50989a1d03eSRichard   // This is the default.
51089a1d03eSRichard   //NET(const NET &Other) noexcept {}
51189a1d03eSRichard   NET &operator=(const NET &Other) noexcept;
51289a1d03eSRichard };
51389a1d03eSRichard //NET &NET::operator=(const NET &Other) noexcept { return *this; }
51489a1d03eSRichard 
51589a1d03eSRichard // noexcept(false).
51689a1d03eSRichard struct NEF {
51789a1d03eSRichard   // This is the default.
51889a1d03eSRichard   //NEF(const NEF &Other) noexcept(false) {}
51989a1d03eSRichard   NEF &operator=(const NEF &Other) noexcept(false);
52089a1d03eSRichard };
52189a1d03eSRichard //NEF &NEF::operator=(const NEF &Other) noexcept(false) { return *this; }
52289a1d03eSRichard 
52389a1d03eSRichard #define STRUCT_WITH_COPY_CONSTRUCT(_base, _type) \
52489a1d03eSRichard   struct _type {                                 \
52589a1d03eSRichard     _type(const _type &v) : value(v.value) {}    \
52689a1d03eSRichard     _base value;                                 \
52789a1d03eSRichard   };
52889a1d03eSRichard 
52989a1d03eSRichard STRUCT_WITH_COPY_CONSTRUCT(unsigned char, Hex8CopyConstruct)
53089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy constructor
53189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-6]]:44: note:
53289a1d03eSRichard 
53389a1d03eSRichard #define STRUCT_WITH_COPY_ASSIGN(_base, _type) \
53489a1d03eSRichard   struct _type {                              \
53589a1d03eSRichard     _type &operator=(const _type &rhs) {      \
53689a1d03eSRichard       value = rhs.value;                      \
53789a1d03eSRichard       return *this;                           \
53889a1d03eSRichard     }                                         \
53989a1d03eSRichard     _base value;                              \
54089a1d03eSRichard   };
54189a1d03eSRichard 
54289a1d03eSRichard STRUCT_WITH_COPY_ASSIGN(unsigned char, Hex8CopyAssign)
54389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy-assignment operator
54489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-9]]:40: note:
54589a1d03eSRichard 
54689a1d03eSRichard // Use of braces
54789a1d03eSRichard struct UOB{
UOBUOB54889a1d03eSRichard   UOB(const UOB &Other):j{Other.j}{}
54989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default]
55089a1d03eSRichard   // CHECK-FIXES: UOB(const UOB &Other)= default;
55189a1d03eSRichard   int j;
55289a1d03eSRichard };
553