666 lines · cpp
1// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer %t -- -- -fcxx-exceptions2 3extern void __assert_fail (__const char *__assertion, __const char *__file,4 unsigned int __line, __const char *__function)5 __attribute__ ((__noreturn__));6#define assert(expr) \7 ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__))8 9class Simple1 {10 int n;11 double x;12 13public:14 Simple1() {15 // CHECK-FIXES: Simple1() : n(0), x(0.0) {16 n = 0;17 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]18 // CHECK-FIXES: {{^\ *$}}19 x = 0.0;20 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]21 // CHECK-FIXES: {{^\ *$}}22 }23 24 Simple1(int nn, double xx) {25 // CHECK-FIXES: Simple1(int nn, double xx) : n(nn), x(xx) {26 n = nn;27 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]28 // CHECK-FIXES: {{^\ *$}}29 x = xx;30 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]31 // CHECK-FIXES: {{^\ *$}}32 }33 34 ~Simple1() = default;35};36 37class Simple2 {38 int n;39 double x;40 41public:42 Simple2() : n(0) {43 // CHECK-FIXES: Simple2() : n(0), x(0.0) {44 x = 0.0;45 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]46 // CHECK-FIXES: {{^\ *$}}47 }48 49 Simple2(int nn, double xx) : n(nn) {50 // CHECK-FIXES: Simple2(int nn, double xx) : n(nn), x(xx) {51 x = xx;52 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]53 // CHECK-FIXES: {{^\ *$}}54 }55 56 ~Simple2() = default;57};58 59class Simple3 {60 int n;61 double x;62 63public:64 Simple3() : x(0.0) {65 // CHECK-FIXES: Simple3() : n(0), x(0.0) {66 n = 0;67 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]68 // CHECK-FIXES: {{^\ *$}}69 }70 71 Simple3(int nn, double xx) : x(xx) {72 // CHECK-FIXES: Simple3(int nn, double xx) : n(nn), x(xx) {73 n = nn;74 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]75 // CHECK-FIXES: {{^\ *$}}76 }77 78 ~Simple3() = default;79};80 81int something_int();82double something_double();83 84class Simple4 {85 int n;86 87public:88 Simple4() {89 // CHECK-FIXES: Simple4() : n(something_int()) {90 n = something_int();91 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]92 // CHECK-FIXES: {{^\ *$}}93 }94 95 ~Simple4() = default;96};97 98static bool dice();99 100class Complex1 {101 int n;102 int m;103 104public:105 Complex1() : n(0) {106 if (dice())107 m = 1;108 // NO-MESSAGES: initialization of 'm' is nested in a conditional expression109 }110 111 ~Complex1() = default;112};113 114class Complex2 {115 int n;116 int m;117 118public:119 Complex2() : n(0) {120 if (!dice())121 return;122 m = 1;123 // NO-MESSAGES: initialization of 'm' follows a conditional expression124 }125 126 ~Complex2() = default;127};128 129class Complex3 {130 int n;131 int m;132 133public:134 Complex3() : n(0) {135 while (dice())136 m = 1;137 // NO-MESSAGES: initialization of 'm' is nested in a conditional loop138 }139 140 ~Complex3() = default;141};142 143class Complex4 {144 int n;145 int m;146 147public:148 Complex4() : n(0) {149 while (!dice())150 return;151 m = 1;152 // NO-MESSAGES: initialization of 'm' follows a conditional loop153 }154 155 ~Complex4() = default;156};157 158class Complex5 {159 int n;160 int m;161 162public:163 Complex5() : n(0) {164 do {165 m = 1;166 // NO-MESSAGES: initialization of 'm' is nested in a conditional loop167 } while (dice());168 }169 170 ~Complex5() = default;171};172 173class Complex6 {174 int n;175 int m;176 177public:178 Complex6() : n(0) {179 do {180 return;181 } while (!dice());182 m = 1;183 // NO-MESSAGES: initialization of 'm' follows a conditional loop184 }185 186 ~Complex6() = default;187};188 189class Complex7 {190 int n;191 int m;192 193public:194 Complex7() : n(0) {195 for (int i = 2; i < 1; ++i) {196 m = 1;197 }198 // NO-MESSAGES: initialization of 'm' is nested into a conditional loop199 }200 201 ~Complex7() = default;202};203 204class Complex8 {205 int n;206 int m;207 208public:209 Complex8() : n(0) {210 for (int i = 0; i < 2; ++i) {211 return;212 }213 m = 1;214 // NO-MESSAGES: initialization of 'm' follows a conditional loop215 }216 217 ~Complex8() = default;218};219 220class Complex9 {221 int n;222 int m;223 224public:225 Complex9() : n(0) {226 switch (dice()) {227 case 1:228 m = 1;229 // NO-MESSAGES: initialization of 'm' is nested in a conditional expression230 break;231 default:232 break;233 }234 }235 236 ~Complex9() = default;237};238 239class Complex10 {240 int n;241 int m;242 243public:244 Complex10() : n(0) {245 switch (dice()) {246 case 1:247 return;248 break;249 default:250 break;251 }252 m = 1;253 // NO-MESSAGES: initialization of 'm' follows a conditional expression254 }255 256 ~Complex10() = default;257};258 259class E {};260int risky(); // may throw261 262class Complex11 {263 int n;264 int m;265 266public:267 Complex11() : n(0) {268 try {269 risky();270 m = 1;271 // NO-MESSAGES: initialization of 'm' follows is nested in a try-block272 } catch (const E& e) {273 return;274 }275 }276 277 ~Complex11() = default;278};279 280class Complex12 {281 int n;282 int m;283 284public:285 Complex12() : n(0) {286 try {287 risky();288 } catch (const E& e) {289 return;290 }291 m = 1;292 // NO-MESSAGES: initialization of 'm' follows a try-block293 }294 295 ~Complex12() = default;296};297 298class Complex13 {299 int n;300 int m;301 302public:303 Complex13() : n(0) {304 return;305 m = 1;306 // NO-MESSAGES: initialization of 'm' follows a return statement307 }308 309 ~Complex13() = default;310};311 312class Complex14 {313 int n;314 int m;315 316public:317 Complex14() : n(0) {318 goto X;319 m = 1;320 // NO-MESSAGES: initialization of 'm' follows a goto statement321 X:322 ;323 }324 325 ~Complex14() = default;326};327 328void returning();329 330class Complex15 {331 int n;332 int m;333 334public:335 Complex15() : n(0) {336 // CHECK-FIXES: Complex15() : n(0), m(1) {337 returning();338 m = 1;339 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]340 // CHECK-FIXES: {{^\ *$}}341 }342 343 ~Complex15() = default;344};345 346[[noreturn]] void not_returning();347 348class Complex16 {349 int n;350 int m;351 352public:353 Complex16() : n(0) {354 not_returning();355 m = 1;356 // NO-MESSAGES: initialization of 'm' follows a non-returning function call357 }358 359 ~Complex16() = default;360};361 362class Complex17 {363 int n;364 int m;365 366public:367 Complex17() : n(0) {368 throw 1;369 m = 1;370 // NO-MESSAGES: initialization of 'm' follows a 'throw' statement;371 }372 373 ~Complex17() = default;374};375 376class Complex18 {377 int n;378 379public:380 Complex18() try {381 n = risky();382 // NO-MESSAGES: initialization of 'n' in a 'try' body;383 } catch (const E& e) {384 n = 0;385 }386 387 ~Complex18() = default;388};389 390class Complex19 {391 int n;392public:393 Complex19() {394 // CHECK-FIXES: Complex19() : n(0) {395 n = 0;396 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]397 // CHECK-FIXES: {{^\ *$}}398 }399 400 explicit Complex19(int) {401 // CHECK-FIXES: explicit Complex19(int) : n(12) {402 n = 12;403 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]404 // CHECK-FIXES: {{^\ *$}}405 }406 407 ~Complex19() = default;408};409 410class Complex20 {411 int n;412 int m;413 414public:415 Complex20(int k) : n(0) {416 assert(k > 0);417 m = 1;418 // NO-MESSAGES: initialization of 'm' follows an assertion419 }420 421 ~Complex20() = default;422};423 424class VeryComplex1 {425 int n1, n2, n3;426 double x1, x2, x3;427 int n4, n5, n6;428 double x4, x5, x6;429 430 VeryComplex1() : n3(something_int()), x3(something_double()),431 n5(something_int()), x4(something_double()),432 x5(something_double()) {433 // CHECK-FIXES: VeryComplex1() : n2(something_int()), n1(something_int()), n3(something_int()), x2(something_double()), x1(something_double()), x3(something_double()),434 // CHECK-FIXES: n4(something_int()), n5(something_int()), n6(something_int()), x4(something_double()),435 // CHECK-FIXES: x5(something_double()), x6(something_double()) {436 437// FIXME: Order of elements on the constructor initializer list should match438// the order of the declaration of the fields. Thus the correct fixes439// should look like these:440//441 // C ECK-FIXES: VeryComplex1() : n2(something_int()), n1(something_int()), n3(something_int()), x2(something_double()), x1(something_double()), x3(something_double()),442 // C ECK-FIXES: n4(something_int()), n5(something_int()), n6(something_int()), x4(something_double()),443 // C ECK-FIXES: x5(something_double()), x6(something_double()) {444//445// However, the Diagnostics Engine processes fixes in the order of the446// diagnostics and insertions to the same position are handled in left to447// right order thus in the case two adjacent fields are initialized448// inside the constructor in reverse order the provided fix is a449// constructor initializer list that does not match the order of the450// declaration of the fields.451 452 x2 = something_double();453 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x2' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]454 // CHECK-FIXES: {{^\ *$}}455 n2 = something_int();456 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n2' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]457 // CHECK-FIXES: {{^\ *$}}458 x6 = something_double();459 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x6' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]460 // CHECK-FIXES: {{^\ *$}}461 x1 = something_double();462 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x1' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]463 // CHECK-FIXES: {{^\ *$}}464 n6 = something_int();465 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n6' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]466 // CHECK-FIXES: {{^\ *$}}467 n1 = something_int();468 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n1' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]469 // CHECK-FIXES: {{^\ *$}}470 n4 = something_int();471 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n4' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]472 // CHECK-FIXES: {{^\ *$}}473 }474};475 476struct Outside {477 int n;478 double x;479 Outside();480};481 482Outside::Outside() {483 // CHECK-FIXES: Outside::Outside() : n(1), x(1.0) {484 n = 1;485 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]486 // CHECK-FIXES: {{^\ *$}}487 x = 1.0;488 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]489 // CHECK-FIXES: {{^\ *$}}490}491 492struct SafeDependancy {493 int m;494 int n;495 SafeDependancy(int M) : m(M) {496 // CHECK-FIXES: SafeDependancy(int M) : m(M), n(m) {497 n = m;498 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor499 }500 // We match against direct field dependancy as well as descendant field501 // dependancy, ensure both are accounted for.502 SafeDependancy(short M) : m(M) {503 // CHECK-FIXES: SafeDependancy(short M) : m(M), n(m + 1) {504 n = m + 1;505 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor506 }507};508 509struct BadDependancy {510 int m;511 int n;512 BadDependancy(int N) : n(N) {513 m = n;514 }515 BadDependancy(short N) : n(N) {516 m = n + 1;517 }518};519 520struct InitFromVarDecl {521 int m;522 InitFromVarDecl() {523 // Can't apply this fix as n is declared in the body of the constructor.524 int n = 3;525 m = n;526 }527};528 529struct HasInClassInit {530 int m = 4;531 HasInClassInit() {532 m = 3;533 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm' should be initialized in a member initializer of the constructor534 }535};536 537struct HasInitListInit {538 int M;539 // CHECK-MESSAGES: :[[@LINE+5]]:5: warning: 'M' should be initialized in a member initializer of the constructor540 // CHECK-FIXES: HasInitListInit(const HasInitListInit &Other) : M(Other.M) {541 // CHECK-FIXES-NEXT: {{^ $}}542 // CHECK-FIXES-NEXT: }543 HasInitListInit(const HasInitListInit &Other) : M(4) {544 M = Other.M;545 }546 // CHECK-MESSAGES: :[[@LINE+5]]:5: warning: 'M' should be initialized in a member initializer of the constructor547 // CHECK-FIXES: HasInitListInit(HasInitListInit &&Other) : M(Other.M) {548 // CHECK-FIXES-NEXT: {{^ $}}549 // CHECK-FIXES-NEXT: }550 HasInitListInit(HasInitListInit &&Other) : M() {551 M = Other.M;552 }553};554 555#define ASSIGN_IN_MACRO(FIELD, VALUE) FIELD = (VALUE);556 557struct MacroCantFix {558 int n; // NoFix559 // CHECK-FIXES: int n; // NoFix560 MacroCantFix() {561 ASSIGN_IN_MACRO(n, 0)562 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: 'n' should be initialized in a member initializer of the constructor563 // CHECK-FIXES: ASSIGN_IN_MACRO(n, 0)564 }565};566 567struct PR52818 {568 PR52818() : bar(5) {}569 PR52818(int) : PR52818() { bar = 3; }570 571 int bar;572};573 574struct RefReassignment {575 RefReassignment(int &i) : m_i{i} {576 m_i = 1;577 }578 int & m_i;579};580 581struct ReassignmentAfterUnsafetyAssignment {582 ReassignmentAfterUnsafetyAssignment() {583 int a = 10;584 m_i = a;585 m_i = 1;586 }587 int m_i;588};589 590namespace PR70189 {591#define RGB(r,g,b) ((unsigned long)(((unsigned char)(r)|((unsigned short)((unsigned char)(g))<<8))|(((unsigned long)(unsigned char)(b))<<16)))592#define INVALID_HANDLE_VALUE ((void*)(unsigned long long)-1)593#define SIMPLE 12594 595class Foo {596public:597 Foo() {598// CHECK-FIXES: Foo() : m_color(RGB(255, 128, 0)), m_handle(INVALID_HANDLE_VALUE), m_myval(SIMPLE) {599 m_color = RGB(255, 128, 0);600// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm_color' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]601// CHECK-FIXES: {{^\ *$}}602 m_handle = INVALID_HANDLE_VALUE;603// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm_handle' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]604// CHECK-FIXES: {{^\ *$}}605 m_myval = SIMPLE;606// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm_myval' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]607// CHECK-FIXES: {{^\ *$}}608 }609private:610 unsigned long m_color;611 void* m_handle;612 int m_myval;613};614 615#undef SIMPLE616#undef INVALID_HANDLE_VALUE617#undef RGB618}619 620namespace GH77684 {621struct S1 {622// CHECK-MESSAGES: :[[@LINE+1]]:16: warning: 'M' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]623 S1() : M{} { M = 0; }624// CHECK-FIXES: S1() : M{0} { }625 int M;626};627struct S2 {628// CHECK-MESSAGES: :[[@LINE+1]]:17: warning: 'M' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]629 S2() : M{2} { M = 1; }630// CHECK-FIXES: S2() : M{1} { }631 int M;632};633struct T { int a; int b; int c; };634T v;635struct S3 {636// CHECK-MESSAGES: :[[@LINE+1]]:21: warning: 'M' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer]637 S3() : M{1,2,3} { M = v; }638// CHECK-FIXES: S3() : M{v} { }639 T M;640};641}642 643namespace GH82970 {644struct InitFromBindingDecl {645 int m;646 InitFromBindingDecl() {647 struct { int i; } a;648 auto [n] = a;649 m = n;650 }651};652} // namespace GH82970653 654struct A {655 int m;656};657 658struct B : A {659 B() { m = 0; }660};661 662template <class T>663struct C : A {664 C() { m = 0; }665};666