// 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 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