
```cpp
struct Base {
int m;
};
template <class T>
struct Derived : Base {
Derived() { m = 0; }
};
```
would previously generate the following output:
```
<source>:7:15: warning: 'm' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
7 | Derived() { m = 0; }
| ^~~~~~
| : m(0)
```
This patch fixes this false positive.
Note that before this patch the checker won't give false positive for
```cpp
struct Derived : Base {
Derived() { m = 0; }
};
```
and the constructor's AST is
```
`-CXXConstructorDecl 0x557df03d1fb0 <line:7:3, col:22> col:3 Derived 'void ()' implicit-inline
|-CXXCtorInitializer 'Base'
| `-CXXConstructExpr 0x557df03d2748 <col:3> 'Base' 'void () noexcept'
`-CompoundStmt 0x557df03d2898 <col:13, col:22>
`-BinaryOperator 0x557df03d2878 <col:15, col:19> 'int' lvalue '='
|-MemberExpr 0x557df03d2828 <col:15> 'int' lvalue ->m 0x557df03d1c40
| `-ImplicitCastExpr 0x557df03d2808 <col:15> 'Base *' <UncheckedDerivedToBase (Base)>
| `-CXXThisExpr 0x557df03d27f8 <col:15> 'Derived *' implicit this
`-IntegerLiteral 0x557df03d2858 <col:19> 'int' 0
```
so `isAssignmentToMemberOf` would return empty due to
f0967fca04/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp (L118-L119)
Fixes #104400
666 lines
16 KiB
C++
666 lines
16 KiB
C++
// RUN: %check_clang_tidy --match-partial-fixes %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 HasInClassInit {
|
|
int m = 4;
|
|
HasInClassInit() {
|
|
m = 3;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm' should be initialized in a member initializer of the constructor
|
|
}
|
|
};
|
|
|
|
struct HasInitListInit {
|
|
int M;
|
|
// CHECK-MESSAGES: :[[@LINE+5]]:5: warning: 'M' should be initialized in a member initializer of the constructor
|
|
// CHECK-FIXES: HasInitListInit(const HasInitListInit &Other) : M(Other.M) {
|
|
// CHECK-FIXES-NEXT: {{^ $}}
|
|
// CHECK-FIXES-NEXT: }
|
|
HasInitListInit(const HasInitListInit &Other) : M(4) {
|
|
M = Other.M;
|
|
}
|
|
// CHECK-MESSAGES: :[[@LINE+5]]:5: warning: 'M' should be initialized in a member initializer of the constructor
|
|
// CHECK-FIXES: HasInitListInit(HasInitListInit &&Other) : M(Other.M) {
|
|
// CHECK-FIXES-NEXT: {{^ $}}
|
|
// CHECK-FIXES-NEXT: }
|
|
HasInitListInit(HasInitListInit &&Other) : M() {
|
|
M = Other.M;
|
|
}
|
|
};
|
|
|
|
#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)
|
|
}
|
|
};
|
|
|
|
struct PR52818 {
|
|
PR52818() : bar(5) {}
|
|
PR52818(int) : PR52818() { bar = 3; }
|
|
|
|
int bar;
|
|
};
|
|
|
|
struct RefReassignment {
|
|
RefReassignment(int &i) : m_i{i} {
|
|
m_i = 1;
|
|
}
|
|
int & m_i;
|
|
};
|
|
|
|
struct ReassignmentAfterUnsafetyAssignment {
|
|
ReassignmentAfterUnsafetyAssignment() {
|
|
int a = 10;
|
|
m_i = a;
|
|
m_i = 1;
|
|
}
|
|
int m_i;
|
|
};
|
|
|
|
namespace PR70189 {
|
|
#define RGB(r,g,b) ((unsigned long)(((unsigned char)(r)|((unsigned short)((unsigned char)(g))<<8))|(((unsigned long)(unsigned char)(b))<<16)))
|
|
#define INVALID_HANDLE_VALUE ((void*)(unsigned long long)-1)
|
|
#define SIMPLE 12
|
|
|
|
class Foo {
|
|
public:
|
|
Foo() {
|
|
// CHECK-FIXES: Foo() : m_color(RGB(255, 128, 0)), m_handle(INVALID_HANDLE_VALUE), m_myval(SIMPLE) {
|
|
m_color = RGB(255, 128, 0);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm_color' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
|
|
// CHECK-FIXES: {{^\ *$}}
|
|
m_handle = INVALID_HANDLE_VALUE;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm_handle' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
|
|
// CHECK-FIXES: {{^\ *$}}
|
|
m_myval = SIMPLE;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm_myval' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
|
|
// CHECK-FIXES: {{^\ *$}}
|
|
}
|
|
private:
|
|
unsigned long m_color;
|
|
void* m_handle;
|
|
int m_myval;
|
|
};
|
|
|
|
#undef SIMPLE
|
|
#undef INVALID_HANDLE_VALUE
|
|
#undef RGB
|
|
}
|
|
|
|
namespace GH77684 {
|
|
struct S1 {
|
|
// CHECK-MESSAGES: :[[@LINE+1]]:16: warning: 'M' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
|
|
S1() : M{} { M = 0; }
|
|
// CHECK-FIXES: S1() : M{0} { }
|
|
int M;
|
|
};
|
|
struct S2 {
|
|
// CHECK-MESSAGES: :[[@LINE+1]]:17: warning: 'M' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
|
|
S2() : M{2} { M = 1; }
|
|
// CHECK-FIXES: S2() : M{1} { }
|
|
int M;
|
|
};
|
|
struct T { int a; int b; int c; };
|
|
T v;
|
|
struct S3 {
|
|
// CHECK-MESSAGES: :[[@LINE+1]]:21: warning: 'M' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]
|
|
S3() : M{1,2,3} { M = v; }
|
|
// CHECK-FIXES: S3() : M{v} { }
|
|
T M;
|
|
};
|
|
}
|
|
|
|
namespace GH82970 {
|
|
struct InitFromBindingDecl {
|
|
int m;
|
|
InitFromBindingDecl() {
|
|
struct { int i; } a;
|
|
auto [n] = a;
|
|
m = n;
|
|
}
|
|
};
|
|
} // namespace GH82970
|
|
|
|
struct A {
|
|
int m;
|
|
};
|
|
|
|
struct B : A {
|
|
B() { m = 0; }
|
|
};
|
|
|
|
template <class T>
|
|
struct C : A {
|
|
C() { m = 0; }
|
|
};
|