// RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-member-init %t -- -- -std=c++11 -fno-delayed-template-parsing struct PositiveFieldBeforeConstructor { int F; // CHECK-FIXES: int F{}; PositiveFieldBeforeConstructor() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F // CHECK-FIXES: PositiveFieldBeforeConstructor() {} }; struct PositiveFieldAfterConstructor { PositiveFieldAfterConstructor() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F, G // CHECK-FIXES: PositiveFieldAfterConstructor() {} int F; // CHECK-FIXES: int F{}; bool G /* with comment */; // CHECK-FIXES: bool G{} /* with comment */; PositiveFieldBeforeConstructor IgnoredField; }; struct PositiveSeparateDefinition { PositiveSeparateDefinition(); int F; // CHECK-FIXES: int F{}; }; PositiveSeparateDefinition::PositiveSeparateDefinition() {} // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F // CHECK-FIXES: PositiveSeparateDefinition::PositiveSeparateDefinition() {} struct PositiveMixedFieldOrder { PositiveMixedFieldOrder() : J(0) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: I, K // CHECK-FIXES: PositiveMixedFieldOrder() : J(0) {} int I; // CHECK-FIXES: int I{}; int J; int K; // CHECK-FIXES: int K{}; }; template struct Template { Template() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F int F; // CHECK-FIXES: int F{}; T T1; // CHECK-FIXES: T T1; }; void instantiate() { Template TInt; } struct NegativeFieldInitialized { int F; NegativeFieldInitialized() : F() {} }; struct NegativeFieldInitializedInDefinition { int F; NegativeFieldInitializedInDefinition(); }; NegativeFieldInitializedInDefinition::NegativeFieldInitializedInDefinition() : F() {} struct NegativeInClassInitialized { int F = 0; NegativeInClassInitialized() {} }; struct NegativeInClassInitializedDefaulted { int F = 0; NegativeInClassInitializedDefaulted() = default; }; struct NegativeConstructorDelegated { int F; NegativeConstructorDelegated(int F) : F(F) {} NegativeConstructorDelegated() : NegativeConstructorDelegated(0) {} }; struct NegativeInitializedInBody { NegativeInitializedInBody() { I = 0; } int I; }; struct A {}; template class AA; template class NegativeTemplateConstructor { NegativeTemplateConstructor(const AA &, A) {} bool Bool{false}; // CHECK-FIXES: bool Bool{false}; }; #define UNINITIALIZED_FIELD_IN_MACRO_BODY(FIELD) \ struct UninitializedField##FIELD { \ UninitializedField##FIELD() {} \ int FIELD; \ }; \ // Ensure FIELD is not initialized since fixes inside of macros are disabled. // CHECK-FIXES: int FIELD; UNINITIALIZED_FIELD_IN_MACRO_BODY(F); // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F UNINITIALIZED_FIELD_IN_MACRO_BODY(G); // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: G #define UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(ARGUMENT) \ ARGUMENT UNINITIALIZED_FIELD_IN_MACRO_ARGUMENT(struct UninitializedFieldInMacroArg { UninitializedFieldInMacroArg() {} int Field; }); // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: constructor does not initialize these fields: Field // Ensure FIELD is not initialized since fixes inside of macros are disabled. // CHECK-FIXES: int Field; struct NegativeAggregateType { int X; int Y; int Z; }; struct PositiveTrivialType { PositiveTrivialType() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F NegativeAggregateType F; // CHECK-FIXES: NegativeAggregateType F{}; }; struct NegativeNonTrivialType { PositiveTrivialType F; }; static void PositiveUninitializedTrivialType() { NegativeAggregateType X; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'X' // CHECK-FIXES: NegativeAggregateType X{}; NegativeAggregateType A[10]; // Don't warn because this isn't an object type. } static void NegativeInitializedTrivialType() { NegativeAggregateType X{}; NegativeAggregateType Y = {}; NegativeAggregateType Z = NegativeAggregateType(); NegativeAggregateType A[10]{}; NegativeAggregateType B[10] = {}; int C; // No need to initialize this because we don't have a constructor. int D[8]; NegativeAggregateType E = {0, 1, 2}; NegativeAggregateType F({}); } struct NonTrivialType { NonTrivialType() = default; NonTrivialType(const NonTrivialType &RHS) : X(RHS.X), Y(RHS.Y) {} int X; int Y; }; static void PositiveNonTrivialTypeWithCopyConstructor() { NonTrivialType T; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'T' // CHECK-FIXES: NonTrivialType T{}; NonTrivialType A[8]; // Don't warn because this isn't an object type } struct ComplexNonTrivialType { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: Y NegativeFieldInitialized X; int Y; // CHECK-FIXES: int Y{}; }; static void PositiveComplexNonTrivialType() { ComplexNonTrivialType T; } struct NegativeStaticMember { static NonTrivialType X; static NonTrivialType Y; static constexpr NonTrivialType Z{}; }; NonTrivialType NegativeStaticMember::X; NonTrivialType NegativeStaticMember::Y{}; struct PositiveMultipleConstructors { PositiveMultipleConstructors() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B PositiveMultipleConstructors(int) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B PositiveMultipleConstructors(const PositiveMultipleConstructors &) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B // FIXME: The fix-its here collide providing an erroneous fix int A, B; // CHECK-FIXES: int A{}{}{}, B{}{}{}; }; typedef struct { int Member; } CStyleStruct; struct PositiveUninitializedBase : public NegativeAggregateType, CStyleStruct { PositiveUninitializedBase() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType, CStyleStruct // CHECK-FIXES: PositiveUninitializedBase() : NegativeAggregateType(), CStyleStruct() {} }; struct PositiveUninitializedBaseOrdering : public NegativeAggregateType, public NonTrivialType { PositiveUninitializedBaseOrdering() : B() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType, NonTrivialType // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: constructor does not initialize these fields: A // CHECK-FIXES: PositiveUninitializedBaseOrdering() : NegativeAggregateType(), NonTrivialType(), B() {} // This is somewhat pathological with the base class initializer at the end... PositiveUninitializedBaseOrdering(int) : B(), NonTrivialType(), A() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType // CHECK-FIXES: PositiveUninitializedBaseOrdering(int) : B(), NegativeAggregateType(), NonTrivialType(), A() {} PositiveUninitializedBaseOrdering(float) : B(), NegativeAggregateType(), A() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NonTrivialType // CHECK-FIXES: PositiveUninitializedBaseOrdering(float) : B(), NegativeAggregateType(), NonTrivialType(), A() {} int A, B; // CHECK-FIXES: int A{}, B; }; // We shouldn't need to initialize anything because PositiveUninitializedBase // has a user-defined constructor. struct NegativeUninitializedBase : public PositiveUninitializedBase { NegativeUninitializedBase() {} }; struct InheritedAggregate : public NegativeAggregateType { int F; }; static InheritedAggregate NegativeGlobal; enum TestEnum { A, B, C }; enum class TestScopedEnum { A, B, C }; struct PositiveEnumType { PositiveEnumType() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: X, Y // No proposed fixes, as we don't know whether value initialization for these // enums really makes sense. TestEnum X; TestScopedEnum Y; }; extern "C" { struct NegativeCStruct { int X, Y, Z; }; static void PositiveCStructVariable() { NegativeCStruct X; // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: uninitialized record type: 'X' // CHECK-FIXES: NegativeCStruct X{}; } } static void NegativeStaticVariable() { static NegativeCStruct S; (void)S; } union NegativeUnionInClass { NegativeUnionInClass() {} // No message as a union can only initialize one member. int X = 0; float Y; }; union PositiveUnion { PositiveUnion() : X() {} // No message as a union can only initialize one member. PositiveUnion(int) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: X, Y int X; // CHECK-FIXES: int X{}; // Make sure we don't give Y an initializer. float Y; // CHECK-FIXES-NOT: float Y{}; }; union PositiveUnionReversed { PositiveUnionReversed() : X() {} // No message as a union can only initialize one member. PositiveUnionReversed(int) {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: Y, X // Make sure we don't give Y an initializer. TestEnum Y; // CHECK-FIXES-NOT: TestEnum Y{}; int X; // CHECK-FIXES: int X{}; }; struct PositiveAnonymousUnionAndStruct { PositiveAnonymousUnionAndStruct() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A, B, Y, Z, C, D, E, F, X union { int A; // CHECK-FIXES: int A{}; short B; }; struct { int Y; // CHECK-FIXES: int Y{}; char *Z; // CHECK-FIXES: char *Z{}; struct { short C; // CHECK-FIXES: short C{}; double D; // CHECK-FIXES: double D{}; }; union { long E; // CHECK-FIXES: long E{}; float F; }; }; int X; // CHECK-FIXES: int X{}; }; // This check results in a CXXConstructorDecl with no body. struct NegativeDeletedConstructor : NegativeAggregateType { NegativeDeletedConstructor() = delete; Template F; }; // This pathological template fails to compile if actually instantiated. It // results in the check seeing a null RecordDecl when examining the base class // initializer list. template class PositiveSelfInitialization : NegativeAggregateType { PositiveSelfInitialization() : PositiveSelfInitialization() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these bases: NegativeAggregateType // CHECK-FIXES: PositiveSelfInitialization() : NegativeAggregateType(), PositiveSelfInitialization() {} }; class PositiveIndirectMember { struct { int *A; // CHECK-FIXES: int *A{}; }; PositiveIndirectMember() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A }; void Bug30487() { NegativeInClassInitializedDefaulted s; } struct PositiveVirtualMethod { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F int F; // CHECK-FIXES: int F{}; virtual int f() = 0; }; struct PositiveVirtualDestructor { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F PositiveVirtualDestructor() = default; int F; // CHECK-FIXES: int F{}; virtual ~PositiveVirtualDestructor() {} }; struct PositiveVirtualBase : public virtual NegativeAggregateType { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these bases: NegativeAggregateType // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: constructor does not initialize these fields: F int F; // CHECK-FIXES: int F{}; }; template struct PositiveTemplateVirtualDestructor { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: constructor does not initialize these fields: F T Val; int F; // CHECK-FIXES: int F{}; virtual ~PositiveTemplateVirtualDestructor() = default; }; template struct PositiveTemplateVirtualDestructor; #define UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(FIELD) \ struct UninitializedFieldVirtual##FIELD { \ int FIELD; \ virtual ~UninitializedFieldVirtual##FIELD() {} \ }; \ // Ensure FIELD is not initialized since fixes inside of macros are disabled. // CHECK-FIXES: int FIELD; UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(F); // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F UNINITIALIZED_FIELD_IN_MACRO_BODY_VIRTUAL(G); // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: G struct NegativeEmpty { }; static void NegativeEmptyVar() { NegativeEmpty e; (void)e; } struct NegativeEmptyMember { NegativeEmptyMember() {} NegativeEmpty e; }; struct NegativeEmptyBase : NegativeEmpty { NegativeEmptyBase() {} }; struct NegativeEmptyArrayMember { NegativeEmptyArrayMember() {} char e[0]; }; struct NegativeIncompleteArrayMember { NegativeIncompleteArrayMember() {} char e[]; }; template class NoCrash { class B : public NoCrash { template B(U u) {} }; }; struct PositiveBitfieldMember { PositiveBitfieldMember() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: F unsigned F : 5; // CHECK-FIXES-NOT: unsigned F : 5{}; }; struct NegativeUnnamedBitfieldMember { NegativeUnnamedBitfieldMember() {} unsigned : 5; }; struct NegativeInitializedBitfieldMembers { NegativeInitializedBitfieldMembers() : F(3) { G = 2; } unsigned F : 5; unsigned G : 5; }; struct NegativeImplicitInheritedCtorBase { NegativeImplicitInheritedCtorBase(unsigned F) : F(F) {} unsigned F; }; struct NegativeImplicitInheritedCtor : NegativeImplicitInheritedCtorBase { using NegativeImplicitInheritedCtorBase::NegativeImplicitInheritedCtorBase; }; void Bug33557() { NegativeImplicitInheritedCtor I(5); }