470 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			470 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
| // RUN: %check_clang_tidy %s modernize-use-default %t -- -- -std=c++11 -fno-delayed-template-parsing -fexceptions
 | |
| 
 | |
| // Out of line definition.
 | |
| struct OL {
 | |
|   OL(const OL &);
 | |
|   OL &operator=(const OL &);
 | |
|   int Field;
 | |
| };
 | |
| OL::OL(const OL &Other) : Field(Other.Field) {}
 | |
| // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy constructor [modernize-use-default]
 | |
| // CHECK-FIXES: OL::OL(const OL &Other) = default;
 | |
| OL &OL::operator=(const OL &Other) {
 | |
|   Field = Other.Field;
 | |
|   return *this;
 | |
| }
 | |
| // CHECK-MESSAGES: :[[@LINE-4]]:1: warning: use '= default' to define a trivial copy-assignment operator [modernize-use-default]
 | |
| // CHECK-FIXES: OL &OL::operator=(const OL &Other) = default;
 | |
| 
 | |
| // Inline.
 | |
| struct IL {
 | |
|   IL(const IL &Other) : Field(Other.Field) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: IL(const IL &Other) = default;
 | |
|   IL &operator=(const IL &Other) {
 | |
|     Field = Other.Field;
 | |
|     return *this;
 | |
|   }
 | |
|   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: IL &operator=(const IL &Other) = default;
 | |
|   int Field;
 | |
| };
 | |
| 
 | |
| // Wrong type.
 | |
| struct WT {
 | |
|   WT(const IL &Other) {}
 | |
|   WT &operator=(const IL &);
 | |
| };
 | |
| WT &WT::operator=(const IL &Other) { return *this; }
 | |
| 
 | |
| // Qualifiers.
 | |
| struct Qual {
 | |
|   Qual(const Qual &Other) : Field(Other.Field), Volatile(Other.Volatile),
 | |
|                             Mutable(Other.Mutable), Reference(Other.Reference),
 | |
|                             Const(Other.Const) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: Qual(const Qual &Other) = default;
 | |
| 
 | |
|   int Field;
 | |
|   volatile char Volatile;
 | |
|   mutable bool Mutable;
 | |
|   const OL &Reference; // This makes this class non-assignable.
 | |
|   const IL Const;      // This also makes this class non-assignable.
 | |
|   static int Static;
 | |
| };
 | |
| 
 | |
| // Wrong init arguments.
 | |
| struct WI {
 | |
|   WI(const WI &Other) : Field1(Other.Field1), Field2(Other.Field1) {}
 | |
|   WI &operator=(const WI &);
 | |
|   int Field1, Field2;
 | |
| };
 | |
| WI &WI::operator=(const WI &Other) {
 | |
|   Field1 = Other.Field1;
 | |
|   Field2 = Other.Field1;
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // Missing field.
 | |
| struct MF {
 | |
|   MF(const MF &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
 | |
|   MF &operator=(const MF &);
 | |
|   int Field1, Field2, Field3;
 | |
| };
 | |
| MF &MF::operator=(const MF &Other) {
 | |
|   Field1 = Other.Field1;
 | |
|   Field2 = Other.Field2;
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| struct Comments {
 | |
|   Comments(const Comments &Other)
 | |
|       /* don't delete */ : /* this comment */ Field(Other.Field) {}
 | |
|   int Field;
 | |
| };
 | |
| 
 | |
| struct MoreComments {
 | |
|   MoreComments(const MoreComments &Other) /* this comment is OK */
 | |
|       : Field(Other.Field) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: MoreComments(const MoreComments &Other) /* this comment is OK */
 | |
|   // CHECK-FIXES-NEXT: = default;
 | |
|   int Field;
 | |
| };
 | |
| 
 | |
| struct ColonInComment {
 | |
|   ColonInComment(const ColonInComment &Other) /* : */ : Field(Other.Field) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: ColonInComment(const ColonInComment &Other) /* : */ = default;
 | |
|   int Field;
 | |
| };
 | |
| 
 | |
| // No members or bases (in particular, no colon).
 | |
| struct Empty {
 | |
|   Empty(const Empty &Other) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: Empty(const Empty &Other) = default;
 | |
|   Empty &operator=(const Empty &);
 | |
| };
 | |
| Empty &Empty::operator=(const Empty &Other) { return *this; }
 | |
| // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default'
 | |
| // CHECK-FIXES: Empty &Empty::operator=(const Empty &Other) = default;
 | |
| 
 | |
| // Bit fields.
 | |
| struct BF {
 | |
|   BF() = default;
 | |
|   BF(const BF &Other) : Field1(Other.Field1), Field2(Other.Field2), Field3(Other.Field3),
 | |
|                         Field4(Other.Field4) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: BF(const BF &Other) = default;
 | |
|   BF &operator=(const BF &);
 | |
| 
 | |
|   unsigned Field1 : 3;
 | |
|   int : 7;
 | |
|   char Field2 : 6;
 | |
|   int : 0;
 | |
|   int Field3 : 24;
 | |
|   unsigned char Field4;
 | |
| };
 | |
| BF &BF::operator=(const BF &Other) {
 | |
|   Field1 = Other.Field1;
 | |
|   Field2 = Other.Field2;
 | |
|   Field3 = Other.Field3;
 | |
|   Field4 = Other.Field4;
 | |
|   return *this;
 | |
| }
 | |
| // CHECK-MESSAGES: :[[@LINE-7]]:1: warning: use '= default'
 | |
| // CHECK-FIXES: BF &BF::operator=(const BF &Other) = default;
 | |
| 
 | |
| // Base classes.
 | |
| struct BC : IL, OL, BF {
 | |
|   BC(const BC &Other) : IL(Other), OL(Other), BF(Other) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: BC(const BC &Other) = default;
 | |
|   BC &operator=(const BC &Other);
 | |
| };
 | |
| BC &BC::operator=(const BC &Other) {
 | |
|   IL::operator=(Other);
 | |
|   OL::operator=(Other);
 | |
|   BF::operator=(Other);
 | |
|   return *this;
 | |
| }
 | |
| // CHECK-MESSAGES: :[[@LINE-6]]:1: warning: use '= default'
 | |
| // CHECK-FIXES: BC &BC::operator=(const BC &Other) = default;
 | |
| 
 | |
| // Base classes with member.
 | |
| struct BCWM : IL, OL {
 | |
|   BCWM(const BCWM &Other) : IL(Other), OL(Other), Bf(Other.Bf) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: BCWM(const BCWM &Other) = default;
 | |
|   BCWM &operator=(const BCWM &);
 | |
|   BF Bf;
 | |
| };
 | |
| BCWM &BCWM::operator=(const BCWM &Other) {
 | |
|   IL::operator=(Other);
 | |
|   OL::operator=(Other);
 | |
|   Bf = Other.Bf;
 | |
|   return *this;
 | |
| }
 | |
| // CHECK-MESSAGES: :[[@LINE-6]]:1: warning: use '= default'
 | |
| // CHECK-FIXES: BCWM &BCWM::operator=(const BCWM &Other) = default;
 | |
| 
 | |
| // Missing base class.
 | |
| struct MBC : IL, OL, BF {
 | |
|   MBC(const MBC &Other) : IL(Other), OL(Other) {}
 | |
|   MBC &operator=(const MBC &);
 | |
| };
 | |
| MBC &MBC::operator=(const MBC &Other) {
 | |
|   IL::operator=(Other);
 | |
|   OL::operator=(Other);
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // Base classes, incorrect parameter.
 | |
| struct BCIP : BCWM, BF {
 | |
|   BCIP(const BCIP &Other) : BCWM(Other), BF(Other.Bf) {}
 | |
|   BCIP &operator=(const BCIP &);
 | |
| };
 | |
| BCIP &BCIP::operator=(const BCIP &Other) {
 | |
|   BCWM::operator=(Other);
 | |
|   BF::operator=(Other.Bf);
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // Virtual base classes.
 | |
| struct VA : virtual OL {};
 | |
| struct VB : virtual OL {};
 | |
| struct VBC : VA, VB, virtual OL {
 | |
|   // OL is the first thing that is going to be initialized, despite the fact
 | |
|   // that it is the last in the list of bases, because it is virtual and there
 | |
|   // is a virtual OL at the beginning of VA (which is the same).
 | |
|   VBC(const VBC &Other) : OL(Other), VA(Other), VB(Other) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: VBC(const VBC &Other) = default;
 | |
|   VBC &operator=(const VBC &Other);
 | |
| };
 | |
| VBC &VBC::operator=(const VBC &Other) {
 | |
|   OL::operator=(Other);
 | |
|   VA::operator=(Other);
 | |
|   VB::operator=(Other);
 | |
|   return *this;
 | |
| }
 | |
| // CHECK-MESSAGES: :[[@LINE-6]]:1: warning: use '= default'
 | |
| // CHECK-FIXES: VBC &VBC::operator=(const VBC &Other) = default;
 | |
| 
 | |
| // Indirect base.
 | |
| struct IB : VBC {
 | |
|   IB(const IB &Other) : OL(Other), VBC(Other) {}
 | |
|   IB &operator=(const IB &);
 | |
| };
 | |
| IB &IB::operator=(const IB &Other) {
 | |
|   OL::operator=(Other);
 | |
|   VBC::operator=(Other);
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // Class template.
 | |
| template <class T>
 | |
| struct Template {
 | |
|   Template() = default;
 | |
|   Template(const Template &Other) : Field(Other.Field) {}
 | |
|   Template &operator=(const Template &Other);
 | |
|   void foo(const T &t);
 | |
|   int Field;
 | |
| };
 | |
| template <class T>
 | |
| Template<T> &Template<T>::operator=(const Template<T> &Other) {
 | |
|   Field = Other.Field;
 | |
|   return *this;
 | |
| }
 | |
| Template<int> T1;
 | |
| 
 | |
| // Dependent types.
 | |
| template <class T>
 | |
| struct DT1 {
 | |
|   DT1() = default;
 | |
|   DT1(const DT1 &Other) : Field(Other.Field) {}
 | |
|   DT1 &operator=(const DT1 &);
 | |
|   T Field;
 | |
| };
 | |
| template <class T>
 | |
| DT1<T> &DT1<T>::operator=(const DT1<T> &Other) {
 | |
|   Field = Other.Field;
 | |
|   return *this;
 | |
| }
 | |
| DT1<int> Dt1;
 | |
| 
 | |
| template <class T>
 | |
| struct DT2 {
 | |
|   DT2() = default;
 | |
|   DT2(const DT2 &Other) : Field(Other.Field), Dependent(Other.Dependent) {}
 | |
|   DT2 &operator=(const DT2 &);
 | |
|   T Field;
 | |
|   typename T::TT Dependent;
 | |
| };
 | |
| template <class T>
 | |
| DT2<T> &DT2<T>::operator=(const DT2<T> &Other) {
 | |
|   Field = Other.Field;
 | |
|   Dependent = Other.Dependent;
 | |
|   return *this;
 | |
| }
 | |
| struct T {
 | |
|   typedef int TT;
 | |
| };
 | |
| DT2<T> Dt2;
 | |
| 
 | |
| // Default arguments.
 | |
| struct DA {
 | |
|   DA(int Int);
 | |
|   DA(const DA &Other = DA(0)) : Field1(Other.Field1), Field2(Other.Field2) {}
 | |
|   DA &operator=(const DA &);
 | |
|   int Field1;
 | |
|   char Field2;
 | |
| };
 | |
| // Overloaded operator= cannot have a default argument.
 | |
| DA &DA::operator=(const DA &Other) {
 | |
|   Field1 = Other.Field1;
 | |
|   Field2 = Other.Field2;
 | |
|   return *this;
 | |
| }
 | |
| // CHECK-MESSAGES: :[[@LINE-5]]:1: warning: use '= default'
 | |
| // CHECK-FIXES: DA &DA::operator=(const DA &Other) = default;
 | |
| 
 | |
| struct DA2 {
 | |
|   // Can be used as copy-constructor but cannot be explicitly defaulted.
 | |
|   DA2(const DA &Other, int Def = 0) {}
 | |
| };
 | |
| 
 | |
| // Default initialization.
 | |
| struct DI {
 | |
|   DI(const DI &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
 | |
|   int Field1;
 | |
|   int Field2 = 0;
 | |
|   int Fiedl3;
 | |
| };
 | |
| 
 | |
| // Statement inside body.
 | |
| void foo();
 | |
| struct SIB {
 | |
|   SIB(const SIB &Other) : Field(Other.Field) { foo(); }
 | |
|   SIB &operator=(const SIB &);
 | |
|   int Field;
 | |
| };
 | |
| SIB &SIB::operator=(const SIB &Other) {
 | |
|   Field = Other.Field;
 | |
|   foo();
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // Comment inside body.
 | |
| struct CIB {
 | |
|   CIB(const CIB &Other) : Field(Other.Field) { /* Don't erase this */
 | |
|   }
 | |
|   CIB &operator=(const CIB &);
 | |
|   int Field;
 | |
| };
 | |
| CIB &CIB::operator=(const CIB &Other) {
 | |
|   Field = Other.Field;
 | |
|   // FIXME: don't erase this comment.
 | |
|   return *this;
 | |
| }
 | |
| // CHECK-MESSAGES: :[[@LINE-5]]:1: warning: use '= default'
 | |
| // CHECK-FIXES: CIB &CIB::operator=(const CIB &Other) = default;
 | |
| 
 | |
| // Take non-const reference as argument.
 | |
| struct NCRef {
 | |
|   NCRef(NCRef &Other) : Field1(Other.Field1), Field2(Other.Field2) {}
 | |
|   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
 | |
|   // CHECK-FIXES: NCRef(NCRef &Other) = default;
 | |
|   NCRef &operator=(NCRef &);
 | |
|   int Field1, Field2;
 | |
| };
 | |
| NCRef &NCRef::operator=(NCRef &Other) {
 | |
|   Field1 = Other.Field1;
 | |
|   Field2 = Other.Field2;
 | |
|   return *this;
 | |
| }
 | |
| // CHECK-MESSAGES: :[[@LINE-5]]:1: warning: use '= default'
 | |
| // CHECK-FIXES: NCRef &NCRef::operator=(NCRef &Other) = default;
 | |
| 
 | |
| // Already defaulted.
 | |
| struct IAD {
 | |
|   IAD(const IAD &Other) = default;
 | |
|   IAD &operator=(const IAD &Other) = default;
 | |
| };
 | |
| 
 | |
| struct OAD {
 | |
|   OAD(const OAD &Other);
 | |
|   OAD &operator=(const OAD &);
 | |
| };
 | |
| OAD::OAD(const OAD &Other) = default;
 | |
| OAD &OAD::operator=(const OAD &Other) = default;
 | |
| 
 | |
| // Deleted.
 | |
| struct ID {
 | |
|   ID(const ID &Other) = delete;
 | |
|   ID &operator=(const ID &Other) = delete;
 | |
| };
 | |
| 
 | |
| // Non-reference parameter.
 | |
| struct NRef {
 | |
|   NRef &operator=(NRef Other);
 | |
|   int Field1;
 | |
| };
 | |
| NRef &NRef::operator=(NRef Other) {
 | |
|   Field1 = Other.Field1;
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // RValue reference parameter.
 | |
| struct RVR {
 | |
|   RVR(RVR &&Other) {}
 | |
|   RVR &operator=(RVR &&);
 | |
| };
 | |
| RVR &RVR::operator=(RVR &&Other) { return *this; }
 | |
| 
 | |
| // Similar function.
 | |
| struct SF {
 | |
|   SF &foo(const SF &);
 | |
|   int Field1;
 | |
| };
 | |
| SF &SF::foo(const SF &Other) {
 | |
|   Field1 = Other.Field1;
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // No return.
 | |
| struct NR {
 | |
|   NR &operator=(const NR &);
 | |
| };
 | |
| NR &NR::operator=(const NR &Other) {}
 | |
| 
 | |
| // Return misplaced.
 | |
| struct RM {
 | |
|   RM &operator=(const RM &);
 | |
|   int Field;
 | |
| };
 | |
| RM &RM::operator=(const RM &Other) {
 | |
|   return *this;
 | |
|   Field = Other.Field;
 | |
| }
 | |
| 
 | |
| // Wrong return value.
 | |
| struct WRV {
 | |
|   WRV &operator=(WRV &);
 | |
| };
 | |
| WRV &WRV::operator=(WRV &Other) {
 | |
|   return Other;
 | |
| }
 | |
| 
 | |
| // Wrong return type.
 | |
| struct WRT : IL {
 | |
|   IL &operator=(const WRT &);
 | |
| };
 | |
| IL &WRT::operator=(const WRT &Other) {
 | |
|   return *this;
 | |
| }
 | |
| 
 | |
| // Try-catch.
 | |
| struct ITC {
 | |
|   ITC(const ITC &Other)
 | |
|   try : Field(Other.Field) {
 | |
|   } catch (...) {
 | |
|   }
 | |
|   ITC &operator=(const ITC &Other) try {
 | |
|     Field = Other.Field;
 | |
|   } catch (...) {
 | |
|   }
 | |
|   int Field;
 | |
| };
 | |
| 
 | |
| struct OTC {
 | |
|   OTC(const OTC &);
 | |
|   OTC &operator=(const OTC &);
 | |
|   int Field;
 | |
| };
 | |
| OTC::OTC(const OTC &Other) try : Field(Other.Field) {
 | |
| } catch (...) {
 | |
| }
 | |
| OTC &OTC::operator=(const OTC &Other) try {
 | |
|   Field = Other.Field;
 | |
| } catch (...) {
 | |
| }
 | |
| 
 | |
| // FIXME: the check is not able to detect exception specification.
 | |
| // noexcept(true).
 | |
| struct NET {
 | |
|   // This is the default.
 | |
|   //NET(const NET &Other) noexcept {}
 | |
|   NET &operator=(const NET &Other) noexcept;
 | |
| };
 | |
| //NET &NET::operator=(const NET &Other) noexcept { return *this; }
 | |
| 
 | |
| // noexcept(false).
 | |
| struct NEF {
 | |
|   // This is the default.
 | |
|   //NEF(const NEF &Other) noexcept(false) {}
 | |
|   NEF &operator=(const NEF &Other) noexcept(false);
 | |
| };
 | |
| //NEF &NEF::operator=(const NEF &Other) noexcept(false) { return *this; }
 |