xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default.cpp (revision eb87e55c9aade5d7b42606487e69b5f3a6da1e65)
1 // RUN: %check_clang_tidy %s modernize-use-equals-default %t -- -- -fno-delayed-template-parsing -fexceptions
2 
3 // Out of line definition.
4 class OL {
5 public:
6   OL();
7   ~OL();
8 };
9 
OL()10 OL::OL() {};
11 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial default constructor [modernize-use-equals-default]
12 // CHECK-FIXES: OL::OL() = default;
~OL()13 OL::~OL() {}
14 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default' to define a trivial destructor [modernize-use-equals-default]
15 // CHECK-FIXES: OL::~OL() = default;
16 
17 // Inline definitions.
18 class IL {
19 public:
IL()20   IL() {} 	 ; // Note embedded tab on this line
21   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
22   // CHECK-FIXES: IL() = default 	 ; // Note embedded tab on this line
~IL()23   ~IL() {}
24   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
25   // CHECK-FIXES: ~IL() = default;
26 };
27 
28 // Non-empty body.
29 void f();
30 class NE {
31 public:
NE()32   NE() { f(); }
~NE()33   ~NE() { f(); }
34 };
35 
36 // Skip unions.
37 union NU {
NU()38   NU() {}
39   // CHECK-FIXES: NU() {}
~NU()40   ~NU() {}
41   // CHECK-FIXES: ~NU() {}
42   NE Field;
43 };
44 
45 // Skip unions with out-of-line constructor/destructor.
46 union NUO {
47   NUO();
48   ~NUO();
49   NE Field;
50 };
51 
NUO()52 NUO::NUO() {}
53 // CHECK-FIXES: NUO::NUO() {}
~NUO()54 NUO::~NUO() {}
55 // CHECK-FIXES: NUO::~NUO() {}
56 
57 // Skip structs/classes containing anonymous unions.
58 struct SU {
SUSU59   SU() {}
60   // CHECK-FIXES: SU() {}
~SUSU61   ~SU() {}
62   // CHECK-FIXES: ~SU() {}
63   union {
64     NE Field;
65   };
66 };
67 
68 // Skip variadic constructors.
69 struct VA {
VAVA70   VA(...) {}
71 };
72 
73 // Skip template constructors.
74 struct TC {
75   template <unsigned U>
TCTC76   TC() {}
77 
78   template <unsigned U>
TCTC79   TC(const TC &) {}
80 
81   template <unsigned U>
operator =TC82   TC& operator = (const TC &) { return *this; }
83 };
84 
85 // Initializer or arguments.
86 class IA {
87 public:
88   // Constructor with initializer.
IA()89   IA() : Field(5) {}
90   // Constructor with arguments.
IA(int Arg1,int Arg2)91   IA(int Arg1, int Arg2) {}
92   int Field;
93 };
94 
95 // Default member initializer
96 class DMI {
97 public:
DMI()98   DMI() {} // Comment before semi-colon on next line
99   ;
100   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use '= default'
101   // CHECK-FIXES: DMI() = default // Comment before semi-colon on next line
102   // CHECK-FIXES-NEXT:   ;
103   int Field = 5;
104 };
105 
106 // Class member
107 class CM {
108 public:
CM()109   CM() {} /* Comments */ /* before */ /* semicolon */;
110   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
111   // CHECK-FIXES: CM() = default /* Comments */ /* before */ /* semicolon */;
112   OL o;
113 };
114 
115 // Private constructor/destructor.
116 class Priv {
117   Priv();
~Priv()118   ~Priv() {}
119   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
120   // CHECK-FIXES: ~Priv() = default;
121 };
122 
Priv()123 Priv::Priv() {}
124 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use '= default'
125 // CHECK-FIXES: Priv::Priv() = default;
126 
127 struct SemiColon {
SemiColonSemiColon128   SemiColon() {};
129   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
130   // CHECK-FIXES: SemiColon() = default;{{$}}
131 };
132 
133 struct SemiColonOutOfLine {
134   SemiColonOutOfLine();
135 };
136 
SemiColonOutOfLine()137 SemiColonOutOfLine::SemiColonOutOfLine() {};
138 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: use '= default'
139 // CHECK-FIXES: SemiColonOutOfLine::SemiColonOutOfLine() = default;{{$}}
140 
141 // struct.
142 struct ST {
STST143   ST() {}
144   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
145   // CHECK-FIXES: ST() = default;{{$}}
~STST146   ~ST() {}
147   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
148   // CHECK-FIXES: ST() = default;{{$}}
149 };
150 
151 // Deleted constructor/destructor.
152 class Del {
153 public:
154   Del() = delete;
155   ~Del() = delete;
156 };
157 
158 // Do not remove other keywords.
159 class KW {
160 public:
KW()161   explicit KW() {}
162   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use '= default'
163   // CHECK-FIXES: explicit KW() = default;
~KW()164   virtual ~KW() {}
165   // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use '= default'
166   // CHECK-FIXES: virtual ~KW() = default;
167 };
168 
169 // Nested class.
170 struct N {
171   struct NN {
NNN::NN172     NN() {}
173     // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default'
174     // CHECK-FIXES: NN() = default;
~NNN::NN175     ~NN() {}
176     // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use '= default'
177     // CHECK-FIXES: ~NN() = default;
178   };
179   int Int;
180 };
181 
182 // Class template.
183 template <class T>
184 class Temp {
185 public:
Temp()186   Temp() {}
187   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
188   // CHECK-FIXES: Temp() = default;
~Temp()189   ~Temp() {}
190   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
191   // CHECK-FIXES: ~Temp() = default;
192 };
193 
194 // Class template out of line with explicit instantiation.
195 template <class T>
196 class TempODef {
197 public:
198   TempODef();
199   ~TempODef();
200 };
201 
202 template <class T>
TempODef()203 TempODef<T>::TempODef() {}
204 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use '= default'
205 // CHECK-FIXES: TempODef<T>::TempODef() = default;
206 template <class T>
~TempODef()207 TempODef<T>::~TempODef() {}
208 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use '= default'
209 // CHECK-FIXES: TempODef<T>::~TempODef() = default;
210 
211 template class TempODef<int>;
212 template class TempODef<double>;
213 
214 // Non user-provided constructor/destructor.
215 struct Imp {
216   int Int;
217 };
g()218 void g() {
219   Imp *PtrImp = new Imp();
220   PtrImp->~Imp();
221   delete PtrImp;
222 }
223 
224 // Already using default.
225 struct IDef {
226   IDef() = default;
227   ~IDef() = default;
228 };
229 struct ODef {
230   ODef();
231   ~ODef();
232 };
233 ODef::ODef() = default;
234 ODef::~ODef() = default;
235 
236 // Delegating constructor and overriden destructor.
237 struct DC : KW {
DCDC238   DC() : KW() {}
~DCDC239   ~DC() override {}
240   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
241   // CHECK-FIXES: ~DC() override = default;{{$}}
242 };
243 
244 struct OverrideWithSemiColon : KW {
~OverrideWithSemiColonOverrideWithSemiColon245   ~OverrideWithSemiColon() override {};
246   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
247   // CHECK-FIXES: ~OverrideWithSemiColon() override = default;{{$}}
248 };
249 
250 struct Comments {
CommentsComments251   Comments() {
252     // Don't erase comments inside the body.
253   }
254   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
~CommentsComments255   ~Comments() {
256     // Don't erase comments inside the body.
257   }
258   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use '= default'
259 };
260 
261 // Try-catch.
262 struct ITC {
ITCITC263   ITC() try {} catch(...) {}
~ITCITC264   ~ITC() try {} catch(...) {}
265 };
266 
267 struct OTC {
268   OTC();
269   ~OTC();
270 };
OTC()271 OTC::OTC() try {} catch(...) {}
~OTC()272 OTC::~OTC() try {} catch(...) {}
273 
274 #define STRUCT_WITH_DEFAULT(_base, _type) \
275   struct _type {                          \
276     _type() {}                            \
277     _base value;                          \
278   };
279 
280 STRUCT_WITH_DEFAULT(unsigned char, InMacro)
281 
282 #define ZERO_VALUE 0
283 struct PreprocesorDependentTest
284 {
285   void something();
286 
PreprocesorDependentTestPreprocesorDependentTest287   PreprocesorDependentTest() {
288 #if ZERO_VALUE
289     something();
290 #endif
291   }
292 
~PreprocesorDependentTestPreprocesorDependentTest293   ~PreprocesorDependentTest() {
294 #if ZERO_VALUE
295     something();
296 #endif
297   }
298 };
299