xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/branch-clone.cpp (revision 42c83e32706e2284acb880468295701743d437c6)
189a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-branch-clone %t -- -- -fno-delayed-template-parsing
289a1d03eSRichard 
test_basic1(int in,int & out)389a1d03eSRichard void test_basic1(int in, int &out) {
489a1d03eSRichard   if (in > 77)
589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
689a1d03eSRichard     out++;
789a1d03eSRichard   else
889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
989a1d03eSRichard     out++;
1089a1d03eSRichard 
1189a1d03eSRichard   out++;
1289a1d03eSRichard }
1389a1d03eSRichard 
test_basic2(int in,int & out)1489a1d03eSRichard void test_basic2(int in, int &out) {
1589a1d03eSRichard   if (in > 77) {
1689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
1789a1d03eSRichard     out++;
1889a1d03eSRichard   }
1989a1d03eSRichard   else {
2089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
2189a1d03eSRichard     out++;
2289a1d03eSRichard   }
2389a1d03eSRichard 
2489a1d03eSRichard   out++;
2589a1d03eSRichard }
2689a1d03eSRichard 
test_basic3(int in,int & out)2789a1d03eSRichard void test_basic3(int in, int &out) {
2889a1d03eSRichard   if (in > 77) {
2989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
3089a1d03eSRichard     out++;
3189a1d03eSRichard   }
3289a1d03eSRichard   else
3389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
3489a1d03eSRichard     out++;
3589a1d03eSRichard 
3689a1d03eSRichard   out++;
3789a1d03eSRichard }
3889a1d03eSRichard 
test_basic4(int in,int & out)3989a1d03eSRichard void test_basic4(int in, int &out) {
4089a1d03eSRichard   if (in > 77) {
4189a1d03eSRichard     out--;
4289a1d03eSRichard   }
4389a1d03eSRichard   else {
4489a1d03eSRichard     out++;
4589a1d03eSRichard   }
4689a1d03eSRichard }
4789a1d03eSRichard 
test_basic5(int in,int & out)4889a1d03eSRichard void test_basic5(int in, int &out) {
4989a1d03eSRichard   if (in > 77) {
5089a1d03eSRichard     out++;
5189a1d03eSRichard   }
5289a1d03eSRichard   else {
5389a1d03eSRichard     out++;
5489a1d03eSRichard     out++;
5589a1d03eSRichard   }
5689a1d03eSRichard }
5789a1d03eSRichard 
test_basic6(int in,int & out)5889a1d03eSRichard void test_basic6(int in, int &out) {
5989a1d03eSRichard   if (in > 77) {
6089a1d03eSRichard     out++;
6189a1d03eSRichard   }
6289a1d03eSRichard   else {
6389a1d03eSRichard     out++, out++;
6489a1d03eSRichard   }
6589a1d03eSRichard }
6689a1d03eSRichard 
test_basic7(int in,int & out)6789a1d03eSRichard void test_basic7(int in, int &out) {
6889a1d03eSRichard   if (in > 77) {
6989a1d03eSRichard     out++;
7089a1d03eSRichard     out++;
7189a1d03eSRichard   }
7289a1d03eSRichard   else
7389a1d03eSRichard     out++;
7489a1d03eSRichard 
7589a1d03eSRichard   out++;
7689a1d03eSRichard }
7789a1d03eSRichard 
test_basic8(int in,int & out)7889a1d03eSRichard void test_basic8(int in, int &out) {
7989a1d03eSRichard   if (in > 77) {
8089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
8189a1d03eSRichard     out++;
8289a1d03eSRichard     out++;
8389a1d03eSRichard   } else {
8489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
8589a1d03eSRichard     out++;
8689a1d03eSRichard     out++;
8789a1d03eSRichard   }
8889a1d03eSRichard 
8989a1d03eSRichard   if (in % 2)
9089a1d03eSRichard     out++;
9189a1d03eSRichard }
9289a1d03eSRichard 
test_basic9(int in,int & out)9389a1d03eSRichard void test_basic9(int in, int &out) {
9489a1d03eSRichard   if (in > 77) {
9589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
9689a1d03eSRichard     if (in % 2)
9789a1d03eSRichard       out++;
9889a1d03eSRichard     else
9989a1d03eSRichard       out--;
10089a1d03eSRichard   } else {
10189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
10289a1d03eSRichard     if (in % 2)
10389a1d03eSRichard       out++;
10489a1d03eSRichard     else
10589a1d03eSRichard       out--;
10689a1d03eSRichard   }
10789a1d03eSRichard }
10889a1d03eSRichard 
10989a1d03eSRichard // If we remove the braces from the previous example, the check recognizes it
11089a1d03eSRichard // as an `else if`.
test_basic10(int in,int & out)11189a1d03eSRichard void test_basic10(int in, int &out) {
11289a1d03eSRichard   if (in > 77)
11389a1d03eSRichard     if (in % 2)
11489a1d03eSRichard       out++;
11589a1d03eSRichard     else
11689a1d03eSRichard       out--;
11789a1d03eSRichard   else
11889a1d03eSRichard     if (in % 2)
11989a1d03eSRichard       out++;
12089a1d03eSRichard     else
12189a1d03eSRichard       out--;
12289a1d03eSRichard 
12389a1d03eSRichard }
12489a1d03eSRichard 
test_basic11(int in,int & out)12589a1d03eSRichard void test_basic11(int in, int &out) {
12689a1d03eSRichard   if (in > 77) {
12789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
12889a1d03eSRichard     if (in % 2)
12989a1d03eSRichard       out++;
13089a1d03eSRichard     else
13189a1d03eSRichard       out--;
13289a1d03eSRichard     if (in % 3)
13389a1d03eSRichard       out++;
13489a1d03eSRichard     else
13589a1d03eSRichard       out--;
13689a1d03eSRichard   } else {
13789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
13889a1d03eSRichard     if (in % 2)
13989a1d03eSRichard       out++;
14089a1d03eSRichard     else
14189a1d03eSRichard       out--;
14289a1d03eSRichard     if (in % 3)
14389a1d03eSRichard       out++;
14489a1d03eSRichard     else
14589a1d03eSRichard       out--;
14689a1d03eSRichard   }
14789a1d03eSRichard }
14889a1d03eSRichard 
test_basic12(int in,int & out)14989a1d03eSRichard void test_basic12(int in, int &out) {
15089a1d03eSRichard   if (in > 77) {
15189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
15289a1d03eSRichard   } else {
15389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
15489a1d03eSRichard   }
15589a1d03eSRichard }
15689a1d03eSRichard 
test_basic13(int in,int & out)15789a1d03eSRichard void test_basic13(int in, int &out) {
15889a1d03eSRichard   if (in > 77) {
15989a1d03eSRichard     // Empty compound statement is not identical to null statement.
16089a1d03eSRichard   } else;
16189a1d03eSRichard }
16289a1d03eSRichard 
16389a1d03eSRichard // We use a comparison that ignores redundant parentheses:
test_basic14(int in,int & out)16489a1d03eSRichard void test_basic14(int in, int &out) {
16589a1d03eSRichard   if (in > 77)
16689a1d03eSRichard     out += 2;
16789a1d03eSRichard   else
16889a1d03eSRichard     (out) += (2);
16989a1d03eSRichard }
17089a1d03eSRichard 
test_basic15(int in,int & out)17189a1d03eSRichard void test_basic15(int in, int &out) {
17289a1d03eSRichard   if (in > 77)
17389a1d03eSRichard     ((out += 2));
17489a1d03eSRichard   else
17589a1d03eSRichard     out += 2;
17689a1d03eSRichard }
17789a1d03eSRichard 
17889a1d03eSRichard // ..but does not apply additional simplifications:
test_basic16(int in,int & out)17989a1d03eSRichard void test_basic16(int in, int &out) {
18089a1d03eSRichard   if (in > 77)
18189a1d03eSRichard     out += 2;
18289a1d03eSRichard   else
18389a1d03eSRichard     out += 1 + 1;
18489a1d03eSRichard }
18589a1d03eSRichard 
18689a1d03eSRichard // ..and does not forget important parentheses:
test_basic17(int a,int b,int c,int mode)18789a1d03eSRichard int test_basic17(int a, int b, int c, int mode) {
18889a1d03eSRichard   if (mode>8)
18989a1d03eSRichard     return (a + b) * c;
19089a1d03eSRichard   else
19189a1d03eSRichard     return a + b * c;
19289a1d03eSRichard }
19389a1d03eSRichard 
19489a1d03eSRichard //=========--------------------==========//
19589a1d03eSRichard 
19689a1d03eSRichard #define PASTE_CODE(x) x
19789a1d03eSRichard 
test_macro1(int in,int & out)19889a1d03eSRichard void test_macro1(int in, int &out) {
19989a1d03eSRichard   PASTE_CODE(
20089a1d03eSRichard     if (in > 77)
20189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]
20289a1d03eSRichard       out++;
20389a1d03eSRichard     else
20489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
20589a1d03eSRichard       out++;
20689a1d03eSRichard   )
20789a1d03eSRichard 
20889a1d03eSRichard   out--;
20989a1d03eSRichard }
21089a1d03eSRichard 
test_macro2(int in,int & out)21189a1d03eSRichard void test_macro2(int in, int &out) {
21289a1d03eSRichard   PASTE_CODE(
21389a1d03eSRichard     if (in > 77)
21489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]
21589a1d03eSRichard       out++;
21689a1d03eSRichard   )
21789a1d03eSRichard   else
21889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
21989a1d03eSRichard     out++;
22089a1d03eSRichard }
22189a1d03eSRichard 
test_macro3(int in,int & out)22289a1d03eSRichard void test_macro3(int in, int &out) {
22389a1d03eSRichard   if (in > 77)
22489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
22589a1d03eSRichard     out++;
22689a1d03eSRichard   PASTE_CODE(
22789a1d03eSRichard     else
22889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
22989a1d03eSRichard       out++;
23089a1d03eSRichard   )
23189a1d03eSRichard }
23289a1d03eSRichard 
test_macro4(int in,int & out)23389a1d03eSRichard void test_macro4(int in, int &out) {
23489a1d03eSRichard   if (in > 77)
23589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
23689a1d03eSRichard     out++;
23789a1d03eSRichard   else
23889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
23989a1d03eSRichard     PASTE_CODE(
24089a1d03eSRichard       out++;
24189a1d03eSRichard     )
24289a1d03eSRichard }
24389a1d03eSRichard 
test_macro5(int in,int & out)24489a1d03eSRichard void test_macro5(int in, int &out) {
24589a1d03eSRichard   PASTE_CODE(if) (in > 77)
24689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: if with identical then and else branches [bugprone-branch-clone]
24789a1d03eSRichard     out++;
24889a1d03eSRichard   PASTE_CODE(else)
24989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: note: else branch starts here
25089a1d03eSRichard     out++;
25189a1d03eSRichard }
25289a1d03eSRichard 
25389a1d03eSRichard #define OTHERWISE_INCREASE else out++
25489a1d03eSRichard 
test_macro6(int in,int & out)25589a1d03eSRichard void test_macro6(int in, int &out) {
25689a1d03eSRichard   if (in > 77)
25789a1d03eSRichard       out++;
25889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
25989a1d03eSRichard   OTHERWISE_INCREASE;
26089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
26189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-8]]:28: note: expanded from macro 'OTHERWISE_INCREASE'
26289a1d03eSRichard }
26389a1d03eSRichard 
26489a1d03eSRichard #define COND_INCR(a, b, c) \
26589a1d03eSRichard   do {                     \
26689a1d03eSRichard     if ((a))               \
26789a1d03eSRichard       (b)++;               \
26889a1d03eSRichard     else                   \
26989a1d03eSRichard       (c)++;               \
27089a1d03eSRichard   } while (0)
27189a1d03eSRichard 
test_macro7(int in,int & out1,int & out2)27289a1d03eSRichard void test_macro7(int in, int &out1, int &out2) {
27389a1d03eSRichard   COND_INCR(in, out1, out1);
27489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
27589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR'
27689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here
27789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR'
27889a1d03eSRichard }
27989a1d03eSRichard 
test_macro8(int in,int & out1,int & out2)28089a1d03eSRichard void test_macro8(int in, int &out1, int &out2) {
28189a1d03eSRichard   COND_INCR(in, out1, out2);
28289a1d03eSRichard }
28389a1d03eSRichard 
test_macro9(int in,int & out1,int & out2)28489a1d03eSRichard void test_macro9(int in, int &out1, int &out2) {
28589a1d03eSRichard   COND_INCR(in, out2, out2);
28689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
28789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR'
28889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here
28989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR'
29089a1d03eSRichard }
29189a1d03eSRichard 
29289a1d03eSRichard #define CONCAT(a, b) a##b
29389a1d03eSRichard 
test_macro10(int in,int & out)29489a1d03eSRichard void test_macro10(int in, int &out) {
29589a1d03eSRichard   CONCAT(i, f) (in > 77)
29689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
29789a1d03eSRichard     out++;
29889a1d03eSRichard   CONCAT(el, se)
29989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
30089a1d03eSRichard     out++;
30189a1d03eSRichard }
30289a1d03eSRichard 
30389a1d03eSRichard #define PROBLEM (-1)
30489a1d03eSRichard 
test_macro11(int count)30589a1d03eSRichard int test_macro11(int count) {
30689a1d03eSRichard   if (!count)
30789a1d03eSRichard     return PROBLEM;
30889a1d03eSRichard   else if (count == 13)
30989a1d03eSRichard     return -1;
31089a1d03eSRichard   else
31189a1d03eSRichard     return count * 2;
31289a1d03eSRichard }
31389a1d03eSRichard 
31489a1d03eSRichard #define IF if (
31589a1d03eSRichard #define THEN ) {
31689a1d03eSRichard #define ELSE } else {
31789a1d03eSRichard #define END }
31889a1d03eSRichard 
test_macro12(int in,int & out)31989a1d03eSRichard void test_macro12(int in, int &out) {
32089a1d03eSRichard   IF in > 77 THEN
32189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
32289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-8]]:12: note: expanded from macro 'IF'
32389a1d03eSRichard     out++;
32489a1d03eSRichard     out++;
32589a1d03eSRichard   ELSE
32689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
32789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-11]]:16: note: expanded from macro 'ELSE'
32889a1d03eSRichard     out++;
32989a1d03eSRichard     out++;
33089a1d03eSRichard   END
33189a1d03eSRichard }
33289a1d03eSRichard 
33389a1d03eSRichard // A hack for implementing a switch with no fallthrough:
33489a1d03eSRichard #define SWITCH(x) switch (x) {
33589a1d03eSRichard #define CASE(x) break; case (x):
33689a1d03eSRichard #define DEFAULT break; default:
33789a1d03eSRichard 
test_macro13(int in,int & out)33889a1d03eSRichard void test_macro13(int in, int &out) {
33989a1d03eSRichard   SWITCH(in)
34089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
34189a1d03eSRichard     CASE(1)
34289a1d03eSRichard       out++;
34389a1d03eSRichard       out++;
34489a1d03eSRichard     CASE(2)
34589a1d03eSRichard       out++;
34689a1d03eSRichard       out++;
34789a1d03eSRichard     CASE(3)
34889a1d03eSRichard       out++;
34989a1d03eSRichard       out++;
35089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-15]]:24: note: expanded from macro 'CASE'
35189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:9: note: last of these clones ends here
35289a1d03eSRichard     CASE(4)
35389a1d03eSRichard       out++;
35489a1d03eSRichard     CASE(5)
35589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
35689a1d03eSRichard     CASE(6)
35789a1d03eSRichard       out--;
35889a1d03eSRichard     CASE(7)
35989a1d03eSRichard       out--;
36089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-25]]:24: note: expanded from macro 'CASE'
36189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:9: note: last of these clones ends here
36289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
36389a1d03eSRichard     CASE(8)
36489a1d03eSRichard       out++;
36589a1d03eSRichard       out++;
36689a1d03eSRichard     CASE(9)
36789a1d03eSRichard       out++;
36889a1d03eSRichard       out++;
36989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-34]]:24: note: expanded from macro 'CASE'
37089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:12: note: last of these clones ends here
37189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
37289a1d03eSRichard     DEFAULT
37389a1d03eSRichard       out--;
37489a1d03eSRichard       out--;
37589a1d03eSRichard     CASE(10)
37689a1d03eSRichard       out--;
37789a1d03eSRichard       out--;
37889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-42]]:24: note: expanded from macro 'DEFAULT'
37989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:9: note: last of these clones ends here
38089a1d03eSRichard     CASE(12)
38189a1d03eSRichard       out++;
38289a1d03eSRichard     CASE(13)
38389a1d03eSRichard       out++;
38489a1d03eSRichard   END
38589a1d03eSRichard }
38689a1d03eSRichard 
38789a1d03eSRichard //=========--------------------==========//
38889a1d03eSRichard 
test_chain1(int in,int & out)38989a1d03eSRichard void test_chain1(int in, int &out) {
39089a1d03eSRichard   if (in > 77)
3912b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
39289a1d03eSRichard     out++;
39389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
39489a1d03eSRichard   else if (in > 55)
39589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
39689a1d03eSRichard     out++;
39789a1d03eSRichard 
39889a1d03eSRichard   out++;
39989a1d03eSRichard }
40089a1d03eSRichard 
test_chain2(int in,int & out)40189a1d03eSRichard void test_chain2(int in, int &out) {
40289a1d03eSRichard   if (in > 77)
4032b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
40489a1d03eSRichard     out++;
40589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
40689a1d03eSRichard   else if (in > 55)
40789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
40889a1d03eSRichard     out++;
40989a1d03eSRichard   else if (in > 42)
41089a1d03eSRichard     out--;
41189a1d03eSRichard   else if (in > 28)
41289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here
41389a1d03eSRichard     out++;
41489a1d03eSRichard   else if (in > 12) {
41589a1d03eSRichard     out++;
41689a1d03eSRichard     out *= 7;
41789a1d03eSRichard   } else if (in > 7) {
41889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:22: note: clone 3 starts here
41989a1d03eSRichard     out++;
42089a1d03eSRichard   }
42189a1d03eSRichard }
42289a1d03eSRichard 
test_chain3(int in,int & out)42389a1d03eSRichard void test_chain3(int in, int &out) {
42489a1d03eSRichard   if (in > 77) {
4252b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
42689a1d03eSRichard     out++;
42789a1d03eSRichard     out++;
42889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original
42989a1d03eSRichard   } else if (in > 55) {
43089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here
43189a1d03eSRichard     out++;
43289a1d03eSRichard     out++;
43389a1d03eSRichard   } else if (in > 42)
43489a1d03eSRichard     out--;
43589a1d03eSRichard   else if (in > 28) {
43689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:21: note: clone 2 starts here
43789a1d03eSRichard     out++;
43889a1d03eSRichard     out++;
43989a1d03eSRichard   } else if (in > 12) {
44089a1d03eSRichard     out++;
44189a1d03eSRichard     out++;
44289a1d03eSRichard     out++;
44389a1d03eSRichard     out *= 7;
44489a1d03eSRichard   } else if (in > 7) {
44589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:22: note: clone 3 starts here
44689a1d03eSRichard     out++;
44789a1d03eSRichard     out++;
44889a1d03eSRichard   }
44989a1d03eSRichard }
45089a1d03eSRichard 
45189a1d03eSRichard // In this chain there are two clone families; notice that the checker
45289a1d03eSRichard // describes all branches of the first one before mentioning the second one.
test_chain4(int in,int & out)45389a1d03eSRichard void test_chain4(int in, int &out) {
45489a1d03eSRichard   if (in > 77) {
4552b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
45689a1d03eSRichard     out++;
45789a1d03eSRichard     out++;
45889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original
45989a1d03eSRichard   } else if (in > 55) {
46089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here
46189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+8]]:21: note: clone 2 starts here
46289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+15]]:22: note: clone 3 starts here
46389a1d03eSRichard     out++;
46489a1d03eSRichard     out++;
46589a1d03eSRichard   } else if (in > 42)
4662b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
46789a1d03eSRichard     out--;
46889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
46989a1d03eSRichard   else if (in > 28) {
47089a1d03eSRichard     out++;
47189a1d03eSRichard     out++;
47289a1d03eSRichard   } else if (in > 12) {
47389a1d03eSRichard     out++;
47489a1d03eSRichard     out++;
47589a1d03eSRichard     out++;
47689a1d03eSRichard     out *= 7;
47789a1d03eSRichard   } else if (in > 7) {
47889a1d03eSRichard     out++;
47989a1d03eSRichard     out++;
48089a1d03eSRichard   } else if (in > -3) {
48189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here
48289a1d03eSRichard     out--;
48389a1d03eSRichard   }
48489a1d03eSRichard }
48589a1d03eSRichard 
test_chain5(int in,int & out)48689a1d03eSRichard void test_chain5(int in, int &out) {
48789a1d03eSRichard   if (in > 77)
4882b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
48989a1d03eSRichard     out++;
49089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
49189a1d03eSRichard   else if (in > 55)
49289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
49389a1d03eSRichard     out++;
49489a1d03eSRichard   else if (in > 42)
49589a1d03eSRichard     out--;
49689a1d03eSRichard   else if (in > 28)
49789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here
49889a1d03eSRichard     out++;
49989a1d03eSRichard   else if (in > 12) {
50089a1d03eSRichard     out++;
50189a1d03eSRichard     out *= 7;
50289a1d03eSRichard   } else {
50389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here
50489a1d03eSRichard     out++;
50589a1d03eSRichard   }
50689a1d03eSRichard }
50789a1d03eSRichard 
test_chain6(int in,int & out)50889a1d03eSRichard void test_chain6(int in, int &out) {
50989a1d03eSRichard   if (in > 77) {
5102b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
51189a1d03eSRichard     out++;
51289a1d03eSRichard     out++;
51389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original
51489a1d03eSRichard   } else if (in > 55) {
51589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here
51689a1d03eSRichard     out++;
51789a1d03eSRichard     out++;
51889a1d03eSRichard   } else if (in > 42)
51989a1d03eSRichard     out--;
52089a1d03eSRichard   else if (in > 28) {
52189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:21: note: clone 2 starts here
52289a1d03eSRichard     out++;
52389a1d03eSRichard     out++;
52489a1d03eSRichard   } else if (in > 12) {
52589a1d03eSRichard     out++;
52689a1d03eSRichard     out++;
52789a1d03eSRichard     out++;
52889a1d03eSRichard     out *= 7;
52989a1d03eSRichard   } else {
53089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here
53189a1d03eSRichard     out++;
53289a1d03eSRichard     out++;
53389a1d03eSRichard   }
53489a1d03eSRichard }
53589a1d03eSRichard 
test_nested(int a,int b,int c,int & out)53689a1d03eSRichard void test_nested(int a, int b, int c, int &out) {
53789a1d03eSRichard   if (a > 5) {
53889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
53989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+27]]:5: note: else branch starts here
54089a1d03eSRichard     if (b > 5) {
5412b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
54289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original
54389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here
54489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here
54589a1d03eSRichard       if (c > 5)
54689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]
54789a1d03eSRichard         out++;
54889a1d03eSRichard       else
54989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
55089a1d03eSRichard         out++;
55189a1d03eSRichard     } else if (b > 15) {
55289a1d03eSRichard       if (c > 5)
55389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]
55489a1d03eSRichard         out++;
55589a1d03eSRichard       else
55689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
55789a1d03eSRichard         out++;
55889a1d03eSRichard     } else {
55989a1d03eSRichard       if (c > 5)
56089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]
56189a1d03eSRichard         out++;
56289a1d03eSRichard       else
56389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
56489a1d03eSRichard         out++;
56589a1d03eSRichard     }
56689a1d03eSRichard   } else {
56789a1d03eSRichard     if (b > 5) {
5682b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
56989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original
57089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here
57189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here
57289a1d03eSRichard       if (c > 5)
57389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]
57489a1d03eSRichard         out++;
57589a1d03eSRichard       else
57689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
57789a1d03eSRichard         out++;
57889a1d03eSRichard     } else if (b > 15) {
57989a1d03eSRichard       if (c > 5)
58089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]
58189a1d03eSRichard         out++;
58289a1d03eSRichard       else
58389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
58489a1d03eSRichard         out++;
58589a1d03eSRichard     } else {
58689a1d03eSRichard       if (c > 5)
58789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]
58889a1d03eSRichard         out++;
58989a1d03eSRichard       else
59089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
59189a1d03eSRichard         out++;
59289a1d03eSRichard     }
59389a1d03eSRichard   }
59489a1d03eSRichard }
59589a1d03eSRichard 
59689a1d03eSRichard //=========--------------------==========//
59789a1d03eSRichard 
59889a1d03eSRichard template <class T>
test_template_not_instantiated(const T & t)59989a1d03eSRichard void test_template_not_instantiated(const T &t) {
60089a1d03eSRichard   int a;
60189a1d03eSRichard   if (t)
60289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
60389a1d03eSRichard     a++;
60489a1d03eSRichard   else
60589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
60689a1d03eSRichard     a++;
60789a1d03eSRichard }
60889a1d03eSRichard 
60989a1d03eSRichard template <class T>
test_template_instantiated(const T & t)61089a1d03eSRichard void test_template_instantiated(const T &t) {
61189a1d03eSRichard   int a;
61289a1d03eSRichard   if (t)
61389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
61489a1d03eSRichard     a++;
61589a1d03eSRichard   else
61689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
61789a1d03eSRichard     a++;
61889a1d03eSRichard }
61989a1d03eSRichard 
62089a1d03eSRichard template void test_template_instantiated<int>(const int &t);
62189a1d03eSRichard 
62289a1d03eSRichard template <class T>
test_template2(T t,int a)62389a1d03eSRichard void test_template2(T t, int a) {
62489a1d03eSRichard   if (a) {
62589a1d03eSRichard     T b(0);
62689a1d03eSRichard     a += b;
62789a1d03eSRichard   } else {
62889a1d03eSRichard     int b(0);
62989a1d03eSRichard     a += b;
63089a1d03eSRichard   }
63189a1d03eSRichard }
63289a1d03eSRichard 
63389a1d03eSRichard template void test_template2<int>(int t, int a);
63489a1d03eSRichard 
63589a1d03eSRichard template <class T>
test_template3(T t,int a)63689a1d03eSRichard void test_template3(T t, int a) {
63789a1d03eSRichard   if (a) {
63889a1d03eSRichard     T b(0);
63989a1d03eSRichard     a += b;
64089a1d03eSRichard   } else {
64189a1d03eSRichard     int b(0);
64289a1d03eSRichard     a += b;
64389a1d03eSRichard   }
64489a1d03eSRichard }
64589a1d03eSRichard 
64689a1d03eSRichard template void test_template3<short>(short t, int a);
64789a1d03eSRichard 
64889a1d03eSRichard template <class T>
test_template_two_instances(T t,int & a)64989a1d03eSRichard void test_template_two_instances(T t, int &a) {
65089a1d03eSRichard   if (a) {
65189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
65289a1d03eSRichard     a += int(t);
65389a1d03eSRichard   } else {
65489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
65589a1d03eSRichard     a += int(t);
65689a1d03eSRichard   }
65789a1d03eSRichard }
65889a1d03eSRichard 
65989a1d03eSRichard template void test_template_two_instances<short>(short t, int &a);
66089a1d03eSRichard template void test_template_two_instances<long>(long t, int &a);
66189a1d03eSRichard 
66289a1d03eSRichard class C {
66389a1d03eSRichard   int member;
inline_method(int arg)66489a1d03eSRichard   void inline_method(int arg) {
66589a1d03eSRichard     if (arg)
66689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]
66789a1d03eSRichard       member = 3;
66889a1d03eSRichard     else
66989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
67089a1d03eSRichard       member = 3;
67189a1d03eSRichard   }
67289a1d03eSRichard   int other_method();
67389a1d03eSRichard };
67489a1d03eSRichard 
other_method()67589a1d03eSRichard int C::other_method() {
67689a1d03eSRichard   if (member) {
67789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
67889a1d03eSRichard     return 8;
67989a1d03eSRichard   } else {
68089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
68189a1d03eSRichard     return 8;
68289a1d03eSRichard   }
68389a1d03eSRichard }
68489a1d03eSRichard 
68589a1d03eSRichard //=========--------------------==========//
68689a1d03eSRichard 
simple_switch(char ch)68789a1d03eSRichard int simple_switch(char ch) {
68889a1d03eSRichard   switch (ch) {
68989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
69089a1d03eSRichard   case 'a':
69189a1d03eSRichard     return 10;
69289a1d03eSRichard   case 'A':
69389a1d03eSRichard     return 10;
69489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here
69589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
69689a1d03eSRichard   case 'b':
69789a1d03eSRichard     return 11;
69889a1d03eSRichard   case 'B':
69989a1d03eSRichard     return 11;
70089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here
70189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
70289a1d03eSRichard   case 'c':
70389a1d03eSRichard     return 10;
70489a1d03eSRichard   case 'C':
70589a1d03eSRichard     return 10;
70689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here
70789a1d03eSRichard   default:
70889a1d03eSRichard     return 0;
70989a1d03eSRichard   }
71089a1d03eSRichard }
71189a1d03eSRichard 
long_sequence_switch(char ch)71289a1d03eSRichard int long_sequence_switch(char ch) {
71389a1d03eSRichard   switch (ch) {
71489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 7 consecutive identical branches [bugprone-branch-clone]
71589a1d03eSRichard   case 'a':
71689a1d03eSRichard     return 10;
71789a1d03eSRichard   case 'A':
71889a1d03eSRichard     return 10;
71989a1d03eSRichard   case 'b':
72089a1d03eSRichard     return 10;
72189a1d03eSRichard   case 'B':
72289a1d03eSRichard     return 10;
72389a1d03eSRichard   case 'c':
72489a1d03eSRichard     return 10;
72589a1d03eSRichard   case 'C':
72689a1d03eSRichard     return 10;
72789a1d03eSRichard   default:
72889a1d03eSRichard     return 10;
72989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here
73089a1d03eSRichard   }
73189a1d03eSRichard }
73289a1d03eSRichard 
nested_switch(int a,int b,int c)73389a1d03eSRichard int nested_switch(int a, int b, int c) {
73489a1d03eSRichard   switch (a) {
73589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:3: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
73689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+114]]:6: note: last of these clones ends here
73789a1d03eSRichard   case 1:
73889a1d03eSRichard     switch (b) {
73989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
74089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here
74189a1d03eSRichard     case 1:
74289a1d03eSRichard       switch (c) {
74389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
74489a1d03eSRichard       case 1:
74589a1d03eSRichard         return 42;
74689a1d03eSRichard       case 2:
74789a1d03eSRichard         return 42;
74889a1d03eSRichard       default:
74989a1d03eSRichard         return 42;
75089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
75189a1d03eSRichard       }
75289a1d03eSRichard     case 2:
75389a1d03eSRichard       switch (c) {
75489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
75589a1d03eSRichard       case 1:
75689a1d03eSRichard         return 42;
75789a1d03eSRichard       case 2:
75889a1d03eSRichard         return 42;
75989a1d03eSRichard       default:
76089a1d03eSRichard         return 42;
76189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
76289a1d03eSRichard       }
76389a1d03eSRichard     default:
76489a1d03eSRichard       switch (c) {
76589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
76689a1d03eSRichard       case 1:
76789a1d03eSRichard         return 42;
76889a1d03eSRichard       case 2:
76989a1d03eSRichard         return 42;
77089a1d03eSRichard       default:
77189a1d03eSRichard         return 42;
77289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
77389a1d03eSRichard       }
77489a1d03eSRichard     }
77589a1d03eSRichard   case 2:
77689a1d03eSRichard     switch (b) {
77789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
77889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here
77989a1d03eSRichard     case 1:
78089a1d03eSRichard       switch (c) {
78189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
78289a1d03eSRichard       case 1:
78389a1d03eSRichard         return 42;
78489a1d03eSRichard       case 2:
78589a1d03eSRichard         return 42;
78689a1d03eSRichard       default:
78789a1d03eSRichard         return 42;
78889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
78989a1d03eSRichard       }
79089a1d03eSRichard     case 2:
79189a1d03eSRichard       switch (c) {
79289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
79389a1d03eSRichard       case 1:
79489a1d03eSRichard         return 42;
79589a1d03eSRichard       case 2:
79689a1d03eSRichard         return 42;
79789a1d03eSRichard       default:
79889a1d03eSRichard         return 42;
79989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
80089a1d03eSRichard       }
80189a1d03eSRichard     default:
80289a1d03eSRichard       switch (c) {
80389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
80489a1d03eSRichard       case 1:
80589a1d03eSRichard         return 42;
80689a1d03eSRichard       case 2:
80789a1d03eSRichard         return 42;
80889a1d03eSRichard       default:
80989a1d03eSRichard         return 42;
81089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
81189a1d03eSRichard       }
81289a1d03eSRichard     }
81389a1d03eSRichard   default:
81489a1d03eSRichard     switch (b) {
81589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
81689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+33]]:8: note: last of these clones ends here
81789a1d03eSRichard     case 1:
81889a1d03eSRichard       switch (c) {
81989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
82089a1d03eSRichard       case 1:
82189a1d03eSRichard         return 42;
82289a1d03eSRichard       case 2:
82389a1d03eSRichard         return 42;
82489a1d03eSRichard       default:
82589a1d03eSRichard         return 42;
82689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
82789a1d03eSRichard       }
82889a1d03eSRichard     case 2:
82989a1d03eSRichard       switch (c) {
83089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
83189a1d03eSRichard       case 1:
83289a1d03eSRichard         return 42;
83389a1d03eSRichard       case 2:
83489a1d03eSRichard         return 42;
83589a1d03eSRichard       default:
83689a1d03eSRichard         return 42;
83789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
83889a1d03eSRichard       }
83989a1d03eSRichard     default:
84089a1d03eSRichard       switch (c) {
84189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
84289a1d03eSRichard       case 1:
84389a1d03eSRichard         return 42;
84489a1d03eSRichard       case 2:
84589a1d03eSRichard         return 42;
84689a1d03eSRichard       default:
84789a1d03eSRichard         return 42;
84889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: note: last of these clones ends here
84989a1d03eSRichard       }
85089a1d03eSRichard     }
85189a1d03eSRichard   }
85289a1d03eSRichard }
85389a1d03eSRichard 
85489a1d03eSRichard //=========--------------------==========//
85589a1d03eSRichard 
85689a1d03eSRichard // This should not produce warnings, as in switch statements we only report
85789a1d03eSRichard // identical branches when they are consecutive. Also note that a branch
85889a1d03eSRichard // terminated by a break is different from a branch terminated by the end of
85989a1d03eSRichard // the switch statement.
interleaved_cases(int a,int b)86089a1d03eSRichard int interleaved_cases(int a, int b) {
86189a1d03eSRichard   switch (a) {
86289a1d03eSRichard   case 3:
86389a1d03eSRichard   case 4:
86489a1d03eSRichard     b = 2;
86589a1d03eSRichard     break;
86689a1d03eSRichard   case 5:
86789a1d03eSRichard     b = 3;
86889a1d03eSRichard     break;
86989a1d03eSRichard   case 6:
87089a1d03eSRichard     b = 2;
87189a1d03eSRichard     break;
87289a1d03eSRichard   case 7:
87389a1d03eSRichard     if (b % 2) {
87489a1d03eSRichard       b++;
87589a1d03eSRichard     } else {
87689a1d03eSRichard       b++;
87789a1d03eSRichard       break;
87889a1d03eSRichard     }
87989a1d03eSRichard     b = 2;
88089a1d03eSRichard     break;
88189a1d03eSRichard   case 8:
88289a1d03eSRichard     b = 2;
88389a1d03eSRichard   case 9:
88489a1d03eSRichard     b = 3;
88589a1d03eSRichard     break;
88689a1d03eSRichard   default:
88789a1d03eSRichard     b = 3;
88889a1d03eSRichard   }
88989a1d03eSRichard   return b;
89089a1d03eSRichard }
89189a1d03eSRichard 
89289a1d03eSRichard 
89389a1d03eSRichard // 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
buried_cases(int foo)89489a1d03eSRichard int buried_cases(int foo) {
89589a1d03eSRichard   switch (foo) {
89689a1d03eSRichard     {
89789a1d03eSRichard     case 36:
89889a1d03eSRichard       return 8;
89989a1d03eSRichard     default:
90089a1d03eSRichard       return 8;
90189a1d03eSRichard     }
90289a1d03eSRichard   }
90389a1d03eSRichard }
90489a1d03eSRichard 
90589a1d03eSRichard // Here the `case 7:` is a child statement of the GotoLabelStmt, so the checker
90689a1d03eSRichard // thinks that it is part of the `case 9:` branch. While this result is
90789a1d03eSRichard // counterintuitve, mixing goto labels and switch statements in this fashion is
90889a1d03eSRichard // pretty rare, so it does not deserve a special case in the checker code.
decorated_cases(int z)90989a1d03eSRichard int decorated_cases(int z) {
91089a1d03eSRichard   if (!(z % 777)) {
91189a1d03eSRichard     goto lucky;
91289a1d03eSRichard   }
91389a1d03eSRichard   switch (z) {
91489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
91589a1d03eSRichard   case 1:
91689a1d03eSRichard   case 2:
91789a1d03eSRichard   case 3:
91889a1d03eSRichard     z++;
91989a1d03eSRichard     break;
92089a1d03eSRichard   case 4:
92189a1d03eSRichard   case 5:
92289a1d03eSRichard     z++;
92389a1d03eSRichard     break;
92489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: note: last of these clones ends here
92589a1d03eSRichard   case 9:
92689a1d03eSRichard     z++;
92789a1d03eSRichard     break;
92889a1d03eSRichard   lucky:
92989a1d03eSRichard   case 7:
93089a1d03eSRichard     z += 3;
93189a1d03eSRichard     z *= 2;
93289a1d03eSRichard     break;
93389a1d03eSRichard   case 92:
93489a1d03eSRichard     z += 3;
93589a1d03eSRichard     z *= 2;
93689a1d03eSRichard     break;
93789a1d03eSRichard   default:
93889a1d03eSRichard     z++;
93989a1d03eSRichard   }
94089a1d03eSRichard   return z + 92;
94189a1d03eSRichard }
94289a1d03eSRichard 
94389a1d03eSRichard // The child of the switch statement is not necessarily a compound statement,
94489a1d03eSRichard // do not crash in this unusual case.
no_real_body(int in,int & out)94589a1d03eSRichard char no_real_body(int in, int &out) {
94689a1d03eSRichard   switch (in)
94789a1d03eSRichard   case 42:
94889a1d03eSRichard     return 'A';
94989a1d03eSRichard 
95089a1d03eSRichard   if (in > 77)
9512b51c8cdSDonát Nagy // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
95289a1d03eSRichard     out++;
95389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
95489a1d03eSRichard   else if (in > 55)
95589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
95689a1d03eSRichard     out++;
95789a1d03eSRichard   else if (in > 34)
95889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here
95989a1d03eSRichard     out++;
96089a1d03eSRichard 
96189a1d03eSRichard   return '|';
96289a1d03eSRichard }
96389a1d03eSRichard 
96489a1d03eSRichard // Duff's device [https://en.wikipedia.org/wiki/Duff's_device]
96589a1d03eSRichard // The check does not try to distinguish branches in this sort of convoluted
96689a1d03eSRichard // code, but it should avoid crashing.
send(short * to,short * from,int count)96789a1d03eSRichard void send(short *to, short *from, int count)
96889a1d03eSRichard {
96989a1d03eSRichard     int n = (count + 7) / 8;
97089a1d03eSRichard     switch (count % 8) {
97189a1d03eSRichard     case 0: do { *to = *from++;
97289a1d03eSRichard     case 7:      *to = *from++;
97389a1d03eSRichard     case 6:      *to = *from++;
97489a1d03eSRichard     case 5:      *to = *from++;
97589a1d03eSRichard     case 4:      *to = *from++;
97689a1d03eSRichard     case 3:      *to = *from++;
97789a1d03eSRichard     case 2:      *to = *from++;
97889a1d03eSRichard     case 1:      *to = *from++;
97989a1d03eSRichard             } while (--n > 0);
98089a1d03eSRichard     }
98189a1d03eSRichard }
98289a1d03eSRichard 
98389a1d03eSRichard //=========--------------------==========//
98489a1d03eSRichard 
ternary1(bool b,int & x)98589a1d03eSRichard void ternary1(bool b, int &x) {
98689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:6: warning: conditional operator with identical true and false expressions [bugprone-branch-clone]
98789a1d03eSRichard   (b ? x : x) = 42;
98889a1d03eSRichard }
98989a1d03eSRichard 
ternary2(bool b,int x)99089a1d03eSRichard int ternary2(bool b, int x) {
99189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:12: warning: conditional operator with identical true and false expressions [bugprone-branch-clone]
99289a1d03eSRichard   return b ? 42 : 42;
99389a1d03eSRichard }
99489a1d03eSRichard 
ternary3(bool b,int x)99589a1d03eSRichard int ternary3(bool b, int x) {
99689a1d03eSRichard   return b ? 42 : 43;
99789a1d03eSRichard }
99889a1d03eSRichard 
ternary4(bool b,int x)99989a1d03eSRichard int ternary4(bool b, int x) {
100089a1d03eSRichard   return b ? true ? 45 : 44 : false ? 45 : 44;
100189a1d03eSRichard }
100289a1d03eSRichard 
100389a1d03eSRichard // We do not detect chains of conditional operators.
ternary5(bool b1,bool b2,int x)100489a1d03eSRichard int ternary5(bool b1, bool b2, int x) {
100589a1d03eSRichard   return b1 ? 42 : b2 ? 43 : 42;
100689a1d03eSRichard }
100789a1d03eSRichard 
100889a1d03eSRichard #define SWITCH_WITH_LBRACE(b) switch (b) {
100989a1d03eSRichard #define SEMICOLON_CASE_COLON(b)                                                \
101089a1d03eSRichard   ;                                                                            \
101189a1d03eSRichard   case b:
101289a1d03eSRichard int d, e;
dontCrash()101389a1d03eSRichard void dontCrash() {
101489a1d03eSRichard   SWITCH_WITH_LBRACE(d)
101589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
101689a1d03eSRichard   SEMICOLON_CASE_COLON(1)
101789a1d03eSRichard     e++;
101889a1d03eSRichard     e++;
101989a1d03eSRichard   SEMICOLON_CASE_COLON(2)
102089a1d03eSRichard     e++;
102189a1d03eSRichard     e++;
102289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-11]]:3: note: expanded from macro 'SEMICOLON_CASE_COLON'
102389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE+1]]:23: note: last of these clones ends here
102489a1d03eSRichard   SEMICOLON_CASE_COLON(3);
102589a1d03eSRichard   }
102689a1d03eSRichard }
1027*42c83e32SPiotr Zegar 
1028*42c83e32SPiotr Zegar namespace PR62693 {
1029*42c83e32SPiotr Zegar   class Object {
1030*42c83e32SPiotr Zegar     public:
1031*42c83e32SPiotr Zegar       template <typename T>
1032*42c83e32SPiotr Zegar         bool ConvertableTo() const;
1033*42c83e32SPiotr Zegar 
1034*42c83e32SPiotr Zegar       template <typename T>
1035*42c83e32SPiotr Zegar         void Handle();
1036*42c83e32SPiotr Zegar   };
1037*42c83e32SPiotr Zegar 
1038*42c83e32SPiotr Zegar   template <typename T>
1039*42c83e32SPiotr Zegar   void update(Object &a) {
1040*42c83e32SPiotr Zegar     if (a.ConvertableTo<char *>()) {
1041*42c83e32SPiotr Zegar       a.Handle<char *>();
1042*42c83e32SPiotr Zegar     } else {
1043*42c83e32SPiotr Zegar       a.Handle<T>();
1044*42c83e32SPiotr Zegar     }
1045*42c83e32SPiotr Zegar   }
1046*42c83e32SPiotr Zegar 
1047*42c83e32SPiotr Zegar   template <typename T>
1048*42c83e32SPiotr Zegar   void update2(Object &a) {
1049*42c83e32SPiotr Zegar     if (a.ConvertableTo<char *>()) {
1050*42c83e32SPiotr Zegar       a.Handle<char *>();
1051*42c83e32SPiotr Zegar     } else {
1052*42c83e32SPiotr Zegar       a.Handle<T>();
1053*42c83e32SPiotr Zegar     }
1054*42c83e32SPiotr Zegar   }
1055*42c83e32SPiotr Zegar 
1056*42c83e32SPiotr Zegar   void foo(Object &a) {
1057*42c83e32SPiotr Zegar     update<int>(a);
1058*42c83e32SPiotr Zegar     update2<char *>(a);
1059*42c83e32SPiotr Zegar   }
1060*42c83e32SPiotr Zegar 
1061*42c83e32SPiotr Zegar   template <typename T>
1062*42c83e32SPiotr Zegar   int branch_clone_in_template(T t) {
1063*42c83e32SPiotr Zegar     // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: if with identical then and else branches [bugprone-branch-clone]
1064*42c83e32SPiotr Zegar     // CHECK-MESSAGES: :[[@LINE+3]]:7: note: else branch starts here
1065*42c83e32SPiotr Zegar     if (t) {
1066*42c83e32SPiotr Zegar       return 42;
1067*42c83e32SPiotr Zegar     } else {
1068*42c83e32SPiotr Zegar       return 42;
1069*42c83e32SPiotr Zegar     }
1070*42c83e32SPiotr Zegar   }
1071*42c83e32SPiotr Zegar }
1072