553 lines · cpp
1// RUN: %check_clang_tidy %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-type4 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) : Field(Other.Field) {}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) : Field(Other.Field) {}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.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 fact231 // that it is the last in the list of bases, because it is virtual and there232 // 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 constructor531// 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 operator544// CHECK-MESSAGES: :[[@LINE-9]]:40: note:545 546// Use of braces547struct 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