1 // RUN: %check_clang_tidy %s readability-implicit-bool-conversion %t -- -- -std=c23 2 // RUN: %check_clang_tidy -check-suffix=UPPER-CASE %s readability-implicit-bool-conversion %t -- \ 3 // RUN: -config='{CheckOptions: { \ 4 // RUN: readability-implicit-bool-conversion.UseUpperCaseLiteralSuffix: true \ 5 // RUN: }}' -- -std=c23 6 7 #undef NULL 8 #define NULL 0L 9 10 void functionTakingBool(bool); 11 void functionTakingInt(int); 12 void functionTakingUnsignedLong(unsigned long); 13 void functionTakingChar(char); 14 void functionTakingFloat(float); 15 void functionTakingDouble(double); 16 void functionTakingSignedChar(signed char); 17 18 19 ////////// Implicit conversion from bool. 20 21 void implicitConversionFromBoolSimpleCases() { 22 bool boolean = true; 23 24 functionTakingBool(boolean); 25 26 functionTakingInt(boolean); 27 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: implicit conversion 'bool' -> 'int' [readability-implicit-bool-conversion] 28 // CHECK-FIXES: functionTakingInt((int)boolean); 29 30 functionTakingUnsignedLong(boolean); 31 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'bool' -> 'unsigned long' 32 // CHECK-FIXES: functionTakingUnsignedLong((unsigned long)boolean); 33 34 functionTakingChar(boolean); 35 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'bool' -> 'char' 36 // CHECK-FIXES: functionTakingChar((char)boolean); 37 38 functionTakingFloat(boolean); 39 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion 'bool' -> 'float' 40 // CHECK-FIXES: functionTakingFloat((float)boolean); 41 42 functionTakingDouble(boolean); 43 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'bool' -> 'double' 44 // CHECK-FIXES: functionTakingDouble((double)boolean); 45 } 46 47 float implicitConversionFromBoolInReturnValue() { 48 bool boolean = false; 49 return boolean; 50 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'bool' -> 'float' 51 // CHECK-FIXES: return (float)boolean; 52 } 53 54 void implicitConversionFromBoolInSingleBoolExpressions(bool b1, bool b2) { 55 bool boolean = true; 56 boolean = b1 ^ b2; 57 boolean |= !b1 || !b2; 58 boolean &= b1; 59 60 int integer = boolean - 3; 61 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion 'bool' -> 'int' 62 // CHECK-FIXES: int integer = (int)boolean - 3; 63 64 float floating = boolean / 0.3f; 65 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion 'bool' -> 'float' 66 // CHECK-FIXES: float floating = (float)boolean / 0.3f; 67 68 char character = boolean; 69 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: implicit conversion 'bool' -> 'char' 70 // CHECK-FIXES: char character = (char)boolean; 71 } 72 73 void implicitConversionFromBoolInComplexBoolExpressions() { 74 bool boolean = true; 75 bool anotherBoolean = false; 76 77 int integer = boolean && anotherBoolean; 78 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: implicit conversion 'bool' -> 'int' 79 // CHECK-MESSAGES: :[[@LINE-2]]:28: warning: implicit conversion 'bool' -> 'int' 80 // CHECK-FIXES: int integer = (int)boolean && (int)anotherBoolean; 81 82 float floating = (boolean || anotherBoolean) * 0.3f; 83 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: implicit conversion 'bool' -> 'int' 84 // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: implicit conversion 'bool' -> 'int' 85 // CHECK-FIXES: float floating = ((int)boolean || (int)anotherBoolean) * 0.3f; 86 87 double doubleFloating = (boolean && (anotherBoolean || boolean)) * 0.3; 88 // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit conversion 'bool' -> 'int' 89 // CHECK-MESSAGES: :[[@LINE-2]]:40: warning: implicit conversion 'bool' -> 'int' 90 // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: implicit conversion 'bool' -> 'int' 91 // CHECK-FIXES: double doubleFloating = ((int)boolean && ((int)anotherBoolean || (int)boolean)) * 0.3; 92 } 93 94 void implicitConversionFromBoolLiterals() { 95 functionTakingInt(true); 96 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: implicit conversion 'bool' -> 'int' 97 // CHECK-FIXES: functionTakingInt(1); 98 99 functionTakingUnsignedLong(false); 100 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'bool' -> 'unsigned long' 101 // CHECK-FIXES: functionTakingUnsignedLong(0u); 102 // CHECK-FIXES-UPPER-CASE: functionTakingUnsignedLong(0U); 103 104 functionTakingSignedChar(true); 105 // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: implicit conversion 'bool' -> 'signed char' 106 // CHECK-FIXES: functionTakingSignedChar(1); 107 108 functionTakingFloat(false); 109 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion 'bool' -> 'float' 110 // CHECK-FIXES: functionTakingFloat(0.0f); 111 // CHECK-FIXES-UPPER-CASE: functionTakingFloat(0.0F); 112 113 functionTakingDouble(true); 114 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'bool' -> 'double' 115 // CHECK-FIXES: functionTakingDouble(1.0); 116 } 117 118 void implicitConversionFromBoolInComparisons() { 119 bool boolean = true; 120 int integer = 0; 121 122 functionTakingBool(boolean == integer); 123 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'bool' -> 'int' 124 // CHECK-FIXES: functionTakingBool((int)boolean == integer); 125 126 functionTakingBool(integer != boolean); 127 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: implicit conversion 'bool' -> 'int' 128 // CHECK-FIXES: functionTakingBool(integer != (int)boolean); 129 } 130 131 void ignoreBoolComparisons() { 132 bool boolean = true; 133 bool anotherBoolean = false; 134 135 functionTakingBool(boolean == anotherBoolean); 136 functionTakingBool(boolean != anotherBoolean); 137 } 138 139 void ignoreExplicitCastsFromBool() { 140 bool boolean = true; 141 142 int integer = (int)boolean + 3; 143 float floating = (float)boolean * 0.3f; 144 char character = (char)boolean; 145 } 146 147 void ignoreImplicitConversionFromBoolInMacroExpansions() { 148 bool boolean = true; 149 150 #define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3 151 int integerFromMacroBody = CAST_FROM_BOOL_IN_MACRO_BODY; 152 153 #define CAST_FROM_BOOL_IN_MACRO_ARGUMENT(x) x + 3 154 int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean); 155 } 156 157 ////////// Implicit conversions to bool. 158 159 void implicitConversionToBoolSimpleCases() { 160 int integer = 10; 161 functionTakingBool(integer); 162 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'int' -> 'bool' 163 // CHECK-FIXES: functionTakingBool(integer != 0); 164 165 unsigned long unsignedLong = 10; 166 functionTakingBool(unsignedLong); 167 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'unsigned long' -> 'bool' 168 // CHECK-FIXES: functionTakingBool(unsignedLong != 0u); 169 // CHECK-FIXES-UPPER-CASE: functionTakingBool(unsignedLong != 0U); 170 171 float floating = 0.0f; 172 functionTakingBool(floating); 173 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'float' -> 'bool' 174 // CHECK-FIXES: functionTakingBool(floating != 0.0f); 175 // CHECK-FIXES-UPPER-CASE: functionTakingBool(floating != 0.0F); 176 177 double doubleFloating = 1.0f; 178 functionTakingBool(doubleFloating); 179 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'double' -> 'bool' 180 // CHECK-FIXES: functionTakingBool(doubleFloating != 0.0); 181 182 signed char character = 'a'; 183 functionTakingBool(character); 184 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'signed char' -> 'bool' 185 // CHECK-FIXES: functionTakingBool(character != 0); 186 187 int* pointer = nullptr; 188 functionTakingBool(pointer); 189 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'int *' -> 'bool' 190 // CHECK-FIXES: functionTakingBool(pointer != nullptr); 191 } 192 193 void implicitConversionToBoolInSingleExpressions() { 194 int integer = 10; 195 bool boolComingFromInt; 196 boolComingFromInt = integer; 197 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: implicit conversion 'int' -> 'bool' 198 // CHECK-FIXES: boolComingFromInt = (integer != 0); 199 200 float floating = 10.0f; 201 bool boolComingFromFloat; 202 boolComingFromFloat = floating; 203 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: implicit conversion 'float' -> 'bool' 204 // CHECK-FIXES: boolComingFromFloat = (floating != 0.0f); 205 // CHECK-FIXES-UPPER-CASE: boolComingFromFloat = (floating != 0.0F); 206 207 signed char character = 'a'; 208 bool boolComingFromChar; 209 boolComingFromChar = character; 210 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: implicit conversion 'signed char' -> 'bool' 211 // CHECK-FIXES: boolComingFromChar = (character != 0); 212 213 int* pointer = nullptr; 214 bool boolComingFromPointer; 215 boolComingFromPointer = pointer; 216 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit conversion 'int *' -> 'bool' 217 // CHECK-FIXES: boolComingFromPointer = (pointer != nullptr); 218 } 219 220 void implicitConversionToBoolInComplexExpressions() { 221 bool boolean = true; 222 223 int integer = 10; 224 int anotherInteger = 20; 225 bool boolComingFromInteger; 226 boolComingFromInteger = integer + anotherInteger; 227 // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: implicit conversion 'int' -> 'bool' 228 // CHECK-FIXES: boolComingFromInteger = ((integer + anotherInteger) != 0); 229 } 230 231 void implicitConversionInNegationExpressions() { 232 int integer = 10; 233 bool boolComingFromNegatedInt; 234 boolComingFromNegatedInt = !integer; 235 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: implicit conversion 'int' -> 'bool' 236 // CHECK-FIXES: boolComingFromNegatedInt = ((!integer) != 0); 237 } 238 239 bool implicitConversionToBoolInReturnValue() { 240 float floating = 1.0f; 241 return floating; 242 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: implicit conversion 'float' -> 'bool' 243 // CHECK-FIXES: return floating != 0.0f; 244 } 245 246 void implicitConversionToBoolFromLiterals() { 247 functionTakingBool(0); 248 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'int' -> 'bool' 249 // CHECK-FIXES: functionTakingBool(false); 250 251 functionTakingBool(1); 252 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'int' -> 'bool' 253 // CHECK-FIXES: functionTakingBool(true); 254 255 functionTakingBool(2ul); 256 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'unsigned long' -> 'bool' 257 // CHECK-FIXES: functionTakingBool(true); 258 259 functionTakingBool(0.0f); 260 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'float' -> 'bool' 261 // CHECK-FIXES: functionTakingBool(false); 262 263 functionTakingBool(1.0f); 264 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'float' -> 'bool' 265 // CHECK-FIXES: functionTakingBool(true); 266 267 functionTakingBool(2.0); 268 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'double' -> 'bool' 269 // CHECK-FIXES: functionTakingBool(true); 270 271 functionTakingBool('\0'); 272 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'int' -> 'bool' 273 // CHECK-FIXES: functionTakingBool(false); 274 275 functionTakingBool('a'); 276 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'int' -> 'bool' 277 // CHECK-FIXES: functionTakingBool(true); 278 279 functionTakingBool(""); 280 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'char *' -> 'bool' 281 // CHECK-FIXES: functionTakingBool(true); 282 283 functionTakingBool("abc"); 284 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'char *' -> 'bool' 285 // CHECK-FIXES: functionTakingBool(true); 286 287 functionTakingBool(NULL); 288 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'long' -> 'bool' 289 // CHECK-FIXES: functionTakingBool(false); 290 } 291 292 void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() { 293 functionTakingBool(-0); 294 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'int' -> 'bool' 295 // CHECK-FIXES: functionTakingBool((-0) != 0); 296 297 functionTakingBool(-0.0f); 298 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'float' -> 'bool' 299 // CHECK-FIXES: functionTakingBool((-0.0f) != 0.0f); 300 // CHECK-FIXES-UPPER-CASE: functionTakingBool((-0.0f) != 0.0F); 301 302 functionTakingBool(-0.0); 303 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: implicit conversion 'double' -> 'bool' 304 // CHECK-FIXES: functionTakingBool((-0.0) != 0.0); 305 } 306 307 void ignoreImplicitCastToBoolForComparisonResult() { 308 bool boolFromComparison0 = 1 != 0; 309 bool boolFromComparison1 = 1 == 0; 310 bool boolFromComparison2 = 1 > 0; 311 bool boolFromComparison3 = 1 >= 0; 312 bool boolFromComparison4 = 1 < 0; 313 bool boolFromComparison5 = 1 <= 0; 314 } 315 316 void ignoreExplicitCastsToBool() { 317 int integer = 10; 318 bool boolComingFromInt = (bool)integer; 319 320 float floating = 10.0f; 321 bool boolComingFromFloat = (bool)floating; 322 323 char character = 'a'; 324 bool boolComingFromChar = (bool)character; 325 326 int* pointer = nullptr; 327 bool booleanComingFromPointer = (bool)pointer; 328 } 329 330 void ignoreImplicitConversionToBoolInMacroExpansions() { 331 int integer = 3; 332 333 #define CAST_TO_BOOL_IN_MACRO_BODY integer && false 334 bool boolFromMacroBody = CAST_TO_BOOL_IN_MACRO_BODY; 335 336 #define CAST_TO_BOOL_IN_MACRO_ARGUMENT(x) x || true 337 bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer); 338 } 339 340 int implicitConversionReturnInt() 341 { 342 return true; 343 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: implicit conversion 'bool' -> 'int' 344 // CHECK-FIXES: return 1 345 } 346 347 int implicitConversionReturnIntWithParens() 348 { 349 return (true); 350 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: implicit conversion 'bool' -> 'int' 351 // CHECK-FIXES: return 1 352 } 353 354 bool implicitConversionReturnBool() 355 { 356 return 1; 357 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: implicit conversion 'int' -> 'bool' 358 // CHECK-FIXES: return true 359 } 360 361 bool implicitConversionReturnBoolWithParens() 362 { 363 return (1); 364 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: implicit conversion 'int' -> 'bool' 365 // CHECK-FIXES: return true 366 } 367 368 int keepCompactReturnInC_PR71848() { 369 bool foo = false; 370 return( foo ); 371 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: implicit conversion 'bool' -> 'int' [readability-implicit-bool-conversion] 372 // CHECK-FIXES: return(int)( foo ); 373 } 374