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