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