blob: 73eeb2139b6ab2a42094cab17cf2123c3a737ba4 [file] [log] [blame]
// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer %t -- -- -fcxx-exceptions
extern void __assert_fail (__const char *__assertion, __const char *__file,
unsigned int __line, __const char *__function)
__attribute__ ((__noreturn__));
#define assert(expr) \
((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__))
class Simple1 {
int n;
double x;
public:
Simple1() {
// CHECK-FIXES: Simple1() : n(0), x(0.0) {
n = 0;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
x = 0.0;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
Simple1(int nn, double xx) {
// CHECK-FIXES: Simple1(int nn, double xx) : n(nn), x(xx) {
n = nn;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
x = xx;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
~Simple1() = default;
};
class Simple2 {
int n;
double x;
public:
Simple2() : n(0) {
// CHECK-FIXES: Simple2() : n(0), x(0.0) {
x = 0.0;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
Simple2(int nn, double xx) : n(nn) {
// CHECK-FIXES: Simple2(int nn, double xx) : n(nn), x(xx) {
x = xx;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
~Simple2() = default;
};
class Simple3 {
int n;
double x;
public:
Simple3() : x(0.0) {
// CHECK-FIXES: Simple3() : n(0), x(0.0) {
n = 0;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
Simple3(int nn, double xx) : x(xx) {
// CHECK-FIXES: Simple3(int nn, double xx) : n(nn), x(xx) {
n = nn;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
~Simple3() = default;
};
int something_int();
double something_double();
class Simple4 {
int n;
public:
Simple4() {
// CHECK-FIXES: Simple4() : n(something_int()) {
n = something_int();
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
~Simple4() = default;
};
static bool dice();
class Complex1 {
int n;
int m;
public:
Complex1() : n(0) {
if (dice())
m = 1;
// NO-MESSAGES: initialization of 'm' is nested in a conditional expression
}
~Complex1() = default;
};
class Complex2 {
int n;
int m;
public:
Complex2() : n(0) {
if (!dice())
return;
m = 1;
// NO-MESSAGES: initialization of 'm' follows a conditional expression
}
~Complex2() = default;
};
class Complex3 {
int n;
int m;
public:
Complex3() : n(0) {
while (dice())
m = 1;
// NO-MESSAGES: initialization of 'm' is nested in a conditional loop
}
~Complex3() = default;
};
class Complex4 {
int n;
int m;
public:
Complex4() : n(0) {
while (!dice())
return;
m = 1;
// NO-MESSAGES: initialization of 'm' follows a conditional loop
}
~Complex4() = default;
};
class Complex5 {
int n;
int m;
public:
Complex5() : n(0) {
do {
m = 1;
// NO-MESSAGES: initialization of 'm' is nested in a conditional loop
} while (dice());
}
~Complex5() = default;
};
class Complex6 {
int n;
int m;
public:
Complex6() : n(0) {
do {
return;
} while (!dice());
m = 1;
// NO-MESSAGES: initialization of 'm' follows a conditional loop
}
~Complex6() = default;
};
class Complex7 {
int n;
int m;
public:
Complex7() : n(0) {
for (int i = 2; i < 1; ++i) {
m = 1;
}
// NO-MESSAGES: initialization of 'm' is nested into a conditional loop
}
~Complex7() = default;
};
class Complex8 {
int n;
int m;
public:
Complex8() : n(0) {
for (int i = 0; i < 2; ++i) {
return;
}
m = 1;
// NO-MESSAGES: initialization of 'm' follows a conditional loop
}
~Complex8() = default;
};
class Complex9 {
int n;
int m;
public:
Complex9() : n(0) {
switch (dice()) {
case 1:
m = 1;
// NO-MESSAGES: initialization of 'm' is nested in a conditional expression
break;
default:
break;
}
}
~Complex9() = default;
};
class Complex10 {
int n;
int m;
public:
Complex10() : n(0) {
switch (dice()) {
case 1:
return;
break;
default:
break;
}
m = 1;
// NO-MESSAGES: initialization of 'm' follows a conditional expression
}
~Complex10() = default;
};
class E {};
int risky(); // may throw
class Complex11 {
int n;
int m;
public:
Complex11() : n(0) {
try {
risky();
m = 1;
// NO-MESSAGES: initialization of 'm' follows is nested in a try-block
} catch (const E& e) {
return;
}
}
~Complex11() = default;
};
class Complex12 {
int n;
int m;
public:
Complex12() : n(0) {
try {
risky();
} catch (const E& e) {
return;
}
m = 1;
// NO-MESSAGES: initialization of 'm' follows a try-block
}
~Complex12() = default;
};
class Complex13 {
int n;
int m;
public:
Complex13() : n(0) {
return;
m = 1;
// NO-MESSAGES: initialization of 'm' follows a return statement
}
~Complex13() = default;
};
class Complex14 {
int n;
int m;
public:
Complex14() : n(0) {
goto X;
m = 1;
// NO-MESSAGES: initialization of 'm' follows a goto statement
X:
;
}
~Complex14() = default;
};
void returning();
class Complex15 {
int n;
int m;
public:
Complex15() : n(0) {
// CHECK-FIXES: Complex15() : n(0), m(1) {
returning();
m = 1;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
~Complex15() = default;
};
[[noreturn]] void not_returning();
class Complex16 {
int n;
int m;
public:
Complex16() : n(0) {
not_returning();
m = 1;
// NO-MESSAGES: initialization of 'm' follows a non-returning function call
}
~Complex16() = default;
};
class Complex17 {
int n;
int m;
public:
Complex17() : n(0) {
throw 1;
m = 1;
// NO-MESSAGES: initialization of 'm' follows a 'throw' statement;
}
~Complex17() = default;
};
class Complex18 {
int n;
public:
Complex18() try {
n = risky();
// NO-MESSAGES: initialization of 'n' in a 'try' body;
} catch (const E& e) {
n = 0;
}
~Complex18() = default;
};
class Complex19 {
int n;
public:
Complex19() {
// CHECK-FIXES: Complex19() : n(0) {
n = 0;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
explicit Complex19(int) {
// CHECK-FIXES: Complex19(int) : n(12) {
n = 12;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
~Complex19() = default;
};
class Complex20 {
int n;
int m;
public:
Complex20(int k) : n(0) {
assert(k > 0);
m = 1;
// NO-MESSAGES: initialization of 'm' follows an assertion
}
~Complex20() = default;
};
class VeryComplex1 {
int n1, n2, n3;
double x1, x2, x3;
int n4, n5, n6;
double x4, x5, x6;
VeryComplex1() : n3(something_int()), x3(something_double()),
n5(something_int()), x4(something_double()),
x5(something_double()) {
// CHECK-FIXES: VeryComplex1() : n2(something_int()), n1(something_int()), n3(something_int()), x2(something_double()), x1(something_double()), x3(something_double()),
// CHECK-FIXES: n4(something_int()), n5(something_int()), n6(something_int()), x4(something_double()),
// CHECK-FIXES: x5(something_double()), x6(something_double()) {
// FIXME: Order of elements on the constructor initializer list should match
// the order of the declaration of the fields. Thus the correct fixes
// should look like these:
//
// C ECK-FIXES: VeryComplex1() : n2(something_int()), n1(something_int()), n3(something_int()), x2(something_double()), x1(something_double()), x3(something_double()),
// C ECK-FIXES: n4(something_int()), n5(something_int()), n6(something_int()), x4(something_double()),
// C ECK-FIXES: x5(something_double()), x6(something_double()) {
//
// However, the Diagnostics Engine processes fixes in the order of the
// diagnostics and insertions to the same position are handled in left to
// right order thus in the case two adjacent fields are initialized
// inside the constructor in reverse order the provided fix is a
// constructor initializer list that does not match the order of the
// declaration of the fields.
x2 = something_double();
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x2' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
n2 = something_int();
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n2' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
x6 = something_double();
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x6' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
x1 = something_double();
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x1' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
n6 = something_int();
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n6' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
n1 = something_int();
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n1' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
n4 = something_int();
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n4' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
};
struct Outside {
int n;
double x;
Outside();
};
Outside::Outside() {
// CHECK-FIXES: Outside::Outside() : n(1), x(1.0) {
n = 1;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
x = 1.0;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
// CHECK-FIXES: {{^\ *$}}
}
struct SafeDependancy {
int m;
int n;
SafeDependancy(int M) : m(M) {
// CHECK-FIXES: SafeDependancy(int M) : m(M), n(m) {
n = m;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor
}
// We match against direct field dependancy as well as descendant field
// dependancy, ensure both are accounted for.
SafeDependancy(short M) : m(M) {
// CHECK-FIXES: SafeDependancy(short M) : m(M), n(m + 1) {
n = m + 1;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor
}
};
struct BadDependancy {
int m;
int n;
BadDependancy(int N) : n(N) {
m = n;
}
BadDependancy(short N) : n(N) {
m = n + 1;
}
};
struct InitFromVarDecl {
int m;
InitFromVarDecl() {
// Can't apply this fix as n is declared in the body of the constructor.
int n = 3;
m = n;
}
};
struct AlreadyHasInit {
int m = 4;
AlreadyHasInit() {
m = 3;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm' should be initialized in a member initializer of the constructor
}
};
#define ASSIGN_IN_MACRO(FIELD, VALUE) FIELD = (VALUE);
struct MacroCantFix {
int n; // NoFix
// CHECK-FIXES: int n; // NoFix
MacroCantFix() {
ASSIGN_IN_MACRO(n, 0)
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'n' should be initialized in a member initializer of the constructor
// CHECK-FIXES: ASSIGN_IN_MACRO(n, 0)
}
};