xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/simplify-boolean-expr.cpp (revision e69794323338c5279011e6f01c12254da8dff10d)
1 // RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t
2 
3 bool a1 = false;
4 
5 //=-=-=-=-=-=-= operator ==
6 bool aa = false == a1;
7 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant boolean literal supplied to boolean operator [readability-simplify-boolean-expr]
8 // CHECK-FIXES: {{^bool aa = !a1;$}}
9 bool ab = true == a1;
10 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
11 // CHECK-FIXES: {{^bool ab = a1;$}}
12 bool a2 = a1 == false;
13 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
14 // CHECK-FIXES: {{^bool a2 = !a1;$}}
15 bool a3 = a1 == true;
16 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
17 // CHECK-FIXES: {{^bool a3 = a1;$}}
18 
19 //=-=-=-=-=-=-= operator !=
20 bool n1 = a1 != false;
21 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
22 // CHECK-FIXES: {{^bool n1 = a1;$}}
23 bool n2 = a1 != true;
24 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
25 // CHECK-FIXES: {{^bool n2 = !a1;$}}
26 bool n3 = false != a1;
27 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
28 // CHECK-FIXES: {{^bool n3 = a1;$}}
29 bool n4 = true != a1;
30 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
31 // CHECK-FIXES: {{^bool n4 = !a1;$}}
32 
33 //=-=-=-=-=-=-= operator ||
34 bool a4 = a1 || false;
35 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
36 // CHECK-FIXES: {{^bool a4 = a1;$}}
37 bool a5 = a1 || true;
38 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
39 // CHECK-FIXES: {{^bool a5 = true;$}}
40 bool a6 = false || a1;
41 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
42 // CHECK-FIXES: {{^bool a6 = a1;$}}
43 bool a7 = true || a1;
44 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
45 // CHECK-FIXES: {{^bool a7 = true;$}}
46 
47 //=-=-=-=-=-=-= operator &&
48 bool a8 = a1 && false;
49 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
50 // CHECK-FIXES: {{^bool a8 = false;$}}
51 bool a9 = a1 && true;
52 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
53 // CHECK-FIXES: {{^bool a9 = a1;$}}
54 bool ac = false && a1;
55 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
56 // CHECK-FIXES: {{^bool ac = false;$}}
57 bool ad = true && a1;
58 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}} to boolean operator
59 // CHECK-FIXES: {{^bool ad = a1;$}}
60 
if_with_bool_literal_condition()61 void if_with_bool_literal_condition() {
62   int i = 0;
63   if (false) {
64     i = 1;
65   } else {
66     i = 2;
67   }
68   i = 3;
69   // CHECK-MESSAGES: :[[@LINE-6]]:7: warning: {{.*}} in if statement condition
70   // CHECK-FIXES:      {{^  int i = 0;$}}
71   // CHECK-FIXES-NEXT: {{^  {$}}
72   // CHECK-FIXES-NEXT: {{^    i = 2;$}}
73   // CHECK-FIXES-NEXT: {{^  }$}}
74   // CHECK-FIXES-NEXT: {{^  i = 3;$}}
75 
76   i = 4;
77   if (true) {
78     i = 5;
79   } else {
80     i = 6;
81   }
82   i = 7;
83   // CHECK-MESSAGES: :[[@LINE-6]]:7: warning: {{.*}} in if statement condition
84   // CHECK-FIXES:      {{^  i = 4;$}}
85   // CHECK-FIXES-NEXT: {{^  {$}}
86   // CHECK-FIXES-NEXT: {{^    i = 5;$}}
87   // CHECK-FIXES-NEXT: {{^  }$}}
88   // CHECK-FIXES-NEXT: {{^  i = 7;$}}
89 
90   i = 8;
91   if (false) {
92     i = 9;
93   }
94   i = 11;
95   // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: {{.*}} in if statement condition
96   // CHECK-FIXES:      {{^  i = 8;$}}
97   // CHECK-FIXES-NEXT: {{^  $}}
98   // CHECK-FIXES-NEXT: {{^  i = 11;$}}
99 }
100 
if_with_negated_bool_condition()101 void if_with_negated_bool_condition() {
102   int i = 10;
103   if (!true) {
104     i = 11;
105   } else {
106     i = 12;
107   }
108   i = 13;
109   // CHECK-MESSAGES: :[[@LINE-6]]:7: warning: {{.*}} in if statement condition
110   // CHECK-FIXES:      {{^  int i = 10;$}}
111   // CHECK-FIXES-NEXT: {{^  {$}}
112   // CHECK-FIXES-NEXT: {{^    i = 12;$}}
113   // CHECK-FIXES-NEXT: {{^  }$}}
114   // CHECK-FIXES-NEXT: {{^  i = 13;$}}
115 
116   i = 14;
117   if (!false) {
118     i = 15;
119   } else {
120     i = 16;
121   }
122   i = 17;
123   // CHECK-MESSAGES: :[[@LINE-6]]:7: warning: {{.*}} in if statement condition
124   // CHECK-FIXES:      {{^  i = 14;$}}
125   // CHECK-FIXES-NEXT: {{^  {$}}
126   // CHECK-FIXES-NEXT: {{^    i = 15;$}}
127   // CHECK-FIXES-NEXT: {{^  }$}}
128   // CHECK-FIXES-NEXT: {{^  i = 17;$}}
129 
130   i = 18;
131   if (!true) {
132     i = 19;
133   }
134   i = 20;
135   // CHECK-MESSAGES: :[[@LINE-4]]:7: warning: {{.*}} in if statement condition
136   // CHECK-FIXES:      {{^  i = 18;$}}
137   // CHECK-FIXES-NEXT: {{^  $}}
138   // CHECK-FIXES-NEXT: {{^  i = 20;$}}
139 }
140 
operator_equals()141 void operator_equals() {
142   int i = 0;
143   bool b1 = (i > 2);
144   if (b1 == true) {
145     // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
146     // CHECK-FIXES: {{^  if \(b1\) {$}}
147     i = 5;
148   } else {
149     i = 6;
150   }
151   bool b2 = (i > 4);
152   if (b2 == false) {
153     // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
154     // CHECK-FIXES: {{^  if \(!b2\) {$}}
155     i = 7;
156   } else {
157     i = 9;
158   }
159   bool b3 = (i > 6);
160   if (true == b3) {
161     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
162     // CHECK-FIXES: {{^  if \(b3\) {$}}
163     i = 10;
164   } else {
165     i = 11;
166   }
167   bool b4 = (i > 8);
168   if (false == b4) {
169     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
170     // CHECK-FIXES: {{^  if \(!b4\) {$}}
171     i = 12;
172   } else {
173     i = 13;
174   }
175 }
176 
operator_or()177 void operator_or() {
178   int i = 0;
179   bool b5 = (i > 10);
180   if (b5 || false) {
181     // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
182     // CHECK-FIXES: {{^  if \(b5\) {$}}
183     i = 14;
184   } else {
185     i = 15;
186   }
187   bool b6 = (i > 10);
188   if (b6 || true) {
189     // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
190     // CHECK-FIXES: {{^  if \(true\) {$}}
191     i = 16;
192   } else {
193     i = 17;
194   }
195   bool b7 = (i > 10);
196   if (false || b7) {
197     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
198     // CHECK-FIXES: {{^  if \(b7\) {$}}
199     i = 18;
200   } else {
201     i = 19;
202   }
203   bool b8 = (i > 10);
204   if (true || b8) {
205     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
206     // CHECK-FIXES: {{^  if \(true\) {$}}
207     i = 20;
208   } else {
209     i = 21;
210   }
211 }
212 
operator_and()213 void operator_and() {
214   int i = 0;
215   bool b9 = (i > 20);
216   if (b9 && false) {
217     // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
218     // CHECK-FIXES: {{^  if \(false\) {$}}
219     i = 22;
220   } else {
221     i = 23;
222   }
223   bool ba = (i > 20);
224   if (ba && true) {
225     // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
226     // CHECK-FIXES: {{^  if \(ba\) {$}}
227     i = 24;
228   } else {
229     i = 25;
230   }
231   bool bb = (i > 20);
232   if (false && bb) {
233     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
234     // CHECK-FIXES: {{^  if \(false\) {$}}
235     i = 26;
236   } else {
237     i = 27;
238   }
239   bool bc = (i > 20);
240   if (true && bc) {
241     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
242     // CHECK-FIXES: {{^  if \(bc\) {$}}
243     i = 28;
244   } else {
245     i = 29;
246   }
247 }
248 
ternary_operator()249 void ternary_operator() {
250   int i = 0;
251   bool bd = (i > 20) ? true : false;
252   // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} in ternary expression result
253   // CHECK-FIXES: {{^  bool bd = i > 20;$}}
254 
255   bool be = (i > 20) ? false : true;
256   // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: {{.*}} in ternary expression result
257   // CHECK-FIXES: {{^  bool be = i <= 20;$}}
258 
259   bool bf = ((i > 20)) ? false : true;
260   // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: {{.*}} in ternary expression result
261   // CHECK-FIXES: {{^  bool bf = i <= 20;$}}
262 }
263 
operator_not_equal()264 void operator_not_equal() {
265   int i = 0;
266   bool bf = (i > 20);
267   if (false != bf) {
268     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
269     // CHECK-FIXES: {{^  if \(bf\) {$}}
270     i = 30;
271   } else {
272     i = 31;
273   }
274   bool bg = (i > 20);
275   if (true != bg) {
276     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
277     // CHECK-FIXES: {{^  if \(!bg\) {$}}
278     i = 32;
279   } else {
280     i = 33;
281   }
282   bool bh = (i > 20);
283   if (bh != false) {
284     // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
285     // CHECK-FIXES: {{^  if \(bh\) {$}}
286     i = 34;
287   } else {
288     i = 35;
289   }
290   bool bi = (i > 20);
291   if (bi != true) {
292     // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}} to boolean operator
293     // CHECK-FIXES: {{^  if \(!bi\) {$}}
294     i = 36;
295   } else {
296     i = 37;
297   }
298 }
299 
nested_booleans()300 void nested_booleans() {
301   if (false || (true || false)) {
302     // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
303     // CHECK-FIXES: {{^  if \(false \|\| \(true\)\) {$}}
304   }
305   if (true && (true || false)) {
306     // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} to boolean operator
307     // CHECK-FIXES: {{^  if \(true && \(true\)\) {$}}
308   }
309   if (false || (true && false)) {
310     // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}} to boolean operator
311     // CHECK-FIXES: {{^  if \(false \|\| \(false\)\) {$}}
312   }
313   if (true && (true && false)) {
314     // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: {{.*}} to boolean operator
315     // CHECK-FIXES: {{^  if \(true && \(false\)\) {$}}
316   }
317 }
318 
truthy()319 static constexpr bool truthy() {
320   return true;
321 }
322 
323 #define HAS_XYZ_FEATURE true
324 #define M1(what) M2(true, what)
325 #define M2(condition, what) if (condition) what
326 
macros_and_constexprs(int i=0)327 void macros_and_constexprs(int i = 0) {
328   bool b = (i == 1);
329   if (b && truthy()) {
330     // leave this alone; if you want it simplified, then you should
331     // inline the constexpr function first.
332     i = 1;
333   }
334   i = 2;
335   if (b && HAS_XYZ_FEATURE) {
336     // leave this alone; if you want it simplified, then you should
337     // inline the macro first.
338     i = 3;
339   }
340   if (HAS_XYZ_FEATURE) {
341     i = 5;
342   }
343   i = 4;
344   M1(i = 7);
345 }
346 
347 #undef HAS_XYZ_FEATURE
348 
conditional_return_statements(int i)349 bool conditional_return_statements(int i) {
350   if (i == 0) return true; else return false;
351 }
352 // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}} in conditional return statement
353 // CHECK-FIXES:      {{^}}  return i == 0;{{$}}
354 // CHECK-FIXES-NEXT: {{^}$}}
355 
conditional_return_statements_no_fix_1(int i)356 bool conditional_return_statements_no_fix_1(int i) {
357   if (i == 0) return true;
358   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: {{.*}} in conditional return statement
359   // CHECK-MESSAGES: :[[@LINE-2]]:7: note: conditions that can be simplified
360   // comment
361   return false;
362   // CHECK-MESSAGES: :[[@LINE-1]]:3: note: return statement that can be simplified
363 }
364 
conditional_return_statements_no_fix_2(int i)365 bool conditional_return_statements_no_fix_2(int i) {
366   if (i == 0) return true;
367   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: {{.*}} in conditional return statement
368   // CHECK-MESSAGES: :[[@LINE-2]]:7: note: conditions that can be simplified
369   // comment
370   else return false;
371 }
372 
conditional_return_statements_then_expr(int i,int j)373 bool conditional_return_statements_then_expr(int i, int j) {
374   if (i == j) return (i == 0); else return false;
375 }
376 
conditional_return_statements_else_expr(int i,int j)377 bool conditional_return_statements_else_expr(int i, int j) {
378   if (i == j) return true; else return (i == 0);
379 }
380 
negated_conditional_return_statements(int i)381 bool negated_conditional_return_statements(int i) {
382   if (i == 0) return false; else return true;
383 }
384 // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}} in conditional return statement
385 // CHECK-FIXES:      {{^}}  return i != 0;{{$}}
386 // CHECK-FIXES-NEXT: {{^}$}}
387 
negative_condition_conditional_return_statement(int i)388 bool negative_condition_conditional_return_statement(int i) {
389   if (!(i == 0)) return false; else return true;
390 }
391 // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: {{.*}} in conditional return statement
392 // CHECK-FIXES:      {{^}}  return i == 0;{{$}}
393 // CHECK-FIXES-NEXT: {{^}$}}
394 
conditional_compound_return_statements(int i)395 bool conditional_compound_return_statements(int i) {
396   if (i == 1) {
397     return true;
398   } else {
399     return false;
400   }
401 }
402 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return statement
403 // CHECK-FIXES:      {{^}}bool conditional_compound_return_statements(int i) {{{$}}
404 // CHECK-FIXES-NEXT: {{^}}  return i == 1;{{$}}
405 // CHECK-FIXES-NEXT: {{^}$}}
406 
negated_conditional_compound_return_statements(int i)407 bool negated_conditional_compound_return_statements(int i) {
408   if (i == 1) {
409     return false;
410   } else {
411     return true;
412   }
413 }
414 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return statement
415 // CHECK-FIXES:      {{^}}bool negated_conditional_compound_return_statements(int i) {{{$}}
416 // CHECK-FIXES-NEXT: {{^}}  return i != 1;{{$}}
417 // CHECK-FIXES-NEXT: {{^}$}}
418 
conditional_return_statements_side_effects_then(int i)419 bool conditional_return_statements_side_effects_then(int i) {
420   if (i == 2) {
421     macros_and_constexprs();
422     return true;
423   } else
424     return false;
425 }
426 
negated_conditional_return_statements_side_effects_then(int i)427 bool negated_conditional_return_statements_side_effects_then(int i) {
428   if (i == 2) {
429     macros_and_constexprs();
430     return false;
431   } else
432     return true;
433 }
434 
conditional_return_statements_side_effects_else(int i)435 bool conditional_return_statements_side_effects_else(int i) {
436   if (i == 2)
437     return true;
438   else {
439     macros_and_constexprs();
440     return false;
441   }
442 }
443 
negated_conditional_return_statements_side_effects_else(int i)444 bool negated_conditional_return_statements_side_effects_else(int i) {
445   if (i == 2)
446     return false;
447   else {
448     macros_and_constexprs();
449     return true;
450   }
451 }
452 
lambda_conditional_return_statements()453 void lambda_conditional_return_statements() {
454   auto lambda = [](int n) -> bool { if (n > 0) return true; else return false; };
455   // CHECK-MESSAGES: :[[@LINE-1]]:55: warning: {{.*}} in conditional return statement
456   // CHECK-FIXES: {{^}}  auto lambda = [](int n) -> bool { return n > 0; };{{$}}
457 
458   auto lambda2 = [](int n) -> bool {
459     if (n > 0) {
460         return true;
461     } else {
462         return false;
463     }
464   };
465   // CHECK-MESSAGES: :[[@LINE-5]]:16: warning: {{.*}} in conditional return statement
466   // CHECK-FIXES:      {{^}}  auto lambda2 = [](int n) -> bool {{{$}}
467   // CHECK-FIXES-NEXT: {{^}}    return n > 0;{{$}}
468   // CHECK-FIXES-NEXT: {{^}}  };{{$}}
469 
470   auto lambda3 = [](int n) -> bool { if (n > 0) {macros_and_constexprs(); return true; } else return false; };
471 
472   auto lambda4 = [](int n) -> bool {
473     if (n > 0)
474         return true;
475     else {
476         macros_and_constexprs();
477         return false;
478     }
479   };
480 
481   auto lambda5 = [](int n) -> bool { if (n > 0) return false; else return true; };
482   // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: {{.*}} in conditional return statement
483   // CHECK-FIXES: {{^}}  auto lambda5 = [](int n) -> bool { return n <= 0; };{{$}}
484 
485   auto lambda6 = [](int n) -> bool {
486     if (n > 0) {
487         return false;
488     } else {
489         return true;
490     }
491   };
492   // CHECK-MESSAGES: :[[@LINE-5]]:16: warning: {{.*}} in conditional return statement
493   // CHECK-FIXES:      {{^}}  auto lambda6 = [](int n) -> bool {{{$}}
494   // CHECK-FIXES-NEXT: {{^}}    return n <= 0;{{$}}
495   // CHECK-FIXES-NEXT: {{^}}  };{{$}}
496 }
497 
condition_variable_return_stmt(int i)498 bool condition_variable_return_stmt(int i) {
499   // Unchanged: condition variable.
500   if (bool Res = i == 0)
501     return true;
502   else
503     return false;
504 }
505 
simple_conditional_assignment_statements(int i)506 void simple_conditional_assignment_statements(int i) {
507   bool b;
508   if (i > 10)
509     b = true;
510   else
511     b = false;
512   bool bb = false;
513   // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in conditional assignment
514   // CHECK-FIXES: bool b;
515   // CHECK-FIXES: {{^  }}b = i > 10;{{$}}
516   // CHECK-FIXES: bool bb = false;
517 
518   bool c;
519   if (i > 20)
520     c = false;
521   else
522     c = true;
523   bool c2 = false;
524   // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in conditional assignment
525   // CHECK-FIXES: bool c;
526   // CHECK-FIXES: {{^  }}c = i <= 20;{{$}}
527   // CHECK-FIXES: bool c2 = false;
528 
529   // Unchanged: different variables.
530   bool b2;
531   if (i > 12)
532     b = true;
533   else
534     b2 = false;
535 
536   // Unchanged: no else statement.
537   bool b3;
538   if (i > 15)
539     b3 = true;
540 
541   // Unchanged: not boolean assignment.
542   int j;
543   if (i > 17)
544     j = 10;
545   else
546     j = 20;
547 
548   // Unchanged: different variables assigned.
549   int k = 0;
550   bool b4 = false;
551   if (i > 10)
552     b4 = true;
553   else
554     k = 10;
555 }
556 
complex_conditional_assignment_statements(int i)557 void complex_conditional_assignment_statements(int i) {
558   bool d;
559   if (i > 30) {
560     d = true;
561   } else {
562     d = false;
563   }
564   d = false;
565   // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
566   // CHECK-FIXES: bool d;
567   // CHECK-FIXES: {{^  }}d = i > 30;{{$}}
568   // CHECK-FIXES: d = false;
569 
570   bool e;
571   if (i > 40) {
572     e = false;
573   } else {
574     e = true;
575   }
576   e = false;
577   // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
578   // CHECK-FIXES: bool e;
579   // CHECK-FIXES: {{^  }}e = i <= 40;{{$}}
580   // CHECK-FIXES: e = false;
581 
582   // Unchanged: no else statement.
583   bool b3;
584   if (i > 15) {
585     b3 = true;
586   }
587 
588   // Unchanged: not a boolean assignment.
589   int j;
590   if (i > 17) {
591     j = 10;
592   } else {
593     j = 20;
594   }
595 
596   // Unchanged: multiple statements.
597   bool f;
598   if (j > 10) {
599     j = 10;
600     f = true;
601   } else {
602     j = 20;
603     f = false;
604   }
605 
606   // Unchanged: multiple statements.
607   bool g;
608   if (j > 10)
609     g = true;
610   else {
611     j = 20;
612     g = false;
613   }
614 
615   // Unchanged: multiple statements.
616   bool h;
617   if (j > 10) {
618     j = 10;
619     h = true;
620   } else
621     h = false;
622 
623   // Unchanged: condition variable.
624   bool k;
625   if (bool Res = j > 10)
626     k = true;
627   else
628     k = false;
629 }
630 
631 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_conditional_compound_return(int i)632 bool chained_conditional_compound_return(int i) {
633   if (i < 0) {
634     return true;
635   } else if (i < 10) {
636     return false;
637   } else if (i > 20) {
638     return true;
639   } else {
640     return false;
641   }
642 }
643 
644 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_conditional_return(int i)645 bool chained_conditional_return(int i) {
646   if (i < 0)
647     return true;
648   else if (i < 10)
649     return false;
650   else if (i > 20)
651     return true;
652   else
653     return false;
654 }
655 
656 // Unchanged: chained assignments, but ChainedConditionalAssignment not set.
chained_conditional_compound_assignment(int i)657 void chained_conditional_compound_assignment(int i) {
658   bool b;
659   if (i < 0) {
660     b = true;
661   } else if (i < 10) {
662     b = false;
663   } else if (i > 20) {
664     b = true;
665   } else {
666     b = false;
667   }
668 }
669 
670 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_conditional_assignment(int i)671 void chained_conditional_assignment(int i) {
672   bool b;
673   if (i < 0)
674     b = true;
675   else if (i < 10)
676     b = false;
677   else if (i > 20)
678     b = true;
679   else
680     b = false;
681 }
682 
683 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_simple_if_return_negated(int i)684 bool chained_simple_if_return_negated(int i) {
685   if (i < 5)
686     return false;
687   if (i > 10)
688     return false;
689   return true;
690 }
691 
692 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
complex_chained_if_return_return(int i)693 bool complex_chained_if_return_return(int i) {
694   if (i < 5) {
695     return true;
696   }
697   if (i > 10) {
698     return true;
699   }
700   return false;
701 }
702 
703 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
complex_chained_if_return_return_negated(int i)704 bool complex_chained_if_return_return_negated(int i) {
705   if (i < 5) {
706     return false;
707   }
708   if (i > 10) {
709     return false;
710   }
711   return true;
712 }
713 
714 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_simple_if_return(int i)715 bool chained_simple_if_return(int i) {
716   if (i < 5)
717     return true;
718   if (i > 10)
719     return true;
720   return false;
721 }
722 
simple_if_return_return(int i)723 bool simple_if_return_return(int i) {
724   if (i > 10)
725     return true;
726   return false;
727 }
728 // CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
729 // CHECK-FIXES: {{^}}bool simple_if_return_return(int i) {{{$}}
730 // CHECK-FIXES: {{^  return i > 10;$}}
731 // CHECK-FIXES: {{^}$}}
732 
simple_if_return_return_negated(int i)733 bool simple_if_return_return_negated(int i) {
734   if (i > 10)
735     return false;
736   return true;
737 }
738 // CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
739 // CHECK-FIXES: {{^}}bool simple_if_return_return_negated(int i) {{{$}}
740 // CHECK-FIXES: {{^  return i <= 10;$}}
741 // CHECK-FIXES: {{^}$}}
742 
complex_if_return_return(int i)743 bool complex_if_return_return(int i) {
744   if (i > 10) {
745     return true;
746   }
747   return false;
748 }
749 // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
750 // CHECK-FIXES: {{^}}bool complex_if_return_return(int i) {{{$}}
751 // CHECK-FIXES: {{^  return i > 10;$}}
752 // CHECK-FIXES: {{^}$}}
753 
complex_if_return_return_negated(int i)754 bool complex_if_return_return_negated(int i) {
755   if (i > 10) {
756     return false;
757   }
758   return true;
759 }
760 // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
761 // CHECK-FIXES: {{^}}bool complex_if_return_return_negated(int i) {{{$}}
762 // CHECK-FIXES: {{^  return i <= 10;$}}
763 // CHECK-FIXES: {{^}$}}
764 
if_implicit_bool_expr(int i)765 bool if_implicit_bool_expr(int i) {
766   if (i & 1) {
767     return true;
768   } else {
769     return false;
770   }
771 }
772 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
773 // CHECK-FIXES: {{^}}  return (i & 1) != 0;{{$}}
774 
negated_if_implicit_bool_expr(int i)775 bool negated_if_implicit_bool_expr(int i) {
776   if (i - 1) {
777     return false;
778   } else {
779     return true;
780   }
781 }
782 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
783 // CHECK-FIXES: {{^}}  return (i - 1) == 0;{{$}}
784 
implicit_int(int i)785 bool implicit_int(int i) {
786   if (i) {
787     return true;
788   } else {
789     return false;
790   }
791 }
792 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
793 // CHECK-FIXES: {{^}}  return i != 0;{{$}}
794 
explicit_bool(bool b)795 bool explicit_bool(bool b) {
796   if (b) {
797     return true;
798   } else {
799     return false;
800   }
801 }
802 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
803 // CHECK-FIXES: {{^}}  return b;{{$}}
804 
805 class Implicit {
806 public:
operator bool()807   operator bool() {
808     return true;
809   }
810 };
811 
object_bool_implicit_conversion(Implicit O)812 bool object_bool_implicit_conversion(Implicit O) {
813   if (O) {
814     return true;
815   } else {
816     return false;
817   }
818 }
819 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
820 // CHECK-FIXES: {{^}}  return O;{{$}}
821 
negated_explicit_bool(bool b)822 bool negated_explicit_bool(bool b) {
823   if (!b) {
824     return true;
825   } else {
826     return false;
827   }
828 }
829 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
830 // CHECK-FIXES: {{^}}  return !b;{{$}}
831 
bitwise_complement_conversion(int i)832 bool bitwise_complement_conversion(int i) {
833   if (~i) {
834     return true;
835   } else {
836     return false;
837   }
838 }
839 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
840 // CHECK-FIXES: {{^}}  return ~i != 0;{{$}}
841 
logical_or(bool a,bool b)842 bool logical_or(bool a, bool b) {
843   if (a || b) {
844     return true;
845   } else {
846     return false;
847   }
848 }
849 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
850 // CHECK-FIXES: {{^}}  return a || b;{{$}}
851 
logical_and(bool a,bool b)852 bool logical_and(bool a, bool b) {
853   if (a && b) {
854     return true;
855   } else {
856     return false;
857   }
858 }
859 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
860 // CHECK-FIXES: {{^}}  return a && b;{{$}}
861 
862 class Comparable
863 {
864 public:
operator ==(Comparable const & rhs)865   bool operator==(Comparable const &rhs) { return true; }
operator !=(Comparable const & rhs)866   bool operator!=(Comparable const &rhs) { return false; }
867 };
868 
comparable_objects()869 bool comparable_objects() {
870   Comparable c;
871   Comparable d;
872   if (c == d) {
873     return true;
874   } else {
875     return false;
876   }
877 }
878 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
879 // CHECK-FIXES: {{^}}  return c == d;{{$}}
880 
negated_comparable_objects()881 bool negated_comparable_objects() {
882   Comparable c;
883   Comparable d;
884   if (c == d) {
885     return false;
886   } else {
887     return true;
888   }
889 }
890 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
891 // CHECK-FIXES: {{^}}  return c != d;{{$}}
892 
893 struct X {
894   explicit operator bool();
895 };
896 
explicit_conversion_assignment(X x)897 void explicit_conversion_assignment(X x) {
898   bool y;
899   if (x) {
900     y = true;
901   } else {
902     y = false;
903   }
904 }
905 // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
906 // CHECK-FIXES: {{^  bool y;$}}
907 // CHECK-FIXES: {{^}}  y = static_cast<bool>(x);{{$}}
908 
ternary_integer_condition(int i)909 void ternary_integer_condition(int i) {
910   bool b = i ? true : false;
911 }
912 // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: {{.*}} in ternary expression result
913 // CHECK-FIXES: bool b = i != 0;{{$}}
914 
non_null_pointer_condition(int * p1)915 bool non_null_pointer_condition(int *p1) {
916   if (p1) {
917     return true;
918   } else {
919     return false;
920   }
921 }
922 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
923 // CHECK-FIXES: return p1 != nullptr;{{$}}
924 
null_pointer_condition(int * p2)925 bool null_pointer_condition(int *p2) {
926   if (!p2) {
927     return true;
928   } else {
929     return false;
930   }
931 }
932 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
933 // CHECK-FIXES: return p2 == nullptr;{{$}}
934 
negated_non_null_pointer_condition(int * p3)935 bool negated_non_null_pointer_condition(int *p3) {
936   if (p3) {
937     return false;
938   } else {
939     return true;
940   }
941 }
942 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
943 // CHECK-FIXES: return p3 == nullptr;{{$}}
944 
negated_null_pointer_condition(int * p4)945 bool negated_null_pointer_condition(int *p4) {
946   if (!p4) {
947     return false;
948   } else {
949     return true;
950   }
951 }
952 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
953 // CHECK-FIXES: return p4 != nullptr;{{$}}
954 
comments_in_the_middle(bool b)955 bool comments_in_the_middle(bool b) {
956   if (b) {
957     return true;
958   } else {
959     // something wicked this way comes
960     return false;
961   }
962 }
963 // CHECK-MESSAGES: :[[@LINE-6]]:12: warning: {{.*}} in conditional return
964 // CHECK-FIXES: {{^}}  if (b) {
965 // CHECK-FIXES: // something wicked this way comes{{$}}
966 
preprocessor_in_the_middle(bool b)967 bool preprocessor_in_the_middle(bool b) {
968   if (b) {
969     return true;
970   } else {
971 #define SOMETHING_WICKED false
972     return false;
973   }
974 }
975 // CHECK-MESSAGES: :[[@LINE-6]]:12: warning: {{.*}} in conditional return
976 // CHECK-FIXES: {{^}}  if (b) {
977 // CHECK-FIXES: {{^}}#define SOMETHING_WICKED false
978 
integer_not_zero(int i)979 bool integer_not_zero(int i) {
980   if (i) {
981     return false;
982   } else {
983     return true;
984   }
985 }
986 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
987 // CHECK-FIXES: {{^}}  return i == 0;{{$}}
988 
989 class A {
990 public:
991     int m;
992 };
993 
member_pointer_nullptr(int A::* p)994 bool member_pointer_nullptr(int A::*p) {
995   if (p) {
996     return true;
997   } else {
998     return false;
999   }
1000 }
1001 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
1002 // CHECK-FIXES: return p != nullptr;{{$}}
1003 
integer_member_implicit_cast(A * p)1004 bool integer_member_implicit_cast(A *p) {
1005   if (p->m) {
1006     return true;
1007   } else {
1008     return false;
1009   }
1010 }
1011 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
1012 // CHECK-FIXES: return p->m != 0;{{$}}
1013 
operator !=(const A &,const A &)1014 bool operator!=(const A&, const A&) { return false; }
expr_with_cleanups(A & S)1015 bool expr_with_cleanups(A &S) {
1016   if (S != (A)S)
1017     return false;
1018 
1019   return true;
1020 }
1021 // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
1022 // CHECK-FIXES: S == (A)S;{{$}}
1023 
1024 template <bool B>
ignoreInstantiations()1025 void ignoreInstantiations() {
1026   if (B) {
1027     return;
1028   } else {
1029     return;
1030   }
1031 }
1032 
instantiate()1033 void instantiate() {
1034   // Just make sure the check isn't fooled by template instantiations.
1035   ignoreInstantiations<true>();
1036   ignoreInstantiations<false>();
1037 }
1038