diff options
| author | Angel Garcia Gomez <angelgarcia@google.com> | 2015-11-02 10:34:19 +0000 | 
|---|---|---|
| committer | Angel Garcia Gomez <angelgarcia@google.com> | 2015-11-02 10:34:19 +0000 | 
| commit | f2bc2f001aeff99ba55cb494b99b0394a5a4dd50 (patch) | |
| tree | ef0fd3289842e7e77c88baa4f930d21124953096 /clang-tools-extra/test | |
| parent | f423c1200f18af85098269a62882d85d461d22d4 (diff) | |
| download | bcm5719-llvm-f2bc2f001aeff99ba55cb494b99b0394a5a4dd50.tar.gz bcm5719-llvm-f2bc2f001aeff99ba55cb494b99b0394a5a4dd50.zip  | |
modernize-use-default supports copy constructor and copy-assignment operator.
Summary: the check will now warn when the user provided definitions of this functions is equivalent to the explicitly defaulted ones.
Reviewers: klimek
Subscribers: klimek, cfe-commits, alexfh
Differential Revision: http://reviews.llvm.org/D14145
llvm-svn: 251788
Diffstat (limited to 'clang-tools-extra/test')
| -rw-r--r-- | clang-tools-extra/test/clang-tidy/modernize-use-default-copy.cpp | 469 | ||||
| -rw-r--r-- | clang-tools-extra/test/clang-tidy/modernize-use-default.cpp | 154 | 
2 files changed, 557 insertions, 66 deletions
diff --git a/clang-tools-extra/test/clang-tidy/modernize-use-default-copy.cpp b/clang-tools-extra/test/clang-tidy/modernize-use-default-copy.cpp new file mode 100644 index 00000000000..424d0752aa3 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/modernize-use-default-copy.cpp @@ -0,0 +1,469 @@ +// RUN: %check_clang_tidy %s modernize-use-default %t -- -- -std=c++11 -fno-delayed-template-parsing + +// 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; } diff --git a/clang-tools-extra/test/clang-tidy/modernize-use-default.cpp b/clang-tools-extra/test/clang-tidy/modernize-use-default.cpp index 3bd4c8e96eb..e6be7241627 100644 --- a/clang-tools-extra/test/clang-tidy/modernize-use-default.cpp +++ b/clang-tools-extra/test/clang-tidy/modernize-use-default.cpp @@ -1,137 +1,159 @@  // RUN: %check_clang_tidy %s modernize-use-default %t -- -- -std=c++11 -fno-delayed-template-parsing -class A { +// Out of line definition. +class OL {  public: -  A(); -  ~A(); +  OL(); +  ~OL();  }; -A::A() {} +OL::OL() {}  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial default constructor [modernize-use-default] -// CHECK-FIXES: A::A() = default; -A::~A() {} +// CHECK-FIXES: OL::OL() = default; +OL::~OL() {}  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial destructor [modernize-use-default] -// CHECK-FIXES: A::~A() = default; +// CHECK-FIXES: OL::~OL() = default;  // Inline definitions. -class B { +class IL {  public: -  B() {} +  IL() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: B() = default; -  ~B() {} +  // CHECK-FIXES: IL() = default; +  ~IL() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: ~B() = default; +  // CHECK-FIXES: ~IL() = default;  }; +// Non-empty body.  void f(); - -class C { +class NE {  public: -  // Non-empty constructor body. -  C() { f(); } -  // Non-empty destructor body. -  ~C() { f(); } +  NE() { f(); } +  ~NE() { f(); }  }; -class D { +// Initializer or arguments. +class IA {  public:    // Constructor with initializer. -  D() : Field(5) {} +  IA() : Field(5) {}    // Constructor with arguments. -  D(int Arg1, int Arg2) {} +  IA(int Arg1, int Arg2) {}    int Field;  };  // Private constructor/destructor. -class E { -  E() {} +class Priv { +  Priv() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: E() = default; -  ~E() {} +  // CHECK-FIXES: Priv() = default; +  ~Priv() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: ~E() = default; +  // CHECK-FIXES: ~Priv() = default;  };  // struct. -struct F { -  F() {} +struct ST { +  ST() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: F() = default; -  ~F() {} +  // CHECK-FIXES: ST() = default; +  ~ST() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: F() = default; +  // CHECK-FIXES: ST() = default;  };  // Deleted constructor/destructor. -class G { +class Del {  public: -  G() = delete; -  ~G() = delete; +  Del() = delete; +  ~Del() = delete;  };  // Do not remove other keywords. -class H { +class KW {  public: -  explicit H() {} +  explicit KW() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: explicit H() = default; -  virtual ~H() {} +  // CHECK-FIXES: explicit KW() = default; +  virtual ~KW() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: virtual ~H() = default; +  // CHECK-FIXES: virtual ~KW() = default;  };  // Nested class. -struct I { -  struct II { -    II() {} +struct N { +  struct NN { +    NN() {}      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' -    // CHECK-FIXES: II() = default; -    ~II() {} +    // CHECK-FIXES: NN() = default; +    ~NN() {}      // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' -    // CHECK-FIXES: ~II() = default; +    // CHECK-FIXES: ~NN() = default;    };    int Int;  };  // Class template.  template <class T> -class J { +class Temp {  public: -  J() {} +  Temp() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: J() = default; -  ~J() {} +  // CHECK-FIXES: Temp() = default; +  ~Temp() {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: ~J() = default; +  // CHECK-FIXES: ~Temp() = default;  };  // Non user-provided constructor/destructor. -struct K { +struct Imp {    int Int;  };  void g() { -  K *PtrK = new K(); -  PtrK->~K(); -  delete PtrK; +  Imp *PtrImp = new Imp(); +  PtrImp->~Imp(); +  delete PtrImp;  }  // Already using default. -struct L { -  L() = default; -  ~L() = default; +struct IDef { +  IDef() = default; +  ~IDef() = default;  }; -struct M { -  M(); -  ~M(); +struct ODef { +  ODef(); +  ~ODef();  }; -M::M() = default; -M::~M() = default; +ODef::ODef() = default; +ODef::~ODef() = default;  // Delegating constructor and overriden destructor. -struct N : H { -  N() : H() {} -  ~N() override {} +struct DC : KW { +  DC() : KW() {} +  ~DC() override {}    // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' -  // CHECK-FIXES: ~N() override = default; +  // CHECK-FIXES: ~DC() override = default; +}; + +struct Comments { +  Comments() { +    // Don't erase comments inside the body. +  } +  ~Comments() { +    // Don't erase comments inside the body. +  } +}; + +// Try-catch. +struct ITC { +  ITC() try {} catch(...) {} +  ~ITC() try {} catch(...) {} +}; + +struct OTC { +  OTC(); +  ~OTC();  }; +OTC::OTC() try {} catch(...) {} +OTC::~OTC() try {} catch(...) {}  | 

