1// RUN: %check_clang_tidy %s bugprone-branch-clone %t -- -- -fno-delayed-template-parsing
2
3void test_basic1(int in, int &out) {
4 if (in > 77)
5// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
6 out++;
7 else
8// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
9 out++;
10
11 out++;
12}
13
14void test_basic2(int in, int &out) {
15 if (in > 77) {
16// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
17 out++;
18 }
19 else {
20// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
21 out++;
22 }
23
24 out++;
25}
26
27void test_basic3(int in, int &out) {
28 if (in > 77) {
29// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
30 out++;
31 }
32 else
33// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
34 out++;
35
36 out++;
37}
38
39void test_basic4(int in, int &out) {
40 if (in > 77) {
41 out--;
42 }
43 else {
44 out++;
45 }
46}
47
48void test_basic5(int in, int &out) {
49 if (in > 77) {
50 out++;
51 }
52 else {
53 out++;
54 out++;
55 }
56}
57
58void test_basic6(int in, int &out) {
59 if (in > 77) {
60 out++;
61 }
62 else {
63 out++, out++;
64 }
65}
66
67void test_basic7(int in, int &out) {
68 if (in > 77) {
69 out++;
70 out++;
71 }
72 else
73 out++;
74
75 out++;
76}
77
78void test_basic8(int in, int &out) {
79 if (in > 77) {
80// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
81 out++;
82 out++;
83 } else {
84// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
85 out++;
86 out++;
87 }
88
89 if (in % 2)
90 out++;
91}
92
93void test_basic9(int in, int &out) {
94 if (in > 77) {
95// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
96 if (in % 2)
97 out++;
98 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`.
111void 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
125void test_basic11(int in, int &out) {
126 if (in > 77) {
127// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
128 if (in % 2)
129 out++;
130 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
149void test_basic12(int in, int &out) {
150 if (in > 77) {
151// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
152 } else {
153// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
154 }
155}
156
157void test_basic13(int in, int &out) {
158 if (in > 77) {
159 // Empty compound statement is not identical to null statement.
160 } else;
161}
162
163// We use a comparison that ignores redundant parentheses:
164void test_basic14(int in, int &out) {
165 if (in > 77)
166 out += 2;
167 else
168 (out) += (2);
169}
170
171void 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:
179void 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:
187int 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
198void test_macro1(int in, int &out) {
199 PASTE_CODE(
200 if (in > 77)
201// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]
202 out++;
203 else
204// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
205 out++;
206 )
207
208 out--;
209}
210
211void test_macro2(int in, int &out) {
212 PASTE_CODE(
213 if (in > 77)
214// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]
215 out++;
216 )
217 else
218// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
219 out++;
220}
221
222void test_macro3(int in, int &out) {
223 if (in > 77)
224// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
225 out++;
226 PASTE_CODE(
227 else
228// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
229 out++;
230 )
231}
232
233void test_macro4(int in, int &out) {
234 if (in > 77)
235// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
236 out++;
237 else
238// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
239 PASTE_CODE(
240 out++;
241 )
242}
243
244void test_macro5(int in, int &out) {
245 PASTE_CODE(if) (in > 77)
246// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: if with identical then and else branches [bugprone-branch-clone]
247 out++;
248 PASTE_CODE(else)
249// CHECK-MESSAGES: :[[@LINE-1]]:14: note: else branch starts here
250 out++;
251}
252
253#define OTHERWISE_INCREASE else out++
254
255void test_macro6(int in, int &out) {
256 if (in > 77)
257 out++;
258// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
259 OTHERWISE_INCREASE;
260// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts 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
272void test_macro7(int in, int &out1, int &out2) {
273 COND_INCR(in, out1, out1);
274// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
275// CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR'
276// CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here
277// CHECK-MESSAGES: :[[@LINE-9]]:5: note: expanded from macro 'COND_INCR'
278}
279
280void test_macro8(int in, int &out1, int &out2) {
281 COND_INCR(in, out1, out2);
282}
283
284void test_macro9(int in, int &out1, int &out2) {
285 COND_INCR(in, out2, out2);
286// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
287// CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR'
288// CHECK-MESSAGES: :[[@LINE-3]]:3: note: else branch starts here
289// CHECK-MESSAGES: :[[@LINE-21]]:5: note: expanded from macro 'COND_INCR'
290}
291
292#define CONCAT(a, b) a##b
293
294void test_macro10(int in, int &out) {
295 CONCAT(i, f) (in > 77)
296// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
297 out++;
298 CONCAT(el, se)
299// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
300 out++;
301}
302
303#define PROBLEM (-1)
304
305int test_macro11(int count) {
306 if (!count)
307 return PROBLEM;
308 else if (count == 13)
309 return -1;
310 else
311 return count * 2;
312}
313
314#define IF if (
315#define THEN ) {
316#define ELSE } else {
317#define END }
318
319void test_macro12(int in, int &out) {
320 IF in > 77 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
338void test_macro13(int in, int &out) {
339 SWITCH(in)
340// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
341 CASE(1)
342 out++;
343 out++;
344 CASE(2)
345 out++;
346 out++;
347 CASE(3)
348 out++;
349 out++;
350// CHECK-MESSAGES: :[[@LINE-15]]:24: note: expanded from macro 'CASE'
351// CHECK-MESSAGES: :[[@LINE+1]]:9: note: last of these clones ends 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
389void test_chain1(int in, int &out) {
390 if (in > 77)
391// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
392 out++;
393// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the original
394 else if (in > 55)
395// CHECK-MESSAGES: :[[@LINE+1]]:5: note: clone 1 starts here
396 out++;
397
398 out++;
399}
400
401void test_chain2(int in, int &out) {
402 if (in > 77)
403// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
404 out++;
405// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the 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
423void test_chain3(int in, int &out) {
424 if (in > 77) {
425// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
426 out++;
427 out++;
428// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the 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.
453void test_chain4(int in, int &out) {
454 if (in > 77) {
455// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
456 out++;
457 out++;
458// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the 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 body 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
486void test_chain5(int in, int &out) {
487 if (in > 77)
488// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
489 out++;
490// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the 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
508void test_chain6(int in, int &out) {
509 if (in > 77) {
510// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
511 out++;
512 out++;
513// CHECK-MESSAGES: :[[@LINE+1]]:4: note: end of the 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
536void test_nested(int a, int b, int c, int &out) {
537 if (a > 5) {
538// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
539// CHECK-MESSAGES: :[[@LINE+27]]:5: note: else branch starts here
540 if (b > 5) {
541// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: repeated branch body in conditional chain [bugprone-branch-clone]
542// CHECK-MESSAGES: :[[@LINE+9]]:6: note: end of the 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 body 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
598template <class T>
599void test_template_not_instantiated(const T &t) {
600 int a;
601 if (t)
602// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
603 a++;
604 else
605// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
606 a++;
607}
608
609template <class T>
610void test_template_instantiated(const T &t) {
611 int a;
612 if (t)
613// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
614 a++;
615 else
616// CHECK-MESSAGES: :[[@LINE-1]]:3: note: else branch starts here
617 a++;
618}
619
620template void test_template_instantiated<int>(const int &t);
621
622template <class T>
623void test_template2(T t, int a) {
624 if (a) {
625 T b(0);
626 a += b;
627 } else {
628 int b(0);
629 a += b;
630 }
631}
632
633template void test_template2<int>(int t, int a);
634
635template <class T>
636void test_template3(T t, int a) {
637 if (a) {
638 T b(0);
639 a += b;
640 } else {
641 int b(0);
642 a += b;
643 }
644}
645
646template void test_template3<short>(short t, int a);
647
648template <class T>
649void test_template_two_instances(T t, int &a) {
650 if (a) {
651// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
652 a += int(t);
653 } else {
654// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
655 a += int(t);
656 }
657}
658
659template void test_template_two_instances<short>(short t, int &a);
660template void test_template_two_instances<long>(long t, int &a);
661
662class C {
663 int member;
664 void inline_method(int arg) {
665 if (arg)
666// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: if with identical then and else branches [bugprone-branch-clone]
667 member = 3;
668 else
669// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
670 member = 3;
671 }
672 int other_method();
673};
674
675int C::other_method() {
676 if (member) {
677// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: if with identical then and else branches [bugprone-branch-clone]
678 return 8;
679 } else {
680// CHECK-MESSAGES: :[[@LINE-1]]:5: note: else branch starts here
681 return 8;
682 }
683}
684
685//=========--------------------==========//
686
687int simple_switch(char ch) {
688 switch (ch) {
689// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
690 case 'a':
691 return 10;
692 case 'A':
693 return 10;
694// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends 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
712int long_sequence_switch(char ch) {
713 switch (ch) {
714// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 7 consecutive identical branches [bugprone-branch-clone]
715 case 'a':
716 return 10;
717 case 'A':
718 return 10;
719 case 'b':
720 return 10;
721 case 'B':
722 return 10;
723 case 'c':
724 return 10;
725 case 'C':
726 return 10;
727 default:
728 return 10;
729// CHECK-MESSAGES: :[[@LINE-1]]:14: note: last of these clones ends here
730 }
731}
732
733int nested_switch(int a, int b, int c) {
734 switch (a) {
735// CHECK-MESSAGES: :[[@LINE+2]]:3: warning: switch has 3 consecutive identical branches [bugprone-branch-clone]
736// CHECK-MESSAGES: :[[@LINE+114]]:6: note: last of these clones ends 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.
860int interleaved_cases(int a, int b) {
861 switch (a) {
862 case 3:
863 case 4:
864 b = 2;
865 break;
866 case 5:
867 b = 3;
868 break;
869 case 6:
870 b = 2;
871 break;
872 case 7:
873 if (b % 2) {
874 b++;
875 } else {
876 b++;
877 break;
878 }
879 b = 2;
880 break;
881 case 8:
882 b = 2;
883 case 9:
884 b = 3;
885 break;
886 default:
887 b = 3;
888 }
889 return b;
890}
891
892
893// A case: or default: is only considered to be the start of a branch if it is a direct child of the CompoundStmt forming the body of the switch
894int 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.
909int decorated_cases(int z) {
910 if (!(z % 777)) {
911 goto lucky;
912 }
913 switch (z) {
914// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
915 case 1:
916 case 2:
917 case 3:
918 z++;
919 break;
920 case 4:
921 case 5:
922 z++;
923 break;
924// CHECK-MESSAGES: :[[@LINE-1]]:10: note: last of these clones ends 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.
945char no_real_body(int in, int &out) {
946 switch (in)
947 case 42:
948 return 'A';
949
950 if (in > 77)
951// CHECK-MESSAGES: :[[@LINE+1]]:5: warning: repeated branch body in conditional chain [bugprone-branch-clone]
952 out++;
953// CHECK-MESSAGES: :[[@LINE-1]]:10: note: end of the 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.
967void send(short *to, short *from, int count)
968{
969 int n = (count + 7) / 8;
970 switch (count % 8) {
971 case 0: do { *to = *from++;
972 case 7: *to = *from++;
973 case 6: *to = *from++;
974 case 5: *to = *from++;
975 case 4: *to = *from++;
976 case 3: *to = *from++;
977 case 2: *to = *from++;
978 case 1: *to = *from++;
979 } while (--n > 0);
980 }
981}
982
983//=========--------------------==========//
984
985void ternary1(bool b, int &x) {
986// CHECK-MESSAGES: :[[@LINE+1]]:6: warning: conditional operator with identical true and false expressions [bugprone-branch-clone]
987 (b ? x : x) = 42;
988}
989
990int ternary2(bool b, int x) {
991// CHECK-MESSAGES: :[[@LINE+1]]:12: warning: conditional operator with identical true and false expressions [bugprone-branch-clone]
992 return b ? 42 : 42;
993}
994
995int ternary3(bool b, int x) {
996 return b ? 42 : 43;
997}
998
999int ternary4(bool b, int x) {
1000 return b ? true ? 45 : 44 : false ? 45 : 44;
1001}
1002
1003// We do not detect chains of conditional operators.
1004int ternary5(bool b1, bool b2, int x) {
1005 return b1 ? 42 : b2 ? 43 : 42;
1006}
1007
1008#define SWITCH_WITH_LBRACE(b) switch (b) {
1009#define SEMICOLON_CASE_COLON(b) \
1010 ; \
1011 case b:
1012int d, e;
1013void dontCrash() {
1014 SWITCH_WITH_LBRACE(d)
1015// CHECK-MESSAGES: :[[@LINE+1]]:3: warning: switch has 2 consecutive identical branches [bugprone-branch-clone]
1016 SEMICOLON_CASE_COLON(1)
1017 e++;
1018 e++;
1019 SEMICOLON_CASE_COLON(2)
1020 e++;
1021 e++;
1022 // CHECK-MESSAGES: :[[@LINE-11]]:3: note: expanded from macro 'SEMICOLON_CASE_COLON'
1023 // CHECK-MESSAGES: :[[@LINE+1]]:23: note: last of these clones ends here
1024 SEMICOLON_CASE_COLON(3);
1025 }
1026}
1027
1028namespace PR62693 {
1029 class Object {
1030 public:
1031 template <typename T>
1032 bool ConvertableTo() const;
1033
1034 template <typename T>
1035 void Handle();
1036 };
1037
1038 template <typename T>
1039 void update(Object &a) {
1040 if (a.ConvertableTo<char *>()) {
1041 a.Handle<char *>();
1042 } else {
1043 a.Handle<T>();
1044 }
1045 }
1046
1047 template <typename T>
1048 void update2(Object &a) {
1049 if (a.ConvertableTo<char *>()) {
1050 a.Handle<char *>();
1051 } else {
1052 a.Handle<T>();
1053 }
1054 }
1055
1056 void foo(Object &a) {
1057 update<int>(a);
1058 update2<char *>(a);
1059 }
1060
1061 template <typename T>
1062 int branch_clone_in_template(T t) {
1063 // CHECK-MESSAGES: :[[@LINE+2]]:5: warning: if with identical then and else branches [bugprone-branch-clone]
1064 // CHECK-MESSAGES: :[[@LINE+3]]:7: note: else branch starts here
1065 if (t) {
1066 return 42;
1067 } else {
1068 return 42;
1069 }
1070 }
1071}
1072

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/branch-clone.cpp