blob: 45bf64ccf9964b79acadaf1a2cea466281cfe314 [file] [log] [blame]
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +00001// RUN: %check_clang_tidy %s readability-implicit-bool-cast %t
2
Piotr Dziwinskidb9d1302015-10-25 15:47:21 +00003// We need NULL macro, but some buildbots don't like including <cstddef> header
4// This is a portable way of getting it to work
5#undef NULL
6#define NULL 0L
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +00007
8template<typename T>
9void functionTaking(T);
10
11struct Struct {
12 int member;
13};
14
15
16////////// Implicit cast from bool.
17
18void implicitCastFromBoolSimpleCases() {
19 bool boolean = true;
20
21 functionTaking<bool>(boolean);
22
23 functionTaking<int>(boolean);
24 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit cast bool -> 'int' [readability-implicit-bool-cast]
25 // CHECK-FIXES: functionTaking<int>(static_cast<int>(boolean));
26
27 functionTaking<unsigned long>(boolean);
28 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'unsigned long'
29 // CHECK-FIXES: functionTaking<unsigned long>(static_cast<unsigned long>(boolean));
30
31 functionTaking<char>(boolean);
32 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'char'
33 // CHECK-FIXES: functionTaking<char>(static_cast<char>(boolean));
34
35 functionTaking<float>(boolean);
36 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast bool -> 'float'
37 // CHECK-FIXES: functionTaking<float>(static_cast<float>(boolean));
38
39 functionTaking<double>(boolean);
40 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit cast bool -> 'double'
41 // CHECK-FIXES: functionTaking<double>(static_cast<double>(boolean));
42}
43
44float implicitCastFromBoolInReturnValue() {
45 bool boolean = false;
46 return boolean;
47 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast bool -> 'float'
48 // CHECK-FIXES: return static_cast<float>(boolean);
49}
50
51void implicitCastFromBoolInSingleBoolExpressions() {
52 bool boolean = true;
53
54 int integer = boolean - 3;
55 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit cast bool -> 'int'
56 // CHECK-FIXES: int integer = static_cast<int>(boolean) - 3;
57
58 float floating = boolean / 0.3f;
59 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'float'
60 // CHECK-FIXES: float floating = static_cast<float>(boolean) / 0.3f;
61
62 char character = boolean;
63 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'char'
64 // CHECK-FIXES: char character = static_cast<char>(boolean);
65}
66
67void implicitCastFromBoollInComplexBoolExpressions() {
68 bool boolean = true;
69 bool anotherBoolean = false;
70
71 int integer = boolean && anotherBoolean;
72 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit cast bool -> 'int'
73 // CHECK-FIXES: int integer = static_cast<int>(boolean && anotherBoolean);
74
75 unsigned long unsignedLong = (! boolean) + 4ul;
76 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast bool -> 'unsigned long'
77 // CHECK-FIXES: unsigned long unsignedLong = static_cast<unsigned long>(! boolean) + 4ul;
78
79 float floating = (boolean || anotherBoolean) * 0.3f;
80 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit cast bool -> 'float'
81 // CHECK-FIXES: float floating = static_cast<float>(boolean || anotherBoolean) * 0.3f;
82
83 double doubleFloating = (boolean && (anotherBoolean || boolean)) * 0.3;
84 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit cast bool -> 'double'
85 // CHECK-FIXES: double doubleFloating = static_cast<double>(boolean && (anotherBoolean || boolean)) * 0.3;
86}
87
88void implicitCastFromBoolLiterals() {
89 functionTaking<int>(true);
90 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit cast bool -> 'int'
91 // CHECK-FIXES: functionTaking<int>(1);
92
93 functionTaking<unsigned long>(false);
94 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast bool -> 'unsigned long'
95 // CHECK-FIXES: functionTaking<unsigned long>(0u);
96
Piotr Dziwinski9c5c7a62015-10-25 17:11:13 +000097 functionTaking<signed char>(true);
98 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: implicit cast bool -> 'signed char'
99 // CHECK-FIXES: functionTaking<signed char>(1);
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +0000100
101 functionTaking<float>(false);
102 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit cast bool -> 'float'
103 // CHECK-FIXES: functionTaking<float>(0.0f);
104
105 functionTaking<double>(true);
106 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: implicit cast bool -> 'double'
107 // CHECK-FIXES: functionTaking<double>(1.0);
108}
109
110void implicitCastFromBoolInComparisons() {
111 bool boolean = true;
112 int integer = 0;
113
114 functionTaking<bool>(boolean == integer);
115 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast bool -> 'int'
116 // CHECK-FIXES: functionTaking<bool>(static_cast<int>(boolean) == integer);
117
118 functionTaking<bool>(integer != boolean);
119 // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: implicit cast bool -> 'int'
120 // CHECK-FIXES: functionTaking<bool>(integer != static_cast<int>(boolean));
121}
122
123void ignoreBoolComparisons() {
124 bool boolean = true;
125 bool anotherBoolean = false;
126
127 functionTaking<bool>(boolean == anotherBoolean);
128 functionTaking<bool>(boolean != anotherBoolean);
129}
130
131void ignoreExplicitCastsFromBool() {
132 bool boolean = true;
133
134 int integer = static_cast<int>(boolean) + 3;
135 float floating = static_cast<float>(boolean) * 0.3f;
136 char character = static_cast<char>(boolean);
137}
138
139void ignoreImplicitCastFromBoolInMacroExpansions() {
140 bool boolean = true;
141
142 #define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3
143 int integerFromMacroBody = CAST_FROM_BOOL_IN_MACRO_BODY;
144
145 #define CAST_FROM_BOOL_IN_MACRO_ARGUMENT(x) x + 3
146 int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);
147}
148
149namespace ignoreImplicitCastFromBoolInTemplateInstantiations {
150
151template<typename T>
152void templateFunction() {
153 bool boolean = true;
154 T uknownType = boolean + 3;
155}
156
157void useOfTemplateFunction() {
158 templateFunction<int>();
159}
160
161} // namespace ignoreImplicitCastFromBoolInTemplateInstantiations
162
163////////// Implicit cast to bool.
164
165void implicitCastToBoolSimpleCases() {
166 int integer = 10;
167 functionTaking<bool>(integer);
168 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
169 // CHECK-FIXES: functionTaking<bool>(integer != 0);
170
171 unsigned long unsignedLong = 10;
172 functionTaking<bool>(unsignedLong);
173 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'unsigned long' -> bool
174 // CHECK-FIXES: functionTaking<bool>(unsignedLong != 0u);
175
176 float floating = 0.0f;
177 functionTaking<bool>(floating);
178 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
179 // CHECK-FIXES: functionTaking<bool>(floating != 0.0f);
180
181 double doubleFloating = 1.0f;
182 functionTaking<bool>(doubleFloating);
183 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
184 // CHECK-FIXES: functionTaking<bool>(doubleFloating != 0.0);
185
Piotr Dziwinski9c5c7a62015-10-25 17:11:13 +0000186 signed char character = 'a';
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +0000187 functionTaking<bool>(character);
Piotr Dziwinski9c5c7a62015-10-25 17:11:13 +0000188 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'signed char' -> bool
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +0000189 // CHECK-FIXES: functionTaking<bool>(character != 0);
190
191 int* pointer = nullptr;
192 functionTaking<bool>(pointer);
193 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int *' -> bool
194 // CHECK-FIXES: functionTaking<bool>(pointer != nullptr);
195
196 auto pointerToMember = &Struct::member;
197 functionTaking<bool>(pointerToMember);
Alexander Kornienkocbe8d162017-05-04 15:34:23 +0000198 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int Struct::*' -> bool
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +0000199 // CHECK-FIXES: functionTaking<bool>(pointerToMember != nullptr);
200}
201
202void implicitCastToBoolInSingleExpressions() {
203 int integer = 10;
204 bool boolComingFromInt = integer;
205 // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit cast 'int' -> bool
206 // CHECK-FIXES: bool boolComingFromInt = integer != 0;
207
208 float floating = 10.0f;
209 bool boolComingFromFloat = floating;
210 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit cast 'float' -> bool
211 // CHECK-FIXES: bool boolComingFromFloat = floating != 0.0f;
212
Piotr Dziwinski9c5c7a62015-10-25 17:11:13 +0000213 signed char character = 'a';
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +0000214 bool boolComingFromChar = character;
Piotr Dziwinski9c5c7a62015-10-25 17:11:13 +0000215 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: implicit cast 'signed char' -> bool
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +0000216 // CHECK-FIXES: bool boolComingFromChar = character != 0;
217
218 int* pointer = nullptr;
219 bool boolComingFromPointer = pointer;
220 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast 'int *' -> bool
221 // CHECK-FIXES: bool boolComingFromPointer = pointer != nullptr;
222}
223
224void implicitCastToBoolInComplexExpressions() {
225 bool boolean = true;
226
227 int integer = 10;
228 int anotherInteger = 20;
229 bool boolComingFromInteger = integer + anotherInteger;
230 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: implicit cast 'int' -> bool
231 // CHECK-FIXES: bool boolComingFromInteger = (integer + anotherInteger) != 0;
232
233 float floating = 0.2f;
234 bool boolComingFromFloating = floating - 0.3f || boolean;
235 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit cast 'float' -> bool
236 // CHECK-FIXES: bool boolComingFromFloating = ((floating - 0.3f) != 0.0f) || boolean;
237
238 double doubleFloating = 0.3;
239 bool boolComingFromDoubleFloating = (doubleFloating - 0.4) && boolean;
240 // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'double' -> bool
241 // CHECK-FIXES: bool boolComingFromDoubleFloating = ((doubleFloating - 0.4) != 0.0) && boolean;
242}
243
244void implicitCastInNegationExpressions() {
245 int integer = 10;
246 bool boolComingFromNegatedInt = !integer;
247 // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: implicit cast 'int' -> bool
248 // CHECK-FIXES: bool boolComingFromNegatedInt = integer == 0;
249
250 float floating = 10.0f;
251 bool boolComingFromNegatedFloat = ! floating;
252 // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'float' -> bool
253 // CHECK-FIXES: bool boolComingFromNegatedFloat = floating == 0.0f;
254
Piotr Dziwinski9c5c7a62015-10-25 17:11:13 +0000255 signed char character = 'a';
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +0000256 bool boolComingFromNegatedChar = (! character);
Piotr Dziwinski9c5c7a62015-10-25 17:11:13 +0000257 // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: implicit cast 'signed char' -> bool
Piotr Dziwinski7f1b5092015-10-25 15:31:25 +0000258 // CHECK-FIXES: bool boolComingFromNegatedChar = (character == 0);
259
260 int* pointer = nullptr;
261 bool boolComingFromNegatedPointer = not pointer;
262 // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: implicit cast 'int *' -> bool
263 // CHECK-FIXES: bool boolComingFromNegatedPointer = pointer == nullptr;
264}
265
266void implicitCastToBoolInControlStatements() {
267 int integer = 10;
268 if (integer) {}
269 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: implicit cast 'int' -> bool
270 // CHECK-FIXES: if (integer != 0) {}
271
272 long int longInteger = 0.2f;
273 for (;longInteger;) {}
274 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit cast 'long' -> bool
275 // CHECK-FIXES: for (;longInteger != 0;) {}
276
277 float floating = 0.3f;
278 while (floating) {}
279 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast 'float' -> bool
280 // CHECK-FIXES: while (floating != 0.0f) {}
281
282 double doubleFloating = 0.4;
283 do {} while (doubleFloating);
284 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: implicit cast 'double' -> bool
285 // CHECK-FIXES: do {} while (doubleFloating != 0.0);
286}
287
288bool implicitCastToBoolInReturnValue() {
289 float floating = 1.0f;
290 return floating;
291 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit cast 'float' -> bool
292 // CHECK-FIXES: return floating != 0.0f;
293}
294
295void implicitCastToBoolFromLiterals() {
296 functionTaking<bool>(0);
297 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
298 // CHECK-FIXES: functionTaking<bool>(false);
299
300 functionTaking<bool>(1);
301 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
302 // CHECK-FIXES: functionTaking<bool>(true);
303
304 functionTaking<bool>(2ul);
305 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'unsigned long' -> bool
306 // CHECK-FIXES: functionTaking<bool>(true);
307
308
309 functionTaking<bool>(0.0f);
310 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
311 // CHECK-FIXES: functionTaking<bool>(false);
312
313 functionTaking<bool>(1.0f);
314 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
315 // CHECK-FIXES: functionTaking<bool>(true);
316
317 functionTaking<bool>(2.0);
318 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
319 // CHECK-FIXES: functionTaking<bool>(true);
320
321
322 functionTaking<bool>('\0');
323 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'char' -> bool
324 // CHECK-FIXES: functionTaking<bool>(false);
325
326 functionTaking<bool>('a');
327 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'char' -> bool
328 // CHECK-FIXES: functionTaking<bool>(true);
329
330
331 functionTaking<bool>("");
332 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'const char *' -> bool
333 // CHECK-FIXES: functionTaking<bool>(true);
334
335 functionTaking<bool>("abc");
336 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'const char *' -> bool
337 // CHECK-FIXES: functionTaking<bool>(true);
338
339 functionTaking<bool>(NULL);
340 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'long' -> bool
341 // CHECK-FIXES: functionTaking<bool>(false);
342}
343
344void implicitCastToBoolFromUnaryMinusAndZeroLiterals() {
345 functionTaking<bool>(-0);
346 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
347 // CHECK-FIXES: functionTaking<bool>((-0) != 0);
348
349 functionTaking<bool>(-0.0f);
350 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'float' -> bool
351 // CHECK-FIXES: functionTaking<bool>((-0.0f) != 0.0f);
352
353 functionTaking<bool>(-0.0);
354 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'double' -> bool
355 // CHECK-FIXES: functionTaking<bool>((-0.0) != 0.0);
356}
357
358void implicitCastToBoolInWithOverloadedOperators() {
359 struct UserStruct {
360 int operator()(int x) { return x; }
361 int operator+(int y) { return y; }
362 };
363
364 UserStruct s;
365
366 functionTaking<bool>(s(0));
367 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
368 // CHECK-FIXES: functionTaking<bool>(s(0) != 0);
369
370 functionTaking<bool>(s + 2);
371 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit cast 'int' -> bool
372 // CHECK-FIXES: functionTaking<bool>((s + 2) != 0);
373}
374
375int functionReturningInt();
376int* functionReturningPointer();
377
378void ignoreImplicitCastToBoolWhenDeclaringVariableInControlStatements() {
379 if (int integer = functionReturningInt()) {}
380
381 while (int* pointer = functionReturningPointer()) {}
382}
383
384void ignoreExplicitCastsToBool() {
385 int integer = 10;
386 bool boolComingFromInt = static_cast<bool>(integer);
387
388 float floating = 10.0f;
389 bool boolComingFromFloat = static_cast<bool>(floating);
390
391 char character = 'a';
392 bool boolComingFromChar = static_cast<bool>(character);
393
394 int* pointer = nullptr;
395 bool booleanComingFromPointer = static_cast<bool>(pointer);
396}
397
398void ignoreImplicitCastToBoolInMacroExpansions() {
399 int integer = 3;
400
401 #define CAST_TO_BOOL_IN_MACRO_BODY integer && false
402 bool boolFromMacroBody = CAST_TO_BOOL_IN_MACRO_BODY;
403
404 #define CAST_TO_BOOL_IN_MACRO_ARGUMENT(x) x || true
405 bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);
406}
407
408namespace ignoreImplicitCastToBoolInTemplateInstantiations {
409
410template<typename T>
411void templateFunction() {
412 T unknownType = 0;
413 bool boolean = unknownType;
414}
415
416void useOfTemplateFunction() {
417 templateFunction<int>();
418}
419
420} // namespace ignoreImplicitCastToBoolInTemplateInstantiations
421
422namespace ignoreUserDefinedConversionOperator {
423
424struct StructWithUserConversion {
425 operator bool();
426};
427
428void useOfUserConversion() {
429 StructWithUserConversion structure;
430 functionTaking<bool>(structure);
431}
432
433} // namespace ignoreUserDefinedConversionOperator