| // 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) |
| } |
| }; |