1 // RUN: %check_clang_tidy -std=c++11,c++14,c++17 %s cppcoreguidelines-pro-type-member-init %t -- -- -fno-delayed-template-parsing
2 // FIXME: Fix the checker to work in C++2a mode.
3 
4 struct PositiveFieldBeforeConstructor {
5   int F;
6   // CHECK-FIXES: int F{};
PositiveFieldBeforeConstructorPositiveFieldBeforeConstructor7   PositiveFieldBeforeConstructor() {}
8   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
9   // CHECK-FIXES: PositiveFieldBeforeConstructor() {}
10 };
11 
12 struct PositiveFieldAfterConstructor {
PositiveFieldAfterConstructorPositiveFieldAfterConstructor13   PositiveFieldAfterConstructor() {}
14   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G
15   // CHECK-FIXES: PositiveFieldAfterConstructor() {}
16   int F;
17   // CHECK-FIXES: int F{};
18   bool G /* with comment */;
19   // CHECK-FIXES: bool G{} /* with comment */;
20   PositiveFieldBeforeConstructor IgnoredField;
21 };
22 
23 struct PositiveSeparateDefinition {
24   PositiveSeparateDefinition();
25   int F;
26   // CHECK-FIXES: int F{};
27 };
28 
PositiveSeparateDefinition()29 PositiveSeparateDefinition::PositiveSeparateDefinition() {}
30 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
31 // CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {}
32 
33 struct PositiveMixedFieldOrder {
PositiveMixedFieldOrderPositiveMixedFieldOrder34   PositiveMixedFieldOrder() : J(0) {}
35   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: I, K
36   // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {}
37   int I;
38   // CHECK-FIXES: int I{};
39   int J;
40   int K;
41   // CHECK-FIXES: int K{};
42 };
43 
44 template <typename T>
45 struct Template {
TemplateTemplate46   Template() {}
47   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
48   int F;
49   // CHECK-FIXES: int F{};
50   T T1;
51   // CHECK-FIXES: T T1;
52 };
53 
instantiate()54 void instantiate() {
55   Template<int> TInt;
56 }
57 
58 struct NegativeFieldInitialized {
59   int F;
60 
NegativeFieldInitializedNegativeFieldInitialized61   NegativeFieldInitialized() : F() {}
62 };
63 
64 struct NegativeFieldInitializedInDefinition {
65   int F;
66 
67   NegativeFieldInitializedInDefinition();
68 };
NegativeFieldInitializedInDefinition()69 NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {}
70 
71 struct NegativeInClassInitialized {
72   int F = 0;
73 
NegativeInClassInitializedNegativeInClassInitialized74   NegativeInClassInitialized() {}
75 };
76 
77 struct NegativeInClassInitializedDefaulted {
78   int F = 0;
79   NegativeInClassInitializedDefaulted() = default;
80 };
81 
82 struct NegativeConstructorDelegated {
83   int F;
84 
NegativeConstructorDelegatedNegativeConstructorDelegated85   NegativeConstructorDelegated(int F) : F(F) {}
NegativeConstructorDelegatedNegativeConstructorDelegated86   NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {}
87 };
88 
89 struct NegativeInitializedInBody {
NegativeInitializedInBodyNegativeInitializedInBody90   NegativeInitializedInBody() { I = 0; }
91   int I;
92 };
93 
94 struct A {};
95 template <class> class AA;
96 template <class T> class NegativeTemplateConstructor {
NegativeTemplateConstructor(const AA<T> &,A)97   NegativeTemplateConstructor(const AA<T> &, A) {}
98   bool Bool{false};
99   // CHECK-FIXES: bool Bool{false};
100 };
101 
102 #define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \
103   struct UninitializedField##FIELD {             \
104     UninitializedField##FIELD() {}               \
105     int FIELD;                                   \
106   };                                             \
107 // Ensure FIELD is not initialized since fixes inside of macros are disabled.
108 // CHECK-FIXES: int FIELD;
109 
110 UNINITIALIZED_FIELD_IN_MACRO_BODY(F);
111 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
112 UNINITIALIZED_FIELD_IN_MACRO_BODY(G);
113 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: G
114 
115 #define UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(ARGUMENT) \
116   ARGUMENT
117 
118 UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(struct UninitializedFieldInMacroArg {
119   UninitializedFieldInMacroArg() {}
120   int Field;
121 });
122 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: constructor does not initialize these fields: Field
123 // Ensure FIELD is not initialized since fixes inside of macros are disabled.
124 // CHECK-FIXES: int Field;
125 
126 struct NegativeAggregateType {
127   int X;
128   int Y;
129   int Z;
130 };
131 
132 struct PositiveTrivialType {
PositiveTrivialTypePositiveTrivialType133   PositiveTrivialType() {}
134   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
135 
136   NegativeAggregateType F;
137   // CHECK-FIXES: NegativeAggregateType F{};
138 };
139 
140 struct NegativeNonTrivialType {
141   PositiveTrivialType F;
142 };
143 
PositiveUninitializedTrivialType()144 static void PositiveUninitializedTrivialType() {
145   NegativeAggregateType X;
146   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'X'
147   // CHECK-FIXES: NegativeAggregateType X{};
148 
149   NegativeAggregateType A[10]; // Don't warn because this isn't an object type.
150 }
151 
NegativeInitializedTrivialType()152 static void NegativeInitializedTrivialType() {
153   NegativeAggregateType X{};
154   NegativeAggregateType Y = {};
155   NegativeAggregateType Z = NegativeAggregateType();
156   NegativeAggregateType A[10]{};
157   NegativeAggregateType B[10] = {};
158   int C; // No need to initialize this because we don't have a constructor.
159   int D[8];
160   NegativeAggregateType E = {0, 1, 2};
161   NegativeAggregateType F({});
162 }
163 
164 struct NonTrivialType {
165   NonTrivialType() = default;
NonTrivialTypeNonTrivialType166   NonTrivialType(const NonTrivialType &RHS) : X(RHS.X), Y(RHS.Y) {}
167 
168   int X;
169   int Y;
170 };
171 
PositiveNonTrivialTypeWithCopyConstructor()172 static void PositiveNonTrivialTypeWithCopyConstructor() {
173   NonTrivialType T;
174   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'T'
175   // CHECK-FIXES: NonTrivialType T{};
176 
177   NonTrivialType A[8];
178   // Don't warn because this isn't an object type
179 }
180 
181 struct ComplexNonTrivialType {
182   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: Y
183   NegativeFieldInitialized X;
184   int Y;
185   // CHECK-FIXES: int Y{};
186 };
187 
PositiveComplexNonTrivialType()188 static void PositiveComplexNonTrivialType() {
189   ComplexNonTrivialType T;
190 }
191 
192 struct NegativeStaticMember {
193   static NonTrivialType X;
194   static NonTrivialType Y;
195   static constexpr NonTrivialType Z{};
196 };
197 
198 NonTrivialType NegativeStaticMember::X;
199 NonTrivialType NegativeStaticMember::Y{};
200 
201 struct PositiveMultipleConstructors {
PositiveMultipleConstructorsPositiveMultipleConstructors202   PositiveMultipleConstructors() {}
203   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
204 
PositiveMultipleConstructorsPositiveMultipleConstructors205   PositiveMultipleConstructors(int) {}
206   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
207 
PositiveMultipleConstructorsPositiveMultipleConstructors208   PositiveMultipleConstructors(const PositiveMultipleConstructors &) {}
209   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B
210 
211   // FIXME: The fix-its here collide providing an erroneous fix
212   int A, B;
213   // CHECK-FIXES: int A{}{}{}, B{}{}{};
214 };
215 
216 typedef struct {
217   int Member;
218 } CStyleStruct;
219 
220 struct PositiveUninitializedBase : public NegativeAggregateType, CStyleStruct {
PositiveUninitializedBasePositiveUninitializedBase221   PositiveUninitializedBase() {}
222   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType, CStyleStruct
223   // CHECK-FIXES: PositiveUninitializedBase() : NegativeAggregateType(), CStyleStruct() {}
224 };
225 
226 struct PositiveUninitializedBaseOrdering : public NegativeAggregateType,
227                                            public NonTrivialType {
PositiveUninitializedBaseOrderingPositiveUninitializedBaseOrdering228   PositiveUninitializedBaseOrdering() : B() {}
229   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType, NonTrivialType
230   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: constructor does not initialize these fields: A
231   // CHECK-FIXES: PositiveUninitializedBaseOrdering() : NegativeAggregateType(), NonTrivialType(), B() {}
232 
233   // This is somewhat pathological with the base class initializer at the end...
PositiveUninitializedBaseOrderingPositiveUninitializedBaseOrdering234   PositiveUninitializedBaseOrdering(int) : B(), NonTrivialType(), A() {}
235   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
236   // CHECK-FIXES: PositiveUninitializedBaseOrdering(int) : B(), NegativeAggregateType(), NonTrivialType(), A() {}
237 
PositiveUninitializedBaseOrderingPositiveUninitializedBaseOrdering238   PositiveUninitializedBaseOrdering(float) : B(), NegativeAggregateType(), A() {}
239   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NonTrivialType
240   // CHECK-FIXES: PositiveUninitializedBaseOrdering(float) : B(), NegativeAggregateType(), NonTrivialType(), A() {}
241 
242   int A, B;
243   // CHECK-FIXES: int A{}, B;
244 };
245 
246 // We shouldn't need to initialize anything because PositiveUninitializedBase
247 // has a user-defined constructor.
248 struct NegativeUninitializedBase : public PositiveUninitializedBase {
NegativeUninitializedBaseNegativeUninitializedBase249   NegativeUninitializedBase() {}
250 };
251 
252 struct InheritedAggregate : public NegativeAggregateType {
253   int F;
254 };
255 
256 static InheritedAggregate NegativeGlobal;
257 
258 enum TestEnum {
259   A,
260   B,
261   C
262 };
263 
264 enum class TestScopedEnum {
265   A,
266   B,
267   C
268 };
269 
270 struct PositiveEnumType {
PositiveEnumTypePositiveEnumType271   PositiveEnumType() {}
272   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: X, Y
273   // No proposed fixes, as we don't know whether value initialization for these
274   // enums really makes sense.
275 
276   TestEnum X;
277   TestScopedEnum Y;
278 };
279 
280 extern "C" {
281 struct NegativeCStruct {
282   int X, Y, Z;
283 };
284 
PositiveCStructVariable()285 static void PositiveCStructVariable() {
286   NegativeCStruct X;
287   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'X'
288   // CHECK-FIXES: NegativeCStruct X{};
289 }
290 }
291 
NegativeStaticVariable()292 static void NegativeStaticVariable() {
293   static NegativeCStruct S;
294   (void)S;
295 }
296 
297 union NegativeUnionInClass {
NegativeUnionInClass()298   NegativeUnionInClass() {} // No message as a union can only initialize one member.
299   int X = 0;
300   float Y;
301 };
302 
303 union PositiveUnion {
PositiveUnion()304   PositiveUnion() : X() {} // No message as a union can only initialize one member.
PositiveUnion(int)305   PositiveUnion(int) {}
306   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: X, Y
307 
308   int X;
309   // CHECK-FIXES: int X{};
310 
311   // Make sure we don't give Y an initializer.
312   float Y;
313   // CHECK-FIXES-NOT: float Y{};
314 };
315 
316 union PositiveUnionReversed {
PositiveUnionReversed()317   PositiveUnionReversed() : X() {} // No message as a union can only initialize one member.
PositiveUnionReversed(int)318   PositiveUnionReversed(int) {}
319   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: Y, X
320 
321   // Make sure we don't give Y an initializer.
322   TestEnum Y;
323   // CHECK-FIXES-NOT: TestEnum Y{};
324 
325   int X;
326   // CHECK-FIXES: int X{};
327 };
328 
329 struct PositiveAnonymousUnionAndStruct {
PositiveAnonymousUnionAndStructPositiveAnonymousUnionAndStruct330   PositiveAnonymousUnionAndStruct() {}
331   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B, Y, Z, C, D, E, F, X
332 
333   union {
334     int A;
335     // CHECK-FIXES: int A{};
336     short B;
337   };
338 
339   struct {
340     int Y;
341     // CHECK-FIXES: int Y{};
342     char *Z;
343     // CHECK-FIXES: char *Z{};
344 
345     struct {
346       short C;
347       // CHECK-FIXES: short C{};
348       double D;
349       // CHECK-FIXES: double D{};
350     };
351 
352     union {
353       long E;
354       // CHECK-FIXES: long E{};
355       float F;
356     };
357   };
358   int X;
359   // CHECK-FIXES: int X{};
360 };
361 
362 // This check results in a CXXConstructorDecl with no body.
363 struct NegativeDeletedConstructor : NegativeAggregateType {
364   NegativeDeletedConstructor() = delete;
365 
366   Template<int> F;
367 };
368 
369 // This pathological template fails to compile if actually instantiated. It
370 // results in the check seeing a null RecordDecl when examining the base class
371 // initializer list.
372 template <typename T>
373 class PositiveSelfInitialization : NegativeAggregateType
374 {
PositiveSelfInitialization()375   PositiveSelfInitialization() : PositiveSelfInitialization() {}
376   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType
377   // CHECK-FIXES: PositiveSelfInitialization() : NegativeAggregateType(), PositiveSelfInitialization() {}
378 };
379 
380 class PositiveIndirectMember {
381   struct {
382     int *A;
383     // CHECK-FIXES: int *A{};
384   };
385 
PositiveIndirectMember()386   PositiveIndirectMember() {}
387   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A
388 };
389 
Bug30487()390 void Bug30487()
391 {
392   NegativeInClassInitializedDefaulted s;
393 }
394 
395 struct PositiveVirtualMethod {
396   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
397   int F;
398   // CHECK-FIXES: int F{};
399   virtual int f() = 0;
400 };
401 
402 struct PositiveVirtualDestructor {
403   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
404   PositiveVirtualDestructor() = default;
405   int F;
406   // CHECK-FIXES: int F{};
~PositiveVirtualDestructorPositiveVirtualDestructor407   virtual ~PositiveVirtualDestructor() {}
408 };
409 
410 struct PositiveVirtualBase : public virtual NegativeAggregateType {
411   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these bases: NegativeAggregateType
412   // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: constructor does not initialize these fields: F
413   int F;
414   // CHECK-FIXES: int F{};
415 };
416 
417 template <typename T>
418 struct PositiveTemplateVirtualDestructor {
419   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F
420   T Val;
421   int F;
422   // CHECK-FIXES: int F{};
423   virtual ~PositiveTemplateVirtualDestructor() = default;
424 };
425 
426 template struct PositiveTemplateVirtualDestructor<int>;
427 
428 #define UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(FIELD) \
429   struct UninitializedFieldVirtual##FIELD {              \
430     int FIELD;                                           \
431     virtual ~UninitializedFieldVirtual##FIELD() {}       \
432   };                                                     \
433 // Ensure FIELD is not initialized since fixes inside of macros are disabled.
434 // CHECK-FIXES: int FIELD;
435 
436 UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(F);
437 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
438 UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(G);
439 // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: G
440 
441 struct NegativeEmpty {
442 };
443 
NegativeEmptyVar()444 static void NegativeEmptyVar() {
445   NegativeEmpty e;
446   (void)e;
447 }
448 
449 struct NegativeEmptyMember {
NegativeEmptyMemberNegativeEmptyMember450   NegativeEmptyMember() {}
451   NegativeEmpty e;
452 };
453 
454 struct NegativeEmptyBase : NegativeEmpty {
NegativeEmptyBaseNegativeEmptyBase455   NegativeEmptyBase() {}
456 };
457 
458 struct NegativeEmptyArrayMember {
NegativeEmptyArrayMemberNegativeEmptyArrayMember459   NegativeEmptyArrayMember() {}
460   char e[0];
461 };
462 
463 struct NegativeIncompleteArrayMember {
NegativeIncompleteArrayMemberNegativeIncompleteArrayMember464   NegativeIncompleteArrayMember() {}
465   char e[];
466 };
467 
468 template <typename T> class NoCrash {
469   class B : public NoCrash {
B(U u)470     template <typename U> B(U u) {}
471   };
472 };
473 
474 struct PositiveBitfieldMember {
PositiveBitfieldMemberPositiveBitfieldMember475   PositiveBitfieldMember() {}
476   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F
477   unsigned F : 5;
478   // CHECK-FIXES-NOT: unsigned F : 5{};
479 };
480 
481 struct NegativeUnnamedBitfieldMember {
NegativeUnnamedBitfieldMemberNegativeUnnamedBitfieldMember482   NegativeUnnamedBitfieldMember() {}
483   unsigned : 5;
484 };
485 
486 struct NegativeInitializedBitfieldMembers {
NegativeInitializedBitfieldMembersNegativeInitializedBitfieldMembers487   NegativeInitializedBitfieldMembers() : F(3) { G = 2; }
488   unsigned F : 5;
489   unsigned G : 5;
490 };
491 
492 struct NegativeImplicitInheritedCtorBase {
NegativeImplicitInheritedCtorBaseNegativeImplicitInheritedCtorBase493   NegativeImplicitInheritedCtorBase(unsigned F) : F(F) {}
494   unsigned F;
495 };
496 
497 struct NegativeImplicitInheritedCtor : NegativeImplicitInheritedCtorBase {
498   using NegativeImplicitInheritedCtorBase::NegativeImplicitInheritedCtorBase;
499 };
500 
Bug33557()501 void Bug33557() {
502   NegativeImplicitInheritedCtor I(5);
503 }
504