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