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_then_expr(int i,int j)356 bool conditional_return_statements_then_expr(int i, int j) {
357   if (i == j) return (i == 0); else return false;
358 }
359 
conditional_return_statements_else_expr(int i,int j)360 bool conditional_return_statements_else_expr(int i, int j) {
361   if (i == j) return true; else return (i == 0);
362 }
363 
negated_conditional_return_statements(int i)364 bool negated_conditional_return_statements(int i) {
365   if (i == 0) return false; else return true;
366 }
367 // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}} in conditional return statement
368 // CHECK-FIXES:      {{^}}  return i != 0;{{$}}
369 // CHECK-FIXES-NEXT: {{^}$}}
370 
negative_condition_conditional_return_statement(int i)371 bool negative_condition_conditional_return_statement(int i) {
372   if (!(i == 0)) return false; else return true;
373 }
374 // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: {{.*}} in conditional return statement
375 // CHECK-FIXES:      {{^}}  return i == 0;{{$}}
376 // CHECK-FIXES-NEXT: {{^}$}}
377 
conditional_compound_return_statements(int i)378 bool conditional_compound_return_statements(int i) {
379   if (i == 1) {
380     return true;
381   } else {
382     return false;
383   }
384 }
385 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return statement
386 // CHECK-FIXES:      {{^}}bool conditional_compound_return_statements(int i) {{{$}}
387 // CHECK-FIXES-NEXT: {{^}}  return i == 1;{{$}}
388 // CHECK-FIXES-NEXT: {{^}$}}
389 
negated_conditional_compound_return_statements(int i)390 bool negated_conditional_compound_return_statements(int i) {
391   if (i == 1) {
392     return false;
393   } else {
394     return true;
395   }
396 }
397 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return statement
398 // CHECK-FIXES:      {{^}}bool negated_conditional_compound_return_statements(int i) {{{$}}
399 // CHECK-FIXES-NEXT: {{^}}  return i != 1;{{$}}
400 // CHECK-FIXES-NEXT: {{^}$}}
401 
conditional_return_statements_side_effects_then(int i)402 bool conditional_return_statements_side_effects_then(int i) {
403   if (i == 2) {
404     macros_and_constexprs();
405     return true;
406   } else
407     return false;
408 }
409 
negated_conditional_return_statements_side_effects_then(int i)410 bool negated_conditional_return_statements_side_effects_then(int i) {
411   if (i == 2) {
412     macros_and_constexprs();
413     return false;
414   } else
415     return true;
416 }
417 
conditional_return_statements_side_effects_else(int i)418 bool conditional_return_statements_side_effects_else(int i) {
419   if (i == 2)
420     return true;
421   else {
422     macros_and_constexprs();
423     return false;
424   }
425 }
426 
negated_conditional_return_statements_side_effects_else(int i)427 bool negated_conditional_return_statements_side_effects_else(int i) {
428   if (i == 2)
429     return false;
430   else {
431     macros_and_constexprs();
432     return true;
433   }
434 }
435 
lambda_conditional_return_statements()436 void lambda_conditional_return_statements() {
437   auto lambda = [](int n) -> bool { if (n > 0) return true; else return false; };
438   // CHECK-MESSAGES: :[[@LINE-1]]:55: warning: {{.*}} in conditional return statement
439   // CHECK-FIXES: {{^}}  auto lambda = [](int n) -> bool { return n > 0; };{{$}}
440 
441   auto lambda2 = [](int n) -> bool {
442     if (n > 0) {
443         return true;
444     } else {
445         return false;
446     }
447   };
448   // CHECK-MESSAGES: :[[@LINE-5]]:16: warning: {{.*}} in conditional return statement
449   // CHECK-FIXES:      {{^}}  auto lambda2 = [](int n) -> bool {{{$}}
450   // CHECK-FIXES-NEXT: {{^}}    return n > 0;{{$}}
451   // CHECK-FIXES-NEXT: {{^}}  };{{$}}
452 
453   auto lambda3 = [](int n) -> bool { if (n > 0) {macros_and_constexprs(); return true; } else return false; };
454 
455   auto lambda4 = [](int n) -> bool {
456     if (n > 0)
457         return true;
458     else {
459         macros_and_constexprs();
460         return false;
461     }
462   };
463 
464   auto lambda5 = [](int n) -> bool { if (n > 0) return false; else return true; };
465   // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: {{.*}} in conditional return statement
466   // CHECK-FIXES: {{^}}  auto lambda5 = [](int n) -> bool { return n <= 0; };{{$}}
467 
468   auto lambda6 = [](int n) -> bool {
469     if (n > 0) {
470         return false;
471     } else {
472         return true;
473     }
474   };
475   // CHECK-MESSAGES: :[[@LINE-5]]:16: warning: {{.*}} in conditional return statement
476   // CHECK-FIXES:      {{^}}  auto lambda6 = [](int n) -> bool {{{$}}
477   // CHECK-FIXES-NEXT: {{^}}    return n <= 0;{{$}}
478   // CHECK-FIXES-NEXT: {{^}}  };{{$}}
479 }
480 
condition_variable_return_stmt(int i)481 bool condition_variable_return_stmt(int i) {
482   // Unchanged: condition variable.
483   if (bool Res = i == 0)
484     return true;
485   else
486     return false;
487 }
488 
simple_conditional_assignment_statements(int i)489 void simple_conditional_assignment_statements(int i) {
490   bool b;
491   if (i > 10)
492     b = true;
493   else
494     b = false;
495   bool bb = false;
496   // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in conditional assignment
497   // CHECK-FIXES: bool b;
498   // CHECK-FIXES: {{^  }}b = i > 10;{{$}}
499   // CHECK-FIXES: bool bb = false;
500 
501   bool c;
502   if (i > 20)
503     c = false;
504   else
505     c = true;
506   bool c2 = false;
507   // CHECK-MESSAGES: :[[@LINE-4]]:9: warning: {{.*}} in conditional assignment
508   // CHECK-FIXES: bool c;
509   // CHECK-FIXES: {{^  }}c = i <= 20;{{$}}
510   // CHECK-FIXES: bool c2 = false;
511 
512   // Unchanged: different variables.
513   bool b2;
514   if (i > 12)
515     b = true;
516   else
517     b2 = false;
518 
519   // Unchanged: no else statement.
520   bool b3;
521   if (i > 15)
522     b3 = true;
523 
524   // Unchanged: not boolean assignment.
525   int j;
526   if (i > 17)
527     j = 10;
528   else
529     j = 20;
530 
531   // Unchanged: different variables assigned.
532   int k = 0;
533   bool b4 = false;
534   if (i > 10)
535     b4 = true;
536   else
537     k = 10;
538 }
539 
complex_conditional_assignment_statements(int i)540 void complex_conditional_assignment_statements(int i) {
541   bool d;
542   if (i > 30) {
543     d = true;
544   } else {
545     d = false;
546   }
547   d = false;
548   // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
549   // CHECK-FIXES: bool d;
550   // CHECK-FIXES: {{^  }}d = i > 30;{{$}}
551   // CHECK-FIXES: d = false;
552 
553   bool e;
554   if (i > 40) {
555     e = false;
556   } else {
557     e = true;
558   }
559   e = false;
560   // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
561   // CHECK-FIXES: bool e;
562   // CHECK-FIXES: {{^  }}e = i <= 40;{{$}}
563   // CHECK-FIXES: e = false;
564 
565   // Unchanged: no else statement.
566   bool b3;
567   if (i > 15) {
568     b3 = true;
569   }
570 
571   // Unchanged: not a boolean assignment.
572   int j;
573   if (i > 17) {
574     j = 10;
575   } else {
576     j = 20;
577   }
578 
579   // Unchanged: multiple statements.
580   bool f;
581   if (j > 10) {
582     j = 10;
583     f = true;
584   } else {
585     j = 20;
586     f = false;
587   }
588 
589   // Unchanged: multiple statements.
590   bool g;
591   if (j > 10)
592     g = true;
593   else {
594     j = 20;
595     g = false;
596   }
597 
598   // Unchanged: multiple statements.
599   bool h;
600   if (j > 10) {
601     j = 10;
602     h = true;
603   } else
604     h = false;
605 
606   // Unchanged: condition variable.
607   bool k;
608   if (bool Res = j > 10)
609     k = true;
610   else
611     k = false;
612 }
613 
614 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_conditional_compound_return(int i)615 bool chained_conditional_compound_return(int i) {
616   if (i < 0) {
617     return true;
618   } else if (i < 10) {
619     return false;
620   } else if (i > 20) {
621     return true;
622   } else {
623     return false;
624   }
625 }
626 
627 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_conditional_return(int i)628 bool chained_conditional_return(int i) {
629   if (i < 0)
630     return true;
631   else if (i < 10)
632     return false;
633   else if (i > 20)
634     return true;
635   else
636     return false;
637 }
638 
639 // Unchanged: chained assignments, but ChainedConditionalAssignment not set.
chained_conditional_compound_assignment(int i)640 void chained_conditional_compound_assignment(int i) {
641   bool b;
642   if (i < 0) {
643     b = true;
644   } else if (i < 10) {
645     b = false;
646   } else if (i > 20) {
647     b = true;
648   } else {
649     b = false;
650   }
651 }
652 
653 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_conditional_assignment(int i)654 void chained_conditional_assignment(int i) {
655   bool b;
656   if (i < 0)
657     b = true;
658   else if (i < 10)
659     b = false;
660   else if (i > 20)
661     b = true;
662   else
663     b = false;
664 }
665 
666 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_simple_if_return_negated(int i)667 bool chained_simple_if_return_negated(int i) {
668   if (i < 5)
669     return false;
670   if (i > 10)
671     return false;
672   return true;
673 }
674 
675 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
complex_chained_if_return_return(int i)676 bool complex_chained_if_return_return(int i) {
677   if (i < 5) {
678     return true;
679   }
680   if (i > 10) {
681     return true;
682   }
683   return false;
684 }
685 
686 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
complex_chained_if_return_return_negated(int i)687 bool complex_chained_if_return_return_negated(int i) {
688   if (i < 5) {
689     return false;
690   }
691   if (i > 10) {
692     return false;
693   }
694   return true;
695 }
696 
697 // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_simple_if_return(int i)698 bool chained_simple_if_return(int i) {
699   if (i < 5)
700     return true;
701   if (i > 10)
702     return true;
703   return false;
704 }
705 
simple_if_return_return(int i)706 bool simple_if_return_return(int i) {
707   if (i > 10)
708     return true;
709   return false;
710 }
711 // CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
712 // CHECK-FIXES: {{^}}bool simple_if_return_return(int i) {{{$}}
713 // CHECK-FIXES: {{^  return i > 10;$}}
714 // CHECK-FIXES: {{^}$}}
715 
simple_if_return_return_negated(int i)716 bool simple_if_return_return_negated(int i) {
717   if (i > 10)
718     return false;
719   return true;
720 }
721 // CHECK-MESSAGES: :[[@LINE-3]]:12: warning: {{.*}} in conditional return
722 // CHECK-FIXES: {{^}}bool simple_if_return_return_negated(int i) {{{$}}
723 // CHECK-FIXES: {{^  return i <= 10;$}}
724 // CHECK-FIXES: {{^}$}}
725 
complex_if_return_return(int i)726 bool complex_if_return_return(int i) {
727   if (i > 10) {
728     return true;
729   }
730   return false;
731 }
732 // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
733 // CHECK-FIXES: {{^}}bool complex_if_return_return(int i) {{{$}}
734 // CHECK-FIXES: {{^  return i > 10;$}}
735 // CHECK-FIXES: {{^}$}}
736 
complex_if_return_return_negated(int i)737 bool complex_if_return_return_negated(int i) {
738   if (i > 10) {
739     return false;
740   }
741   return true;
742 }
743 // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
744 // CHECK-FIXES: {{^}}bool complex_if_return_return_negated(int i) {{{$}}
745 // CHECK-FIXES: {{^  return i <= 10;$}}
746 // CHECK-FIXES: {{^}$}}
747 
if_implicit_bool_expr(int i)748 bool if_implicit_bool_expr(int i) {
749   if (i & 1) {
750     return true;
751   } else {
752     return false;
753   }
754 }
755 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
756 // CHECK-FIXES: {{^}}  return (i & 1) != 0;{{$}}
757 
negated_if_implicit_bool_expr(int i)758 bool negated_if_implicit_bool_expr(int i) {
759   if (i - 1) {
760     return false;
761   } else {
762     return true;
763   }
764 }
765 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
766 // CHECK-FIXES: {{^}}  return (i - 1) == 0;{{$}}
767 
implicit_int(int i)768 bool implicit_int(int i) {
769   if (i) {
770     return true;
771   } else {
772     return false;
773   }
774 }
775 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
776 // CHECK-FIXES: {{^}}  return i != 0;{{$}}
777 
explicit_bool(bool b)778 bool explicit_bool(bool b) {
779   if (b) {
780     return true;
781   } else {
782     return false;
783   }
784 }
785 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
786 // CHECK-FIXES: {{^}}  return b;{{$}}
787 
788 class Implicit {
789 public:
operator bool()790   operator bool() {
791     return true;
792   }
793 };
794 
object_bool_implicit_conversion(Implicit O)795 bool object_bool_implicit_conversion(Implicit O) {
796   if (O) {
797     return true;
798   } else {
799     return false;
800   }
801 }
802 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
803 // CHECK-FIXES: {{^}}  return O;{{$}}
804 
negated_explicit_bool(bool b)805 bool negated_explicit_bool(bool b) {
806   if (!b) {
807     return true;
808   } else {
809     return false;
810   }
811 }
812 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
813 // CHECK-FIXES: {{^}}  return !b;{{$}}
814 
bitwise_complement_conversion(int i)815 bool bitwise_complement_conversion(int i) {
816   if (~i) {
817     return true;
818   } else {
819     return false;
820   }
821 }
822 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
823 // CHECK-FIXES: {{^}}  return ~i != 0;{{$}}
824 
logical_or(bool a,bool b)825 bool logical_or(bool a, bool b) {
826   if (a || b) {
827     return true;
828   } else {
829     return false;
830   }
831 }
832 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
833 // CHECK-FIXES: {{^}}  return a || b;{{$}}
834 
logical_and(bool a,bool b)835 bool logical_and(bool a, bool b) {
836   if (a && b) {
837     return true;
838   } else {
839     return false;
840   }
841 }
842 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
843 // CHECK-FIXES: {{^}}  return a && b;{{$}}
844 
845 class Comparable
846 {
847 public:
operator ==(Comparable const & rhs)848   bool operator==(Comparable const &rhs) { return true; }
operator !=(Comparable const & rhs)849   bool operator!=(Comparable const &rhs) { return false; }
850 };
851 
comparable_objects()852 bool comparable_objects() {
853   Comparable c;
854   Comparable d;
855   if (c == d) {
856     return true;
857   } else {
858     return false;
859   }
860 }
861 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
862 // CHECK-FIXES: {{^}}  return c == d;{{$}}
863 
negated_comparable_objects()864 bool negated_comparable_objects() {
865   Comparable c;
866   Comparable d;
867   if (c == d) {
868     return false;
869   } else {
870     return true;
871   }
872 }
873 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
874 // CHECK-FIXES: {{^}}  return c != d;{{$}}
875 
876 struct X {
877   explicit operator bool();
878 };
879 
explicit_conversion_assignment(X x)880 void explicit_conversion_assignment(X x) {
881   bool y;
882   if (x) {
883     y = true;
884   } else {
885     y = false;
886   }
887 }
888 // CHECK-MESSAGES: :[[@LINE-5]]:9: warning: {{.*}} in conditional assignment
889 // CHECK-FIXES: {{^  bool y;$}}
890 // CHECK-FIXES: {{^}}  y = static_cast<bool>(x);{{$}}
891 
ternary_integer_condition(int i)892 void ternary_integer_condition(int i) {
893   bool b = i ? true : false;
894 }
895 // CHECK-MESSAGES: :[[@LINE-2]]:16: warning: {{.*}} in ternary expression result
896 // CHECK-FIXES: bool b = i != 0;{{$}}
897 
non_null_pointer_condition(int * p1)898 bool non_null_pointer_condition(int *p1) {
899   if (p1) {
900     return true;
901   } else {
902     return false;
903   }
904 }
905 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
906 // CHECK-FIXES: return p1 != nullptr;{{$}}
907 
null_pointer_condition(int * p2)908 bool null_pointer_condition(int *p2) {
909   if (!p2) {
910     return true;
911   } else {
912     return false;
913   }
914 }
915 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
916 // CHECK-FIXES: return p2 == nullptr;{{$}}
917 
negated_non_null_pointer_condition(int * p3)918 bool negated_non_null_pointer_condition(int *p3) {
919   if (p3) {
920     return false;
921   } else {
922     return true;
923   }
924 }
925 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
926 // CHECK-FIXES: return p3 == nullptr;{{$}}
927 
negated_null_pointer_condition(int * p4)928 bool negated_null_pointer_condition(int *p4) {
929   if (!p4) {
930     return false;
931   } else {
932     return true;
933   }
934 }
935 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
936 // CHECK-FIXES: return p4 != nullptr;{{$}}
937 
comments_in_the_middle(bool b)938 bool comments_in_the_middle(bool b) {
939   if (b) {
940     return true;
941   } else {
942     // something wicked this way comes
943     return false;
944   }
945 }
946 // CHECK-MESSAGES: :[[@LINE-6]]:12: warning: {{.*}} in conditional return
947 // CHECK-FIXES: {{^}}  if (b) {
948 // CHECK-FIXES: // something wicked this way comes{{$}}
949 
preprocessor_in_the_middle(bool b)950 bool preprocessor_in_the_middle(bool b) {
951   if (b) {
952     return true;
953   } else {
954 #define SOMETHING_WICKED false
955     return false;
956   }
957 }
958 // CHECK-MESSAGES: :[[@LINE-6]]:12: warning: {{.*}} in conditional return
959 // CHECK-FIXES: {{^}}  if (b) {
960 // CHECK-FIXES: {{^}}#define SOMETHING_WICKED false
961 
integer_not_zero(int i)962 bool integer_not_zero(int i) {
963   if (i) {
964     return false;
965   } else {
966     return true;
967   }
968 }
969 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
970 // CHECK-FIXES: {{^}}  return i == 0;{{$}}
971 
972 class A {
973 public:
974     int m;
975 };
976 
member_pointer_nullptr(int A::* p)977 bool member_pointer_nullptr(int A::*p) {
978   if (p) {
979     return true;
980   } else {
981     return false;
982   }
983 }
984 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
985 // CHECK-FIXES: return p != nullptr;{{$}}
986 
integer_member_implicit_cast(A * p)987 bool integer_member_implicit_cast(A *p) {
988   if (p->m) {
989     return true;
990   } else {
991     return false;
992   }
993 }
994 // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
995 // CHECK-FIXES: return p->m != 0;{{$}}
996 
operator !=(const A &,const A &)997 bool operator!=(const A&, const A&) { return false; }
expr_with_cleanups(A & S)998 bool expr_with_cleanups(A &S) {
999   if (S != (A)S)
1000     return false;
1001 
1002   return true;
1003 }
1004 // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
1005 // CHECK-FIXES: S == (A)S;{{$}}
1006 
1007 template <bool B>
ignoreInstantiations()1008 void ignoreInstantiations() {
1009   if (B) {
1010     return;
1011   } else {
1012     return;
1013   }
1014 }
1015 
instantiate()1016 void instantiate() {
1017   // Just make sure the check isn't fooled by template instantiations.
1018   ignoreInstantiations<true>();
1019   ignoreInstantiations<false>();
1020 }
1021