1// RUN: %check_clang_tidy %s readability-simplify-boolean-expr %t
2
3class A {
4public:
5 int m;
6};
7
8struct S {
9 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
40void 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
76void 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
112void 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
148void 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
163void 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
199void 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
244void 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.
267void 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
278bool 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
288bool 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
298bool 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
308bool 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
318bool 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
328bool 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
338bool 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
348bool operator!=(const A &, const A &) { return false; }
349bool 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

source code of clang-tools-extra/test/clang-tidy/checkers/readability/simplify-boolean-expr-members.cpp