1 // RUN: %check_clang_tidy %s bugprone-branch-clone %t -- -- -fno-delayed-template-parsing
2
test_basic1(int in,int & out)3 void 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 else
8 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
9 out++;
10
11 out++;
12 }
13
test_basic2(int in,int & out)14 void 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 here
21 out++;
22 }
23
24 out++;
25 }
26
test_basic3(int in,int & out)27 void 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 else
33 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
34 out++;
35
36 out++;
37 }
38
test_basic4(int in,int & out)39 void test_basic4(int in, int &out) {
40 if (in > 77) {
41 out--;
42 }
43 else {
44 out++;
45 }
46 }
47
test_basic5(int in,int & out)48 void test_basic5(int in, int &out) {
49 if (in > 77) {
50 out++;
51 }
52 else {
53 out++;
54 out++;
55 }
56 }
57
test_basic6(int in,int & out)58 void test_basic6(int in, int &out) {
59 if (in > 77) {
60 out++;
61 }
62 else {
63 out++, out++;
64 }
65 }
66
test_basic7(int in,int & out)67 void test_basic7(int in, int &out) {
68 if (in > 77) {
69 out++;
70 out++;
71 }
72 else
73 out++;
74
75 out++;
76 }
77
test_basic8(int in,int & out)78 void 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 here
85 out++;
86 out++;
87 }
88
89 if (in % 2)
90 out++;
91 }
92
test_basic9(int in,int & out)93 void 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 else
99 out--;
100 } else {
101 // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
102 if (in % 2)
103 out++;
104 else
105 out--;
106 }
107 }
108
109 // If we remove the braces from the previous example, the check recognizes it
110 // as an `else if`.
test_basic10(int in,int & out)111 void test_basic10(int in, int &out) {
112 if (in > 77)
113 if (in % 2)
114 out++;
115 else
116 out--;
117 else
118 if (in % 2)
119 out++;
120 else
121 out--;
122
123 }
124
test_basic11(int in,int & out)125 void 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 else
131 out--;
132 if (in % 3)
133 out++;
134 else
135 out--;
136 } else {
137 // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
138 if (in % 2)
139 out++;
140 else
141 out--;
142 if (in % 3)
143 out++;
144 else
145 out--;
146 }
147 }
148
test_basic12(int in,int & out)149 void 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 here
154 }
155 }
156
test_basic13(int in,int & out)157 void 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:
test_basic14(int in,int & out)164 void test_basic14(int in, int &out) {
165 if (in > 77)
166 out += 2;
167 else
168 (out) += (2);
169 }
170
test_basic15(int in,int & out)171 void test_basic15(int in, int &out) {
172 if (in > 77)
173 ((out += 2));
174 else
175 out += 2;
176 }
177
178 // ..but does not apply additional simplifications:
test_basic16(int in,int & out)179 void test_basic16(int in, int &out) {
180 if (in > 77)
181 out += 2;
182 else
183 out += 1 + 1;
184 }
185
186 // ..and does not forget important parentheses:
test_basic17(int a,int b,int c,int mode)187 int test_basic17(int a, int b, int c, int mode) {
188 if (mode>8)
189 return (a + b) * c;
190 else
191 return a + b * c;
192 }
193
194 //=========--------------------==========//
195
196 #define PASTE_CODE(x) x
197
test_macro1(int in,int & out)198 void 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 else
204 // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
205 out++;
206 )
207
208 out--;
209 }
210
test_macro2(int in,int & out)211 void 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 else
218 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
219 out++;
220 }
221
test_macro3(int in,int & out)222 void 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 else
228 // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
229 out++;
230 )
231 }
232
test_macro4(int in,int & out)233 void 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 else
238 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
239 PASTE_CODE(
240 out++;
241 )
242 }
243
test_macro5(int in,int & out)244 void 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 here
250 out++;
251 }
252
253 #define OTHERWISE_INCREASE else out++
254
test_macro6(int in,int & out)255 void 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 here
261 // 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
test_macro7(int in,int & out1,int & out2)272 void 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 here
277 // CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR'
278 }
279
test_macro8(int in,int & out1,int & out2)280 void test_macro8(int in, int &out1, int &out2) {
281 COND_INCR(in, out1, out2);
282 }
283
test_macro9(int in,int & out1,int & out2)284 void 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 here
289 // CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR'
290 }
291
292 #define CONCAT(a, b) a##b
293
test_macro10(int in,int & out)294 void 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 here
300 out++;
301 }
302
303 #define PROBLEM (-1)
304
test_macro11(int count)305 int test_macro11(int count) {
306 if (!count)
307 return PROBLEM;
308 else if (count == 13)
309 return -1;
310 else
311 return count * 2;
312 }
313
314 #define IF if (
315 #define THEN ) {
316 #define ELSE } else {
317 #define END }
318
test_macro12(int in,int & out)319 void test_macro12(int in, int &out) {
320 IF in > 77 THEN
321 // 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 ELSE
326 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
327 // CHECK-MESSAGES: :[[@LINE-11]]:16: note: expanded from macro 'ELSE'
328 out++;
329 out++;
330 END
331 }
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
test_macro13(int in,int & out)338 void 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 here
352 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 here
362 // 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 here
371 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
372 DEFAULT
373 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 here
380 CASE(12)
381 out++;
382 CASE(13)
383 out++;
384 END
385 }
386
387 //=========--------------------==========//
388
test_chain1(int in,int & out)389 void test_chain1(int in, int &out) {
390 if (in > 77)
391 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone]
392 out++;
393 // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
394 else if (in > 55)
395 // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
396 out++;
397
398 out++;
399 }
400
test_chain2(int in,int & out)401 void test_chain2(int in, int &out) {
402 if (in > 77)
403 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone]
404 out++;
405 // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
406 else if (in > 55)
407 // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
408 out++;
409 else if (in > 42)
410 out--;
411 else if (in > 28)
412 // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here
413 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 here
419 out++;
420 }
421 }
422
test_chain3(int in,int & out)423 void test_chain3(int in, int &out) {
424 if (in > 77) {
425 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone]
426 out++;
427 out++;
428 // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original
429 } else if (in > 55) {
430 // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here
431 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 here
437 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 here
446 out++;
447 out++;
448 }
449 }
450
451 // In this chain there are two clone families; notice that the checker
452 // describes all branches of the first one before mentioning the second one.
test_chain4(int in,int & out)453 void test_chain4(int in, int &out) {
454 if (in > 77) {
455 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone]
456 out++;
457 out++;
458 // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original
459 } else if (in > 55) {
460 // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here
461 // CHECK-MESSAGES: :[[@LINE+8]]:21: note: clone 2 starts here
462 // CHECK-MESSAGES: :[[@LINE+15]]:22: note: clone 3 starts here
463 out++;
464 out++;
465 } else if (in > 42)
466 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone]
467 out--;
468 // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
469 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 here
482 out--;
483 }
484 }
485
test_chain5(int in,int & out)486 void test_chain5(int in, int &out) {
487 if (in > 77)
488 // CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch in conditional chain [bugprone-branch-clone]
489 out++;
490 // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
491 else if (in > 55)
492 // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
493 out++;
494 else if (in > 42)
495 out--;
496 else if (in > 28)
497 // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here
498 out++;
499 else if (in > 12) {
500 out++;
501 out *= 7;
502 } else {
503 // CHECK-MESSAGES: :[[@LINE-1]]:10: note: clone 3 starts here
504 out++;
505 }
506 }
507
test_chain6(int in,int & out)508 void test_chain6(int in, int &out) {
509 if (in > 77) {
510 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone]
511 out++;
512 out++;
513 // CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the original
514 } else if (in > 55) {
515 // CHECK-MESSAGES: :[[@LINE-1]]:23: note: clone 1 starts here
516 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 here
522 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 here
531 out++;
532 out++;
533 }
534 }
535
test_nested(int a,int b,int c,int & out)536 void 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 here
540 if (b > 5) {
541 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone]
542 // CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original
543 // CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here
544 // CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here
545 if (c > 5)
546 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]
547 out++;
548 else
549 // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
550 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 else
556 // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
557 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 else
563 // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
564 out++;
565 }
566 } else {
567 if (b > 5) {
568 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch in conditional chain [bugprone-branch-clone]
569 // CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the original
570 // CHECK-MESSAGES: :[[@LINE+8]]:24: note: clone 1 starts here
571 // CHECK-MESSAGES: :[[@LINE+14]]:12: note: clone 2 starts here
572 if (c > 5)
573 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: if with identical then and else branches [bugprone-branch-clone]
574 out++;
575 else
576 // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
577 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 else
583 // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
584 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 else
590 // CHECK-MESSAGES: :[[@LINE-1]]:7: note: else branch starts here
591 out++;
592 }
593 }
594 }
595
596 //=========--------------------==========//
597
598 template <class T>
test_template_not_instantiated(const T & t)599 void 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 else
605 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
606 a++;
607 }
608
609 template <class T>
test_template_instantiated(const T & t)610 void 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 else
616 // CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
617 a++;
618 }
619
620 template void test_template_instantiated<int>(const int &t);
621
622 template <class T>
test_template2(T t,int a)623 void 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
633 template void test_template2<int>(int t, int a);
634
635 template <class T>
test_template3(T t,int a)636 void 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
646 template void test_template3<short>(short t, int a);
647
648 template <class T>
test_template_two_instances(T t,int & a)649 void 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 here
655 a += int(t);
656 }
657 }
658
659 template void test_template_two_instances<short>(short t, int &a);
660 template void test_template_two_instances<long>(long t, int &a);
661
662 class C {
663 int member;
inline_method(int arg)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 else
669 // CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
670 member = 3;
671 }
672 int other_method();
673 };
674
other_method()675 int 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 here
681 return 8;
682 }
683 }
684
685 //=========--------------------==========//
686
simple_switch(char ch)687 int 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 here
695 // 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 here
701 // 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 here
707 default:
708 return 0;
709 }
710 }
711
long_sequence_switch(char ch)712 int 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 here
730 }
731 }
732
nested_switch(int a,int b,int c)733 int 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 here
737 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 here
741 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 here
751 }
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 here
762 }
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 here
773 }
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 here
779 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 here
789 }
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 here
800 }
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 here
811 }
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 here
817 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 here
827 }
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 here
838 }
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 here
849 }
850 }
851 }
852 }
853
854 //=========--------------------==========//
855
856 // This should not produce warnings, as in switch statements we only report
857 // identical branches when they are consecutive. Also note that a branch
858 // terminated by a break is different from a branch terminated by the end of
859 // the switch statement.
interleaved_cases(int a,int b)860 int 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 switch
buried_cases(int foo)894 int 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 checker
906 // thinks that it is part of the `case 9:` branch. While this result is
907 // counterintuitve, mixing goto labels and switch statements in this fashion is
908 // pretty rare, so it does not deserve a special case in the checker code.
decorated_cases(int z)909 int 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 here
925 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.
no_real_body(int in,int & out)945 char 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 in conditional chain [bugprone-branch-clone]
952 out++;
953 // CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
954 else if (in > 55)
955 // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
956 out++;
957 else if (in > 34)
958 // CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 2 starts here
959 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 convoluted
966 // code, but it should avoid crashing.
send(short * to,short * from,int count)967 void 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
ternary1(bool b,int & x)985 void 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
ternary2(bool b,int x)990 int 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
ternary3(bool b,int x)995 int ternary3(bool b, int x) {
996 return b ? 42 : 43;
997 }
998
ternary4(bool b,int x)999 int 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.
ternary5(bool b1,bool b2,int x)1004 int 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:
1012 int d, e;
dontCrash()1013 void 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 here
1024 SEMICOLON_CASE_COLON(3);
1025 }
1026 }
1027