// RUN: %check_clang_tidy -std=c++11,c++14,c++17 %s cppcoreguidelines-pro-type-member-init %t -- -- -fno-delayed-template-parsing
// FIXME: Fix the checker to work in C++20 mode.
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 <typename T>
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<int> 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> class AA;
template <class T> class NegativeTemplateConstructor {
NegativeTemplateConstructor(const AA<T> &, 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
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-provided 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<int> 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 <typename T>
class PositiveSelfInitialization : NegativeAggregateType
{
PositiveSelfInitialization() : PositiveSelfInitialization() {}
// This will be detected by -Wdelegating-ctor-cycles and there is no proper way to fix this
};
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 <typename T>
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<int>;
#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[];
};
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);
}
struct NegativeDefaultedCtorOutOfDecl {
NegativeDefaultedCtorOutOfDecl(const NegativeDefaultedCtorOutOfDecl &);
int F;
};
NegativeDefaultedCtorOutOfDecl::NegativeDefaultedCtorOutOfDecl(const NegativeDefaultedCtorOutOfDecl &) = default;
struct PositiveDefaultConstructorOutOfDecl {
PositiveDefaultConstructorOutOfDecl();
int F;
// CHECK-FIXES: int F{};
};
PositiveDefaultConstructorOutOfDecl::PositiveDefaultConstructorOutOfDecl() = default;
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: constructor does not initialize these fields: F
union U1 {
U1() {}
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: X, K, Z, Y
int X;
// CHECK-FIXES: int X{};
union {
int K;
// CHECK-FIXES-NOT: int K{};
};
union {
int Z;
// CHECK-FIXES-NOT: int Z{};
int Y;
// CHECK-FIXES-NOT: int Y{};
};
};
union U2 {
U2() {}
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: union constructor should initialize one of these fields: B, C, A
struct {
int B;
// CHECK-FIXES: int B{};
union {
struct {
PositiveMultipleConstructors Value;
// CHECK-FIXES-NOT: PositiveMultipleConstructors Value{};
};
int C;
// CHECK-FIXES: int C{};
};
};
int A;
// CHECK-FIXES-NOT: int A{};
};
struct S1 {
S1() {}
union {
int a = 0;
int b;
};
};
struct S2 {
S2() : a{} {}
union {
int a;
int b;
};
};
struct S3 {
S3() {}
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: constructor does not initialize these fields: A [cppcoreguidelines-pro-type-member-init]
int A;
// CHECK-FIXES: int A{};
union {
int B;
int C = 0;
};
};
// Ignore issues from delegate constructors
namespace PR37250 {
template <typename T>
struct A {
A() : A(42) {}
explicit A(int value) : value_(value) {}
int value_;
};
struct B {
B() : B(42) {}
explicit B(int value) : value_(value) {}
int value_;
};
template <typename T>
struct C {
C() : C(T()) {}
explicit C(T value) : value_(value) {}
T value_;
};
struct V {
unsigned size() const;
};
struct S {
unsigned size_;
S(unsigned size) : size_{size} {}
template<typename U>
S(const U& u) : S(u.size()) {}
};
const V v;
const S s{v};
}