1072 lines · cpp
1// RUN: %check_clang_tidy %s bugprone-branch-clone %t -- -- -fno-delayed-template-parsing2 3void test_basic1(int in, int &out) {4 if (in > 77)5// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]6 out++;7 else8// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here9 out++;10 11 out++;12}13 14void test_basic2(int in, int &out) {15 if (in > 77) {16// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]17 out++;18 }19 else {20// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here21 out++;22 }23 24 out++;25}26 27void test_basic3(int in, int &out) {28 if (in > 77) {29// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]30 out++;31 }32 else33// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here34 out++;35 36 out++;37}38 39void test_basic4(int in, int &out) {40 if (in > 77) {41 out--;42 }43 else {44 out++;45 }46}47 48void test_basic5(int in, int &out) {49 if (in > 77) {50 out++;51 }52 else {53 out++;54 out++;55 }56}57 58void test_basic6(int in, int &out) {59 if (in > 77) {60 out++;61 }62 else {63 out++, out++;64 }65}66 67void test_basic7(int in, int &out) {68 if (in > 77) {69 out++;70 out++;71 }72 else73 out++;74 75 out++;76}77 78void test_basic8(int in, int &out) {79 if (in > 77) {80// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]81 out++;82 out++;83 } else {84// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here85 out++;86 out++;87 }88 89 if (in % 2)90 out++;91}92 93void test_basic9(int in, int &out) {94 if (in > 77) {95// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]96 if (in % 2)97 out++;98 else99 out--;100 } else {101// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here102 if (in % 2)103 out++;104 else105 out--;106 }107}108 109// If we remove the braces from the previous example, the check recognizes it110// as an `else if`.111void test_basic10(int in, int &out) {112 if (in > 77)113 if (in % 2)114 out++;115 else116 out--;117 else118 if (in % 2)119 out++;120 else121 out--;122 123}124 125void test_basic11(int in, int &out) {126 if (in > 77) {127// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]128 if (in % 2)129 out++;130 else131 out--;132 if (in % 3)133 out++;134 else135 out--;136 } else {137// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here138 if (in % 2)139 out++;140 else141 out--;142 if (in % 3)143 out++;144 else145 out--;146 }147}148 149void test_basic12(int in, int &out) {150 if (in > 77) {151// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]152 } else {153// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here154 }155}156 157void test_basic13(int in, int &out) {158 if (in > 77) {159 // Empty compound statement is not identical to null statement.160 } else;161}162 163// We use a comparison that ignores redundant parentheses:164void test_basic14(int in, int &out) {165 if (in > 77)166 out += 2;167 else168 (out) += (2);169}170 171void test_basic15(int in, int &out) {172 if (in > 77)173 ((out += 2));174 else175 out += 2;176}177 178// ..but does not apply additional simplifications:179void test_basic16(int in, int &out) {180 if (in > 77)181 out += 2;182 else183 out += 1 + 1;184}185 186// ..and does not forget important parentheses:187int test_basic17(int a, int b, int c, int mode) {188 if (mode>8)189 return (a + b) * c;190 else191 return a + b * c;192}193 194//=========--------------------==========//195 196#define PASTE_CODE(x) x197 198void test_macro1(int in, int &out) {199 PASTE_CODE(200 if (in > 77)201// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]202 out++;203 else204// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here205 out++;206 )207 208 out--;209}210 211void test_macro2(int in, int &out) {212 PASTE_CODE(213 if (in > 77)214// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]215 out++;216 )217 else218// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here219 out++;220}221 222void test_macro3(int in, int &out) {223 if (in > 77)224// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]225 out++;226 PASTE_CODE(227 else228// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here229 out++;230 )231}232 233void test_macro4(int in, int &out) {234 if (in > 77)235// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]236 out++;237 else238// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here239 PASTE_CODE(240 out++;241 )242}243 244void test_macro5(int in, int &out) {245 PASTE_CODE(if) (in > 77)246// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: if with identical then and else branches [bugprone-branch-clone]247 out++;248 PASTE_CODE(else)249// CHECK-MESSAGES: :[[@LINE-1]]:14: note: else branch starts here250 out++;251}252 253#define OTHERWISE_INCREASE else out++254 255void test_macro6(int in, int &out) {256 if (in > 77)257 out++;258// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: if with identical then and else branches [bugprone-branch-clone]259 OTHERWISE_INCREASE;260// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here261// CHECK-MESSAGES: :[[@LINE-8]]:28: note: expanded from macro 'OTHERWISE_INCREASE'262}263 264#define COND_INCR(a, b, c) \265 do { \266 if ((a)) \267 (b)++; \268 else \269 (c)++; \270 } while (0)271 272void test_macro7(int in, int &out1, int &out2) {273 COND_INCR(in, out1, out1);274// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]275// CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR'276// CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here277// CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR'278}279 280void test_macro8(int in, int &out1, int &out2) {281 COND_INCR(in, out1, out2);282}283 284void test_macro9(int in, int &out1, int &out2) {285 COND_INCR(in, out2, out2);286// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]287// CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR'288// CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here289// CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR'290}291 292#define CONCAT(a, b) a##b293 294void test_macro10(int in, int &out) {295 CONCAT(i, f) (in > 77)296// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]297 out++;298 CONCAT(el, se)299// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here300 out++;301}302 303#define PROBLEM (-1)304 305int test_macro11(int count) {306 if (!count)307 return PROBLEM;308 else if (count == 13)309 return -1;310 else311 return count * 2;312}313 314#define IF if (315#define THEN ) {316#define ELSE } else {317#define END }318 319void test_macro12(int in, int &out) {320 IF in > 77 THEN321// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]322// CHECK-MESSAGES: :[[@LINE-8]]:12: note: expanded from macro 'IF'323 out++;324 out++;325 ELSE326// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here327// CHECK-MESSAGES: :[[@LINE-11]]:16: note: expanded from macro 'ELSE'328 out++;329 out++;330 END331}332 333// A hack for implementing a switch with no fallthrough:334#define SWITCH(x) switch (x) {335#define CASE(x) break; case (x):336#define DEFAULT break; default:337 338void test_macro13(int in, int &out) {339 SWITCH(in)340// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]341 CASE(1)342 out++;343 out++;344 CASE(2)345 out++;346 out++;347 CASE(3)348 out++;349 out++;350// CHECK-MESSAGES: :[[@LINE-15]]:24: note: expanded from macro 'CASE'351// CHECK-MESSAGES: :[[@LINE+1]]:9: note: last of these clones ends here352 CASE(4)353 out++;354 CASE(5)355// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]356 CASE(6)357 out--;358 CASE(7)359 out--;360// CHECK-MESSAGES: :[[@LINE-25]]:24: note: expanded from macro 'CASE'361// CHECK-MESSAGES: :[[@LINE+2]]:9: note: last of these clones ends here362// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]363 CASE(8)364 out++;365 out++;366 CASE(9)367 out++;368 out++;369// CHECK-MESSAGES: :[[@LINE-34]]:24: note: expanded from macro 'CASE'370// CHECK-MESSAGES: :[[@LINE+2]]:12: note: last of these clones ends here371// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]372 DEFAULT373 out--;374 out--;375 CASE(10)376 out--;377 out--;378// CHECK-MESSAGES: :[[@LINE-42]]:24: note: expanded from macro 'DEFAULT'379// CHECK-MESSAGES: :[[@LINE+1]]:9: note: last of these clones ends here380 CASE(12)381 out++;382 CASE(13)383 out++;384 END385}386 387//=========--------------------==========//388 389void test_chain1(int in, int &out) {390 if (in > 77)391// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]392 out++;393// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original394 else if (in > 55)395// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here396 out++;397 398 out++;399}400 401void test_chain2(int in, int &out) {402 if (in > 77)403// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]404 out++;405// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original406 else if (in > 55)407// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here408 out++;409 else if (in > 42)410 out--;411 else if (in > 28)412// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here413 out++;414 else if (in > 12) {415 out++;416 out *= 7;417 } else if (in > 7) {418// CHECK-MESSAGES: :[[@LINE-1]]:22: note: clone 3 starts here419 out++;420 }421}422 423void test_chain3(int in, int &out) {424 if (in > 77) {425// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]426 out++;427 out++;428// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original429 } else if (in > 55) {430// CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here431 out++;432 out++;433 } else if (in > 42)434 out--;435 else if (in > 28) {436// CHECK-MESSAGES: :[[@LINE-1]]:21: note: clone 2 starts here437 out++;438 out++;439 } else if (in > 12) {440 out++;441 out++;442 out++;443 out *= 7;444 } else if (in > 7) {445// CHECK-MESSAGES: :[[@LINE-1]]:22: note: clone 3 starts here446 out++;447 out++;448 }449}450 451// In this chain there are two clone families; notice that the checker452// describes all branches of the first one before mentioning the second one.453void test_chain4(int in, int &out) {454 if (in > 77) {455// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]456 out++;457 out++;458// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original459 } else if (in > 55) {460// CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here461// CHECK-MESSAGES: :[[@LINE+8]]:21: note: clone 2 starts here462// CHECK-MESSAGES: :[[@LINE+15]]:22: note: clone 3 starts here463 out++;464 out++;465 } else if (in > 42)466// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]467 out--;468// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original469 else if (in > 28) {470 out++;471 out++;472 } else if (in > 12) {473 out++;474 out++;475 out++;476 out *= 7;477 } else if (in > 7) {478 out++;479 out++;480 } else if (in > -3) {481// CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here482 out--;483 }484}485 486void test_chain5(int in, int &out) {487 if (in > 77)488// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]489 out++;490// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original491 else if (in > 55)492// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here493 out++;494 else if (in > 42)495 out--;496 else if (in > 28)497// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here498 out++;499 else if (in > 12) {500 out++;501 out *= 7;502 } else {503// CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here504 out++;505 }506}507 508void test_chain6(int in, int &out) {509 if (in > 77) {510// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]511 out++;512 out++;513// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original514 } else if (in > 55) {515// CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here516 out++;517 out++;518 } else if (in > 42)519 out--;520 else if (in > 28) {521// CHECK-MESSAGES: :[[@LINE-1]]:21: note: clone 2 starts here522 out++;523 out++;524 } else if (in > 12) {525 out++;526 out++;527 out++;528 out *= 7;529 } else {530// CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here531 out++;532 out++;533 }534}535 536void test_nested(int a, int b, int c, int &out) {537 if (a > 5) {538// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]539// CHECK-MESSAGES: :[[@LINE+27]]:5: note: else branch starts here540 if (b > 5) {541// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]542// CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original543// CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here544// CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here545 if (c > 5)546// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]547 out++;548 else549// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here550 out++;551 } else if (b > 15) {552 if (c > 5)553// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]554 out++;555 else556// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here557 out++;558 } else {559 if (c > 5)560// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]561 out++;562 else563// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here564 out++;565 }566 } else {567 if (b > 5) {568// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]569// CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original570// CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here571// CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here572 if (c > 5)573// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]574 out++;575 else576// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here577 out++;578 } else if (b > 15) {579 if (c > 5)580// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]581 out++;582 else583// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here584 out++;585 } else {586 if (c > 5)587// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]588 out++;589 else590// CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here591 out++;592 }593 }594}595 596//=========--------------------==========//597 598template <class T>599void test_template_not_instantiated(const T &t) {600 int a;601 if (t)602// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]603 a++;604 else605// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here606 a++;607}608 609template <class T>610void test_template_instantiated(const T &t) {611 int a;612 if (t)613// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]614 a++;615 else616// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here617 a++;618}619 620template void test_template_instantiated<int>(const int &t);621 622template <class T>623void test_template2(T t, int a) {624 if (a) {625 T b(0);626 a += b;627 } else {628 int b(0);629 a += b;630 }631}632 633template void test_template2<int>(int t, int a);634 635template <class T>636void test_template3(T t, int a) {637 if (a) {638 T b(0);639 a += b;640 } else {641 int b(0);642 a += b;643 }644}645 646template void test_template3<short>(short t, int a);647 648template <class T>649void test_template_two_instances(T t, int &a) {650 if (a) {651// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]652 a += int(t);653 } else {654// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here655 a += int(t);656 }657}658 659template void test_template_two_instances<short>(short t, int &a);660template void test_template_two_instances<long>(long t, int &a);661 662class C {663 int member;664 void inline_method(int arg) {665 if (arg)666// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]667 member = 3;668 else669// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here670 member = 3;671 }672 int other_method();673};674 675int C::other_method() {676 if (member) {677// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]678 return 8;679 } else {680// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here681 return 8;682 }683}684 685//=========--------------------==========//686 687int simple_switch(char ch) {688 switch (ch) {689// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]690 case 'a':691 return 10;692 case 'A':693 return 10;694// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here695// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]696 case 'b':697 return 11;698 case 'B':699 return 11;700// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here701// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]702 case 'c':703 return 10;704 case 'C':705 return 10;706// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here707 default:708 return 0;709 }710}711 712int long_sequence_switch(char ch) {713 switch (ch) {714// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 7 consecutive identical branches [bugprone-branch-clone]715 case 'a':716 return 10;717 case 'A':718 return 10;719 case 'b':720 return 10;721 case 'B':722 return 10;723 case 'c':724 return 10;725 case 'C':726 return 10;727 default:728 return 10;729// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here730 }731}732 733int nested_switch(int a, int b, int c) {734 switch (a) {735// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]736// CHECK-MESSAGES: :[[@LINE+114]]:6: note: last of these clones ends here737 case 1:738 switch (b) {739// CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]740// CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here741 case 1:742 switch (c) {743// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]744 case 1:745 return 42;746 case 2:747 return 42;748 default:749 return 42;750// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here751 }752 case 2:753 switch (c) {754// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]755 case 1:756 return 42;757 case 2:758 return 42;759 default:760 return 42;761// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here762 }763 default:764 switch (c) {765// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]766 case 1:767 return 42;768 case 2:769 return 42;770 default:771 return 42;772// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here773 }774 }775 case 2:776 switch (b) {777// CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]778// CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here779 case 1:780 switch (c) {781// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]782 case 1:783 return 42;784 case 2:785 return 42;786 default:787 return 42;788// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here789 }790 case 2:791 switch (c) {792// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]793 case 1:794 return 42;795 case 2:796 return 42;797 default:798 return 42;799// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here800 }801 default:802 switch (c) {803// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]804 case 1:805 return 42;806 case 2:807 return 42;808 default:809 return 42;810// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here811 }812 }813 default:814 switch (b) {815// CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]816// CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here817 case 1:818 switch (c) {819// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]820 case 1:821 return 42;822 case 2:823 return 42;824 default:825 return 42;826// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here827 }828 case 2:829 switch (c) {830// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]831 case 1:832 return 42;833 case 2:834 return 42;835 default:836 return 42;837// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here838 }839 default:840 switch (c) {841// CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]842 case 1:843 return 42;844 case 2:845 return 42;846 default:847 return 42;848// CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here849 }850 }851 }852}853 854//=========--------------------==========//855 856// This should not produce warnings, as in switch statements we only report857// identical branches when they are consecutive. Also note that a branch858// terminated by a break is different from a branch terminated by the end of859// the switch statement.860int interleaved_cases(int a, int b) {861 switch (a) {862 case 3:863 case 4:864 b = 2;865 break;866 case 5:867 b = 3;868 break;869 case 6:870 b = 2;871 break;872 case 7:873 if (b % 2) {874 b++;875 } else {876 b++;877 break;878 }879 b = 2;880 break;881 case 8:882 b = 2;883 case 9:884 b = 3;885 break;886 default:887 b = 3;888 }889 return b;890}891 892 893// A case: or default: is only considered to be the start of a branch if it is a direct child of the CompoundStmt forming the body of the switch894int buried_cases(int foo) {895 switch (foo) {896 {897 case 36:898 return 8;899 default:900 return 8;901 }902 }903}904 905// Here the `case 7:` is a child statement of the GotoLabelStmt, so the checker906// thinks that it is part of the `case 9:` branch. While this result is907// counterintuitve, mixing goto labels and switch statements in this fashion is908// pretty rare, so it does not deserve a special case in the checker code.909int decorated_cases(int z) {910 if (!(z % 777)) {911 goto lucky;912 }913 switch (z) {914// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]915 case 1:916 case 2:917 case 3:918 z++;919 break;920 case 4:921 case 5:922 z++;923 break;924// CHECK-MESSAGES: :[[@LINE-1]]:10: note: last of these clones ends here925 case 9:926 z++;927 break;928 lucky:929 case 7:930 z += 3;931 z *= 2;932 break;933 case 92:934 z += 3;935 z *= 2;936 break;937 default:938 z++;939 }940 return z + 92;941}942 943// The child of the switch statement is not necessarily a compound statement,944// do not crash in this unusual case.945char no_real_body(int in, int &out) {946 switch (in)947 case 42:948 return 'A';949 950 if (in > 77)951// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]952 out++;953// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original954 else if (in > 55)955// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here956 out++;957 else if (in > 34)958// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here959 out++;960 961 return '|';962}963 964// Duff's device [https://en.wikipedia.org/wiki/Duff's_device]965// The check does not try to distinguish branches in this sort of convoluted966// code, but it should avoid crashing.967void send(short *to, short *from, int count)968{969 int n = (count + 7) / 8;970 switch (count % 8) {971 case 0: do { *to = *from++;972 case 7: *to = *from++;973 case 6: *to = *from++;974 case 5: *to = *from++;975 case 4: *to = *from++;976 case 3: *to = *from++;977 case 2: *to = *from++;978 case 1: *to = *from++;979 } while (--n > 0);980 }981}982 983//=========--------------------==========//984 985void ternary1(bool b, int &x) {986// CHECK-MESSAGES: :[[@LINE+1]]:6: warning: conditional operator with identical true and false expressions [bugprone-branch-clone]987 (b ? x : x) = 42;988}989 990int ternary2(bool b, int x) {991// CHECK-MESSAGES: :[[@LINE+1]]:12: warning: conditional operator with identical true and false expressions [bugprone-branch-clone]992 return b ? 42 : 42;993}994 995int ternary3(bool b, int x) {996 return b ? 42 : 43;997}998 999int ternary4(bool b, int x) {1000 return b ? true ? 45 : 44 : false ? 45 : 44;1001}1002 1003// We do not detect chains of conditional operators.1004int ternary5(bool b1, bool b2, int x) {1005 return b1 ? 42 : b2 ? 43 : 42;1006}1007 1008#define SWITCH_WITH_LBRACE(b) switch (b) {1009#define SEMICOLON_CASE_COLON(b) \1010 ; \1011 case b:1012int d, e;1013void dontCrash() {1014 SWITCH_WITH_LBRACE(d)1015// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]1016 SEMICOLON_CASE_COLON(1)1017 e++;1018 e++;1019 SEMICOLON_CASE_COLON(2)1020 e++;1021 e++;1022 // CHECK-MESSAGES: :[[@LINE-11]]:3: note: expanded from macro 'SEMICOLON_CASE_COLON'1023 // CHECK-MESSAGES: :[[@LINE+1]]:23: note: last of these clones ends here1024 SEMICOLON_CASE_COLON(3);1025 }1026}1027 1028namespace PR62693 {1029 class Object {1030 public:1031 template <typename T>1032 bool ConvertableTo() const;1033 1034 template <typename T>1035 void Handle();1036 };1037 1038 template <typename T>1039 void update(Object &a) {1040 if (a.ConvertableTo<char *>()) {1041 a.Handle<char *>();1042 } else {1043 a.Handle<T>();1044 }1045 }1046 1047 template <typename T>1048 void update2(Object &a) {1049 if (a.ConvertableTo<char *>()) {1050 a.Handle<char *>();1051 } else {1052 a.Handle<T>();1053 }1054 }1055 1056 void foo(Object &a) {1057 update<int>(a);1058 update2<char *>(a);1059 }1060 1061 template <typename T>1062 int branch_clone_in_template(T t) {1063 // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: if with identical then and else branches [bugprone-branch-clone]1064 // CHECK-MESSAGES: :[[@LINE+3]]:7: note: else branch starts here1065 if (t) {1066 return 42;1067 } else {1068 return 42;1069 }1070 }1071}1072