| // RUN: %check_clang_tidy %s bugprone-branch-clone %t -- -- -fno-delayed-template-parsing |
| |
| void test_basic1(int in, int &out) { |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| out++; |
| |
| out++; |
| } |
| |
| void test_basic2(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| } |
| else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| out++; |
| } |
| |
| out++; |
| } |
| |
| void test_basic3(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| } |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| out++; |
| |
| out++; |
| } |
| |
| void test_basic4(int in, int &out) { |
| if (in > 77) { |
| out--; |
| } |
| else { |
| out++; |
| } |
| } |
| |
| void test_basic5(int in, int &out) { |
| if (in > 77) { |
| out++; |
| } |
| else { |
| out++; |
| out++; |
| } |
| } |
| |
| void test_basic6(int in, int &out) { |
| if (in > 77) { |
| out++; |
| } |
| else { |
| out++, out++; |
| } |
| } |
| |
| void test_basic7(int in, int &out) { |
| if (in > 77) { |
| out++; |
| out++; |
| } |
| else |
| out++; |
| |
| out++; |
| } |
| |
| void test_basic8(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| out++; |
| } else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| out++; |
| out++; |
| } |
| |
| if (in % 2) |
| out++; |
| } |
| |
| void test_basic9(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| if (in % 2) |
| out++; |
| else |
| out--; |
| } else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| if (in % 2) |
| out++; |
| else |
| out--; |
| } |
| } |
| |
| // If we remove the braces from the previous example, the check recognizes it |
| // as an `else if`. |
| void test_basic10(int in, int &out) { |
| if (in > 77) |
| if (in % 2) |
| out++; |
| else |
| out--; |
| else |
| if (in % 2) |
| out++; |
| else |
| out--; |
| |
| } |
| |
| void test_basic11(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| if (in % 2) |
| out++; |
| else |
| out--; |
| if (in % 3) |
| out++; |
| else |
| out--; |
| } else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| if (in % 2) |
| out++; |
| else |
| out--; |
| if (in % 3) |
| out++; |
| else |
| out--; |
| } |
| } |
| |
| void test_basic12(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| } else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| } |
| } |
| |
| void test_basic13(int in, int &out) { |
| if (in > 77) { |
| // Empty compound statement is not identical to null statement. |
| } else; |
| } |
| |
| // We use a comparison that ignores redundant parentheses: |
| void test_basic14(int in, int &out) { |
| if (in > 77) |
| out += 2; |
| else |
| (out) += (2); |
| } |
| |
| void test_basic15(int in, int &out) { |
| if (in > 77) |
| ((out += 2)); |
| else |
| out += 2; |
| } |
| |
| // ..but does not apply additional simplifications: |
| void test_basic16(int in, int &out) { |
| if (in > 77) |
| out += 2; |
| else |
| out += 1 + 1; |
| } |
| |
| // ..and does not forget important parentheses: |
| int test_basic17(int a, int b, int c, int mode) { |
| if (mode>8) |
| return (a + b) * c; |
| else |
| return a + b * c; |
| } |
| |
| //=========--------------------==========// |
| |
| #define PASTE_CODE(x) x |
| |
| void test_macro1(int in, int &out) { |
| PASTE_CODE( |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| out++; |
| ) |
| |
| out--; |
| } |
| |
| void test_macro2(int in, int &out) { |
| PASTE_CODE( |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| ) |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| out++; |
| } |
| |
| void test_macro3(int in, int &out) { |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| PASTE_CODE( |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| out++; |
| ) |
| } |
| |
| void test_macro4(int in, int &out) { |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| PASTE_CODE( |
| out++; |
| ) |
| } |
| |
| void test_macro5(int in, int &out) { |
| PASTE_CODE(if) (in > 77) |
| // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| PASTE_CODE(else) |
| // CHECK-MESSAGES: :[[@LINE-1]]:14: note: else branch starts here |
| out++; |
| } |
| |
| #define OTHERWISE_INCREASE else out++ |
| |
| void test_macro6(int in, int &out) { |
| if (in > 77) |
| out++; |
| // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| OTHERWISE_INCREASE; |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| // CHECK-MESSAGES: :[[@LINE-8]]:28: note: expanded from macro 'OTHERWISE_INCREASE' |
| } |
| |
| #define COND_INCR(a, b, c) \ |
| do { \ |
| if ((a)) \ |
| (b)++; \ |
| else \ |
| (c)++; \ |
| } while (0) |
| |
| void test_macro7(int in, int &out1, int &out2) { |
| COND_INCR(in, out1, out1); |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR' |
| // CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here |
| // CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR' |
| } |
| |
| void test_macro8(int in, int &out1, int &out2) { |
| COND_INCR(in, out1, out2); |
| } |
| |
| void test_macro9(int in, int &out1, int &out2) { |
| COND_INCR(in, out2, out2); |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR' |
| // CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here |
| // CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR' |
| } |
| |
| #define CONCAT(a, b) a##b |
| |
| void test_macro10(int in, int &out) { |
| CONCAT(i, f) (in > 77) |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| CONCAT(el, se) |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| out++; |
| } |
| |
| #define PROBLEM (-1) |
| |
| int test_macro11(int count) { |
| if (!count) |
| return PROBLEM; |
| else if (count == 13) |
| return -1; |
| else |
| return count * 2; |
| } |
| |
| #define IF if ( |
| #define THEN ) { |
| #define ELSE } else { |
| #define END } |
| |
| void test_macro12(int in, int &out) { |
| IF in > 77 THEN |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE-8]]:12: note: expanded from macro 'IF' |
| out++; |
| out++; |
| ELSE |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| // CHECK-MESSAGES: :[[@LINE-11]]:16: note: expanded from macro 'ELSE' |
| out++; |
| out++; |
| END |
| } |
| |
| // A hack for implementing a switch with no fallthrough: |
| #define SWITCH(x) switch (x) { |
| #define CASE(x) break; case (x): |
| #define DEFAULT break; default: |
| |
| void test_macro13(int in, int &out) { |
| SWITCH(in) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| CASE(1) |
| out++; |
| out++; |
| CASE(2) |
| out++; |
| out++; |
| CASE(3) |
| out++; |
| out++; |
| // CHECK-MESSAGES: :[[@LINE-15]]:24: note: expanded from macro 'CASE' |
| // CHECK-MESSAGES: :[[@LINE+1]]:9: note: last of these clones ends here |
| CASE(4) |
| out++; |
| CASE(5) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] |
| CASE(6) |
| out--; |
| CASE(7) |
| out--; |
| // CHECK-MESSAGES: :[[@LINE-25]]:24: note: expanded from macro 'CASE' |
| // CHECK-MESSAGES: :[[@LINE+2]]:9: note: last of these clones ends here |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] |
| CASE(8) |
| out++; |
| out++; |
| CASE(9) |
| out++; |
| out++; |
| // CHECK-MESSAGES: :[[@LINE-34]]:24: note: expanded from macro 'CASE' |
| // CHECK-MESSAGES: :[[@LINE+2]]:12: note: last of these clones ends here |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] |
| DEFAULT |
| out--; |
| out--; |
| CASE(10) |
| out--; |
| out--; |
| // CHECK-MESSAGES: :[[@LINE-42]]:24: note: expanded from macro 'DEFAULT' |
| // CHECK-MESSAGES: :[[@LINE+1]]:9: note: last of these clones ends here |
| CASE(12) |
| out++; |
| CASE(13) |
| out++; |
| END |
| } |
| |
| //=========--------------------==========// |
| |
| void test_chain1(int in, int &out) { |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| out++; |
| // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original |
| else if (in > 55) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here |
| out++; |
| |
| out++; |
| } |
| |
| void test_chain2(int in, int &out) { |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| out++; |
| // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original |
| else if (in > 55) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here |
| out++; |
| else if (in > 42) |
| out--; |
| else if (in > 28) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here |
| out++; |
| else if (in > 12) { |
| out++; |
| out *= 7; |
| } else if (in > 7) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:22: note: clone 3 starts here |
| out++; |
| } |
| } |
| |
| void test_chain3(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| out++; |
| out++; |
| // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original |
| } else if (in > 55) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here |
| out++; |
| out++; |
| } else if (in > 42) |
| out--; |
| else if (in > 28) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:21: note: clone 2 starts here |
| out++; |
| out++; |
| } else if (in > 12) { |
| out++; |
| out++; |
| out++; |
| out *= 7; |
| } else if (in > 7) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:22: note: clone 3 starts here |
| out++; |
| out++; |
| } |
| } |
| |
| // In this chain there are two clone families; notice that the checker |
| // describes all branches of the first one before mentioning the second one. |
| void test_chain4(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| out++; |
| out++; |
| // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original |
| } else if (in > 55) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here |
| // CHECK-MESSAGES: :[[@LINE+8]]:21: note: clone 2 starts here |
| // CHECK-MESSAGES: :[[@LINE+15]]:22: note: clone 3 starts here |
| out++; |
| out++; |
| } else if (in > 42) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| out--; |
| // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original |
| else if (in > 28) { |
| out++; |
| out++; |
| } else if (in > 12) { |
| out++; |
| out++; |
| out++; |
| out *= 7; |
| } else if (in > 7) { |
| out++; |
| out++; |
| } else if (in > -3) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here |
| out--; |
| } |
| } |
| |
| void test_chain5(int in, int &out) { |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| out++; |
| // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original |
| else if (in > 55) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here |
| out++; |
| else if (in > 42) |
| out--; |
| else if (in > 28) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here |
| out++; |
| else if (in > 12) { |
| out++; |
| out *= 7; |
| } else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here |
| out++; |
| } |
| } |
| |
| void test_chain6(int in, int &out) { |
| if (in > 77) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| out++; |
| out++; |
| // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original |
| } else if (in > 55) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here |
| out++; |
| out++; |
| } else if (in > 42) |
| out--; |
| else if (in > 28) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:21: note: clone 2 starts here |
| out++; |
| out++; |
| } else if (in > 12) { |
| out++; |
| out++; |
| out++; |
| out *= 7; |
| } else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here |
| out++; |
| out++; |
| } |
| } |
| |
| void test_nested(int a, int b, int c, int &out) { |
| if (a > 5) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE+27]]:5: note: else branch starts here |
| if (b > 5) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original |
| // CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here |
| // CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here |
| if (c > 5) |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here |
| out++; |
| } else if (b > 15) { |
| if (c > 5) |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here |
| out++; |
| } else { |
| if (c > 5) |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here |
| out++; |
| } |
| } else { |
| if (b > 5) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original |
| // CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here |
| // CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here |
| if (c > 5) |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here |
| out++; |
| } else if (b > 15) { |
| if (c > 5) |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here |
| out++; |
| } else { |
| if (c > 5) |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone] |
| out++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here |
| out++; |
| } |
| } |
| } |
| |
| //=========--------------------==========// |
| |
| template <class T> |
| void test_template_not_instantiated(const T &t) { |
| int a; |
| if (t) |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| a++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| a++; |
| } |
| |
| template <class T> |
| void test_template_instantiated(const T &t) { |
| int a; |
| if (t) |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| a++; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here |
| a++; |
| } |
| |
| template void test_template_instantiated<int>(const int &t); |
| |
| template <class T> |
| void test_template2(T t, int a) { |
| if (a) { |
| T b(0); |
| a += b; |
| } else { |
| int b(0); |
| a += b; |
| } |
| } |
| |
| template void test_template2<int>(int t, int a); |
| |
| template <class T> |
| void test_template3(T t, int a) { |
| if (a) { |
| T b(0); |
| a += b; |
| } else { |
| int b(0); |
| a += b; |
| } |
| } |
| |
| template void test_template3<short>(short t, int a); |
| |
| template <class T> |
| void test_template_two_instances(T t, int &a) { |
| if (a) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| a += int(t); |
| } else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| a += int(t); |
| } |
| } |
| |
| template void test_template_two_instances<short>(short t, int &a); |
| template void test_template_two_instances<long>(long t, int &a); |
| |
| class C { |
| int member; |
| void inline_method(int arg) { |
| if (arg) |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone] |
| member = 3; |
| else |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| member = 3; |
| } |
| int other_method(); |
| }; |
| |
| int C::other_method() { |
| if (member) { |
| // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone] |
| return 8; |
| } else { |
| // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here |
| return 8; |
| } |
| } |
| |
| //=========--------------------==========// |
| |
| int simple_switch(char ch) { |
| switch (ch) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] |
| case 'a': |
| return 10; |
| case 'A': |
| return 10; |
| // CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here |
| // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] |
| case 'b': |
| return 11; |
| case 'B': |
| return 11; |
| // CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here |
| // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] |
| case 'c': |
| return 10; |
| case 'C': |
| return 10; |
| // CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here |
| default: |
| return 0; |
| } |
| } |
| |
| int long_sequence_switch(char ch) { |
| switch (ch) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 7 consecutive identical branches [bugprone-branch-clone] |
| case 'a': |
| return 10; |
| case 'A': |
| return 10; |
| case 'b': |
| return 10; |
| case 'B': |
| return 10; |
| case 'c': |
| return 10; |
| case 'C': |
| return 10; |
| default: |
| return 10; |
| // CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here |
| } |
| } |
| |
| int nested_switch(int a, int b, int c) { |
| switch (a) { |
| // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE+114]]:6: note: last of these clones ends here |
| case 1: |
| switch (b) { |
| // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here |
| case 1: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| case 2: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| default: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| } |
| case 2: |
| switch (b) { |
| // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here |
| case 1: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| case 2: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| default: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| } |
| default: |
| switch (b) { |
| // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| // CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here |
| case 1: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| case 2: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| default: |
| switch (c) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| return 42; |
| case 2: |
| return 42; |
| default: |
| return 42; |
| // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here |
| } |
| } |
| } |
| } |
| |
| //=========--------------------==========// |
| |
| // This should not produce warnings, as in switch statements we only report |
| // identical branches when they are consecutive. Also note that a branch |
| // terminated by a break is different from a branch terminated by the end of |
| // the switch statement. |
| int interleaved_cases(int a, int b) { |
| switch (a) { |
| case 3: |
| case 4: |
| b = 2; |
| break; |
| case 5: |
| b = 3; |
| break; |
| case 6: |
| b = 2; |
| break; |
| case 7: |
| if (b % 2) { |
| b++; |
| } else { |
| b++; |
| break; |
| } |
| b = 2; |
| break; |
| case 8: |
| b = 2; |
| case 9: |
| b = 3; |
| break; |
| default: |
| b = 3; |
| } |
| return b; |
| } |
| |
| |
| // 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 switch |
| int buried_cases(int foo) { |
| switch (foo) { |
| { |
| case 36: |
| return 8; |
| default: |
| return 8; |
| } |
| } |
| } |
| |
| // Here the `case 7:` is a child statement of the GotoLabelStmt, so the checker |
| // thinks that it is part of the `case 9:` branch. While this result is |
| // counterintuitve, mixing goto labels and switch statements in this fashion is |
| // pretty rare, so it does not deserve a special case in the checker code. |
| int decorated_cases(int z) { |
| if (!(z % 777)) { |
| goto lucky; |
| } |
| switch (z) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] |
| case 1: |
| case 2: |
| case 3: |
| z++; |
| break; |
| case 4: |
| case 5: |
| z++; |
| break; |
| // CHECK-MESSAGES: :[[@LINE-1]]:10: note: last of these clones ends here |
| case 9: |
| z++; |
| break; |
| lucky: |
| case 7: |
| z += 3; |
| z *= 2; |
| break; |
| case 92: |
| z += 3; |
| z *= 2; |
| break; |
| default: |
| z++; |
| } |
| return z + 92; |
| } |
| |
| // The child of the switch statement is not neccessarily a compound statement, |
| // do not crash in this unusual case. |
| char no_real_body(int in, int &out) { |
| switch (in) |
| case 42: |
| return 'A'; |
| |
| if (in > 77) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone] |
| out++; |
| // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original |
| else if (in > 55) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here |
| out++; |
| else if (in > 34) |
| // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here |
| out++; |
| |
| return '|'; |
| } |
| |
| // Duff's device [https://en.wikipedia.org/wiki/Duff's_device] |
| // The check does not try to distinguish branches in this sort of convoluted |
| // code, but it should avoid crashing. |
| void send(short *to, short *from, int count) |
| { |
| int n = (count + 7) / 8; |
| switch (count % 8) { |
| case 0: do { *to = *from++; |
| case 7: *to = *from++; |
| case 6: *to = *from++; |
| case 5: *to = *from++; |
| case 4: *to = *from++; |
| case 3: *to = *from++; |
| case 2: *to = *from++; |
| case 1: *to = *from++; |
| } while (--n > 0); |
| } |
| } |
| |
| //=========--------------------==========// |
| |
| void ternary1(bool b, int &x) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:6: warning: conditional operator with identical true and false expressions [bugprone-branch-clone] |
| (b ? x : x) = 42; |
| } |
| |
| int ternary2(bool b, int x) { |
| // CHECK-MESSAGES: :[[@LINE+1]]:12: warning: conditional operator with identical true and false expressions [bugprone-branch-clone] |
| return b ? 42 : 42; |
| } |
| |
| int ternary3(bool b, int x) { |
| return b ? 42 : 43; |
| } |
| |
| int ternary4(bool b, int x) { |
| return b ? true ? 45 : 44 : false ? 45 : 44; |
| } |
| |
| // We do not detect chains of conditional operators. |
| int ternary5(bool b1, bool b2, int x) { |
| return b1 ? 42 : b2 ? 43 : 42; |
| } |
| |
| #define SWITCH_WITH_LBRACE(b) switch (b) { |
| #define SEMICOLON_CASE_COLON(b) \ |
| ; \ |
| case b: |
| int d, e; |
| void dontCrash() { |
| SWITCH_WITH_LBRACE(d) |
| // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone] |
| SEMICOLON_CASE_COLON(1) |
| e++; |
| e++; |
| SEMICOLON_CASE_COLON(2) |
| e++; |
| e++; |
| // CHECK-MESSAGES: :[[@LINE-11]]:3: note: expanded from macro 'SEMICOLON_CASE_COLON' |
| // CHECK-MESSAGES: :[[@LINE+1]]:23: note: last of these clones ends here |
| SEMICOLON_CASE_COLON(3); |
| } |
| } |