1*01025dddSPiotr Zegar // RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t
2*01025dddSPiotr Zegar 
3*01025dddSPiotr Zegar class A {
4*01025dddSPiotr Zegar public:
5*01025dddSPiotr Zegar   int m;
6*01025dddSPiotr Zegar };
7*01025dddSPiotr Zegar 
8*01025dddSPiotr Zegar struct S {
SS9*01025dddSPiotr Zegar   S() : m_ar(s_a) {}
10*01025dddSPiotr Zegar 
11*01025dddSPiotr Zegar   void operator_equals();
12*01025dddSPiotr Zegar   void operator_or();
13*01025dddSPiotr Zegar   void operator_and();
14*01025dddSPiotr Zegar   void ternary_operator();
15*01025dddSPiotr Zegar   void operator_not_equal();
16*01025dddSPiotr Zegar   void simple_conditional_assignment_statements();
17*01025dddSPiotr Zegar   void complex_conditional_assignment_statements();
18*01025dddSPiotr Zegar   void chained_conditional_assignment();
19*01025dddSPiotr Zegar   bool non_null_pointer_condition();
20*01025dddSPiotr Zegar   bool null_pointer_condition();
21*01025dddSPiotr Zegar   bool negated_non_null_pointer_condition();
22*01025dddSPiotr Zegar   bool negated_null_pointer_condition();
23*01025dddSPiotr Zegar   bool integer_not_zero();
24*01025dddSPiotr Zegar   bool member_pointer_nullptr();
25*01025dddSPiotr Zegar   bool integer_member_implicit_cast();
26*01025dddSPiotr Zegar   bool expr_with_cleanups();
27*01025dddSPiotr Zegar 
28*01025dddSPiotr Zegar   bool m_b1 = false;
29*01025dddSPiotr Zegar   bool m_b2 = false;
30*01025dddSPiotr Zegar   bool m_b3 = false;
31*01025dddSPiotr Zegar   bool m_b4 = false;
32*01025dddSPiotr Zegar   int *m_p = nullptr;
33*01025dddSPiotr Zegar   int A::*m_m = nullptr;
34*01025dddSPiotr Zegar   int m_i = 0;
35*01025dddSPiotr Zegar   A *m_a = nullptr;
36*01025dddSPiotr Zegar   static A s_a;
37*01025dddSPiotr Zegar   A &m_ar;
38*01025dddSPiotr Zegar };
39*01025dddSPiotr Zegar 
operator_equals()40*01025dddSPiotr Zegar void S::operator_equals() {
41*01025dddSPiotr Zegar   int i = 0;
42*01025dddSPiotr Zegar   m_b1 = (i > 2);
43*01025dddSPiotr Zegar   if (m_b1 == true) {
44*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
45*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(m_b1\) {$}}
46*01025dddSPiotr Zegar     i = 5;
47*01025dddSPiotr Zegar   } else {
48*01025dddSPiotr Zegar     i = 6;
49*01025dddSPiotr Zegar   }
50*01025dddSPiotr Zegar   m_b2 = (i > 4);
51*01025dddSPiotr Zegar   if (m_b2 == false) {
52*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
53*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(!m_b2\) {$}}
54*01025dddSPiotr Zegar     i = 7;
55*01025dddSPiotr Zegar   } else {
56*01025dddSPiotr Zegar     i = 9;
57*01025dddSPiotr Zegar   }
58*01025dddSPiotr Zegar   m_b3 = (i > 6);
59*01025dddSPiotr Zegar   if (true == m_b3) {
60*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
61*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(m_b3\) {$}}
62*01025dddSPiotr Zegar     i = 10;
63*01025dddSPiotr Zegar   } else {
64*01025dddSPiotr Zegar     i = 11;
65*01025dddSPiotr Zegar   }
66*01025dddSPiotr Zegar   m_b4 = (i > 8);
67*01025dddSPiotr Zegar   if (false == m_b4) {
68*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
69*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(!m_b4\) {$}}
70*01025dddSPiotr Zegar     i = 12;
71*01025dddSPiotr Zegar   } else {
72*01025dddSPiotr Zegar     i = 13;
73*01025dddSPiotr Zegar   }
74*01025dddSPiotr Zegar }
75*01025dddSPiotr Zegar 
operator_or()76*01025dddSPiotr Zegar void S::operator_or() {
77*01025dddSPiotr Zegar   int i = 0;
78*01025dddSPiotr Zegar   m_b1 = (i > 10);
79*01025dddSPiotr Zegar   if (m_b1 || false) {
80*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
81*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(m_b1\) {$}}
82*01025dddSPiotr Zegar     i = 14;
83*01025dddSPiotr Zegar   } else {
84*01025dddSPiotr Zegar     i = 15;
85*01025dddSPiotr Zegar   }
86*01025dddSPiotr Zegar   m_b2 = (i > 10);
87*01025dddSPiotr Zegar   if (m_b2 || true) {
88*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
89*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(true\) {$}}
90*01025dddSPiotr Zegar     i = 16;
91*01025dddSPiotr Zegar   } else {
92*01025dddSPiotr Zegar     i = 17;
93*01025dddSPiotr Zegar   }
94*01025dddSPiotr Zegar   m_b3 = (i > 10);
95*01025dddSPiotr Zegar   if (false || m_b3) {
96*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
97*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(m_b3\) {$}}
98*01025dddSPiotr Zegar     i = 18;
99*01025dddSPiotr Zegar   } else {
100*01025dddSPiotr Zegar     i = 19;
101*01025dddSPiotr Zegar   }
102*01025dddSPiotr Zegar   m_b4 = (i > 10);
103*01025dddSPiotr Zegar   if (true || m_b4) {
104*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
105*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(true\) {$}}
106*01025dddSPiotr Zegar     i = 20;
107*01025dddSPiotr Zegar   } else {
108*01025dddSPiotr Zegar     i = 21;
109*01025dddSPiotr Zegar   }
110*01025dddSPiotr Zegar }
111*01025dddSPiotr Zegar 
operator_and()112*01025dddSPiotr Zegar void S::operator_and() {
113*01025dddSPiotr Zegar   int i = 0;
114*01025dddSPiotr Zegar   m_b1 = (i > 20);
115*01025dddSPiotr Zegar   if (m_b1 && false) {
116*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
117*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(false\) {$}}
118*01025dddSPiotr Zegar     i = 22;
119*01025dddSPiotr Zegar   } else {
120*01025dddSPiotr Zegar     i = 23;
121*01025dddSPiotr Zegar   }
122*01025dddSPiotr Zegar   m_b2 = (i > 20);
123*01025dddSPiotr Zegar   if (m_b2 && true) {
124*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
125*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(m_b2\) {$}}
126*01025dddSPiotr Zegar     i = 24;
127*01025dddSPiotr Zegar   } else {
128*01025dddSPiotr Zegar     i = 25;
129*01025dddSPiotr Zegar   }
130*01025dddSPiotr Zegar   m_b3 = (i > 20);
131*01025dddSPiotr Zegar   if (false && m_b3) {
132*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
133*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(false\) {$}}
134*01025dddSPiotr Zegar     i = 26;
135*01025dddSPiotr Zegar   } else {
136*01025dddSPiotr Zegar     i = 27;
137*01025dddSPiotr Zegar   }
138*01025dddSPiotr Zegar   m_b4 = (i > 20);
139*01025dddSPiotr Zegar   if (true && m_b4) {
140*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
141*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(m_b4\) {$}}
142*01025dddSPiotr Zegar     i = 28;
143*01025dddSPiotr Zegar   } else {
144*01025dddSPiotr Zegar     i = 29;
145*01025dddSPiotr Zegar   }
146*01025dddSPiotr Zegar }
147*01025dddSPiotr Zegar 
ternary_operator()148*01025dddSPiotr Zegar void S::ternary_operator() {
149*01025dddSPiotr Zegar   int i = 0;
150*01025dddSPiotr Zegar   m_b1 = (i > 20) ? true : false;
151*01025dddSPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in ternary expression result
152*01025dddSPiotr Zegar   // CHECK-FIXES: {{^  m_b1 = i > 20;$}}
153*01025dddSPiotr Zegar 
154*01025dddSPiotr Zegar   m_b2 = (i > 20) ? false : true;
155*01025dddSPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}} in ternary expression result
156*01025dddSPiotr Zegar   // CHECK-FIXES: {{^  m_b2 = i <= 20;$}}
157*01025dddSPiotr Zegar 
158*01025dddSPiotr Zegar   m_b3 = ((i > 20)) ? false : true;
159*01025dddSPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: {{.*}} in ternary expression result
160*01025dddSPiotr Zegar   // CHECK-FIXES: {{^  m_b3 = i <= 20;$}}
161*01025dddSPiotr Zegar }
162*01025dddSPiotr Zegar 
operator_not_equal()163*01025dddSPiotr Zegar void S::operator_not_equal() {
164*01025dddSPiotr Zegar   int i = 0;
165*01025dddSPiotr Zegar   m_b1 = (i > 20);
166*01025dddSPiotr Zegar   if (false != m_b1) {
167*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
168*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(m_b1\) {$}}
169*01025dddSPiotr Zegar     i = 30;
170*01025dddSPiotr Zegar   } else {
171*01025dddSPiotr Zegar     i = 31;
172*01025dddSPiotr Zegar   }
173*01025dddSPiotr Zegar   m_b2 = (i > 20);
174*01025dddSPiotr Zegar   if (true != m_b2) {
175*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: {{.*}} to boolean operator
176*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(!m_b2\) {$}}
177*01025dddSPiotr Zegar     i = 32;
178*01025dddSPiotr Zegar   } else {
179*01025dddSPiotr Zegar     i = 33;
180*01025dddSPiotr Zegar   }
181*01025dddSPiotr Zegar   m_b3 = (i > 20);
182*01025dddSPiotr Zegar   if (m_b3 != false) {
183*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
184*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(m_b3\) {$}}
185*01025dddSPiotr Zegar     i = 34;
186*01025dddSPiotr Zegar   } else {
187*01025dddSPiotr Zegar     i = 35;
188*01025dddSPiotr Zegar   }
189*01025dddSPiotr Zegar   m_b4 = (i > 20);
190*01025dddSPiotr Zegar   if (m_b4 != true) {
191*01025dddSPiotr Zegar     // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}} to boolean operator
192*01025dddSPiotr Zegar     // CHECK-FIXES: {{^  if \(!m_b4\) {$}}
193*01025dddSPiotr Zegar     i = 36;
194*01025dddSPiotr Zegar   } else {
195*01025dddSPiotr Zegar     i = 37;
196*01025dddSPiotr Zegar   }
197*01025dddSPiotr Zegar }
198*01025dddSPiotr Zegar 
simple_conditional_assignment_statements()199*01025dddSPiotr Zegar void S::simple_conditional_assignment_statements() {
200*01025dddSPiotr Zegar   if (m_i > 10)
201*01025dddSPiotr Zegar     m_b1 = true;
202*01025dddSPiotr Zegar   else
203*01025dddSPiotr Zegar     m_b1 = false;
204*01025dddSPiotr Zegar   bool bb = false;
205*01025dddSPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional assignment
206*01025dddSPiotr Zegar   // CHECK-FIXES: {{^  }}m_b1 = m_i > 10;{{$}}
207*01025dddSPiotr Zegar   // CHECK-FIXES: bool bb = false;
208*01025dddSPiotr Zegar 
209*01025dddSPiotr Zegar   if (m_i > 20)
210*01025dddSPiotr Zegar     m_b2 = false;
211*01025dddSPiotr Zegar   else
212*01025dddSPiotr Zegar     m_b2 = true;
213*01025dddSPiotr Zegar   bool c2 = false;
214*01025dddSPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional assignment
215*01025dddSPiotr Zegar   // CHECK-FIXES: {{^  }}m_b2 = m_i <= 20;{{$}}
216*01025dddSPiotr Zegar   // CHECK-FIXES: bool c2 = false;
217*01025dddSPiotr Zegar 
218*01025dddSPiotr Zegar   // Unchanged: different variables.
219*01025dddSPiotr Zegar   if (m_i > 12)
220*01025dddSPiotr Zegar     m_b1 = true;
221*01025dddSPiotr Zegar   else
222*01025dddSPiotr Zegar     m_b2 = false;
223*01025dddSPiotr Zegar 
224*01025dddSPiotr Zegar   // Unchanged: no else statement.
225*01025dddSPiotr Zegar   if (m_i > 15)
226*01025dddSPiotr Zegar     m_b3 = true;
227*01025dddSPiotr Zegar 
228*01025dddSPiotr Zegar   // Unchanged: not boolean assignment.
229*01025dddSPiotr Zegar   int j;
230*01025dddSPiotr Zegar   if (m_i > 17)
231*01025dddSPiotr Zegar     j = 10;
232*01025dddSPiotr Zegar   else
233*01025dddSPiotr Zegar     j = 20;
234*01025dddSPiotr Zegar 
235*01025dddSPiotr Zegar   // Unchanged: different variables assigned.
236*01025dddSPiotr Zegar   int k = 0;
237*01025dddSPiotr Zegar   m_b4 = false;
238*01025dddSPiotr Zegar   if (m_i > 10)
239*01025dddSPiotr Zegar     m_b4 = true;
240*01025dddSPiotr Zegar   else
241*01025dddSPiotr Zegar     k = 10;
242*01025dddSPiotr Zegar }
243*01025dddSPiotr Zegar 
complex_conditional_assignment_statements()244*01025dddSPiotr Zegar void S::complex_conditional_assignment_statements() {
245*01025dddSPiotr Zegar   if (m_i > 30) {
246*01025dddSPiotr Zegar     m_b1 = true;
247*01025dddSPiotr Zegar   } else {
248*01025dddSPiotr Zegar     m_b1 = false;
249*01025dddSPiotr Zegar   }
250*01025dddSPiotr Zegar   m_b1 = false;
251*01025dddSPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional assignment
252*01025dddSPiotr Zegar   // CHECK-FIXES: {{^  }}m_b1 = m_i > 30;{{$}}
253*01025dddSPiotr Zegar   // CHECK-FIXES: m_b1 = false;
254*01025dddSPiotr Zegar 
255*01025dddSPiotr Zegar   if (m_i > 40) {
256*01025dddSPiotr Zegar     m_b2 = false;
257*01025dddSPiotr Zegar   } else {
258*01025dddSPiotr Zegar     m_b2 = true;
259*01025dddSPiotr Zegar   }
260*01025dddSPiotr Zegar   m_b2 = false;
261*01025dddSPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional assignment
262*01025dddSPiotr Zegar   // CHECK-FIXES: {{^  }}m_b2 = m_i <= 40;{{$}}
263*01025dddSPiotr Zegar   // CHECK-FIXES: m_b2 = false;
264*01025dddSPiotr Zegar }
265*01025dddSPiotr Zegar 
266*01025dddSPiotr Zegar // Unchanged: chained return statements, but ChainedConditionalReturn not set.
chained_conditional_assignment()267*01025dddSPiotr Zegar void S::chained_conditional_assignment() {
268*01025dddSPiotr Zegar   if (m_i < 0)
269*01025dddSPiotr Zegar     m_b1 = true;
270*01025dddSPiotr Zegar   else if (m_i < 10)
271*01025dddSPiotr Zegar     m_b1 = false;
272*01025dddSPiotr Zegar   else if (m_i > 20)
273*01025dddSPiotr Zegar     m_b1 = true;
274*01025dddSPiotr Zegar   else
275*01025dddSPiotr Zegar     m_b1 = false;
276*01025dddSPiotr Zegar }
277*01025dddSPiotr Zegar 
non_null_pointer_condition()278*01025dddSPiotr Zegar bool S::non_null_pointer_condition() {
279*01025dddSPiotr Zegar   if (m_p) {
280*01025dddSPiotr Zegar     return true;
281*01025dddSPiotr Zegar   } else {
282*01025dddSPiotr Zegar     return false;
283*01025dddSPiotr Zegar   }
284*01025dddSPiotr Zegar }
285*01025dddSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
286*01025dddSPiotr Zegar // CHECK-FIXES: return m_p != nullptr;{{$}}
287*01025dddSPiotr Zegar 
null_pointer_condition()288*01025dddSPiotr Zegar bool S::null_pointer_condition() {
289*01025dddSPiotr Zegar   if (!m_p) {
290*01025dddSPiotr Zegar     return true;
291*01025dddSPiotr Zegar   } else {
292*01025dddSPiotr Zegar     return false;
293*01025dddSPiotr Zegar   }
294*01025dddSPiotr Zegar }
295*01025dddSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
296*01025dddSPiotr Zegar // CHECK-FIXES: return m_p == nullptr;{{$}}
297*01025dddSPiotr Zegar 
negated_non_null_pointer_condition()298*01025dddSPiotr Zegar bool S::negated_non_null_pointer_condition() {
299*01025dddSPiotr Zegar   if (m_p) {
300*01025dddSPiotr Zegar     return false;
301*01025dddSPiotr Zegar   } else {
302*01025dddSPiotr Zegar     return true;
303*01025dddSPiotr Zegar   }
304*01025dddSPiotr Zegar }
305*01025dddSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
306*01025dddSPiotr Zegar // CHECK-FIXES: return m_p == nullptr;{{$}}
307*01025dddSPiotr Zegar 
negated_null_pointer_condition()308*01025dddSPiotr Zegar bool S::negated_null_pointer_condition() {
309*01025dddSPiotr Zegar   if (!m_p) {
310*01025dddSPiotr Zegar     return false;
311*01025dddSPiotr Zegar   } else {
312*01025dddSPiotr Zegar     return true;
313*01025dddSPiotr Zegar   }
314*01025dddSPiotr Zegar }
315*01025dddSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
316*01025dddSPiotr Zegar // CHECK-FIXES: return m_p != nullptr;{{$}}
317*01025dddSPiotr Zegar 
integer_not_zero()318*01025dddSPiotr Zegar bool S::integer_not_zero() {
319*01025dddSPiotr Zegar   if (m_i) {
320*01025dddSPiotr Zegar     return false;
321*01025dddSPiotr Zegar   } else {
322*01025dddSPiotr Zegar     return true;
323*01025dddSPiotr Zegar   }
324*01025dddSPiotr Zegar }
325*01025dddSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
326*01025dddSPiotr Zegar // CHECK-FIXES: {{^}}  return m_i == 0;{{$}}
327*01025dddSPiotr Zegar 
member_pointer_nullptr()328*01025dddSPiotr Zegar bool S::member_pointer_nullptr() {
329*01025dddSPiotr Zegar   if (m_m) {
330*01025dddSPiotr Zegar     return true;
331*01025dddSPiotr Zegar   } else {
332*01025dddSPiotr Zegar     return false;
333*01025dddSPiotr Zegar   }
334*01025dddSPiotr Zegar }
335*01025dddSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
336*01025dddSPiotr Zegar // CHECK-FIXES: return m_m != nullptr;{{$}}
337*01025dddSPiotr Zegar 
integer_member_implicit_cast()338*01025dddSPiotr Zegar bool S::integer_member_implicit_cast() {
339*01025dddSPiotr Zegar   if (m_a->m) {
340*01025dddSPiotr Zegar     return true;
341*01025dddSPiotr Zegar   } else {
342*01025dddSPiotr Zegar     return false;
343*01025dddSPiotr Zegar   }
344*01025dddSPiotr Zegar }
345*01025dddSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-5]]:12: warning: {{.*}} in conditional return
346*01025dddSPiotr Zegar // CHECK-FIXES: return m_a->m != 0;{{$}}
347*01025dddSPiotr Zegar 
operator !=(const A &,const A &)348*01025dddSPiotr Zegar bool operator!=(const A &, const A &) { return false; }
expr_with_cleanups()349*01025dddSPiotr Zegar bool S::expr_with_cleanups() {
350*01025dddSPiotr Zegar   if (m_ar != (A)m_ar)
351*01025dddSPiotr Zegar     return false;
352*01025dddSPiotr Zegar 
353*01025dddSPiotr Zegar   return true;
354*01025dddSPiotr Zegar }
355*01025dddSPiotr Zegar // CHECK-MESSAGES: :[[@LINE-4]]:12: warning: {{.*}} in conditional return
356*01025dddSPiotr Zegar // CHECK-FIXES: m_ar == (A)m_ar;{{$}}
357