374 lines · c
1// RUN: %check_clang_tidy -std=c23-or-later %s readability-implicit-bool-conversion %t2// RUN: %check_clang_tidy -std=c23-or-later -check-suffix=UPPER-CASE %s readability-implicit-bool-conversion %t -- \3// RUN: -config='{CheckOptions: { \4// RUN: readability-implicit-bool-conversion.UseUpperCaseLiteralSuffix: true \5// RUN: }}'6 7#undef NULL8#define NULL 0L9 10void functionTakingBool(bool);11void functionTakingInt(int);12void functionTakingUnsignedLong(unsigned long);13void functionTakingChar(char);14void functionTakingFloat(float);15void functionTakingDouble(double);16void functionTakingSignedChar(signed char);17 18 19////////// Implicit conversion from bool.20 21void 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 47float 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 54void 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 73void 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 94void 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 118void 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 131void ignoreBoolComparisons() {132 bool boolean = true;133 bool anotherBoolean = false;134 135 functionTakingBool(boolean == anotherBoolean);136 functionTakingBool(boolean != anotherBoolean);137}138 139void 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 147void ignoreImplicitConversionFromBoolInMacroExpansions() {148 bool boolean = true;149 150 #define CAST_FROM_BOOL_IN_MACRO_BODY boolean + 3151 int integerFromMacroBody = CAST_FROM_BOOL_IN_MACRO_BODY;152 153 #define CAST_FROM_BOOL_IN_MACRO_ARGUMENT(x) x + 3154 int integerFromMacroArgument = CAST_FROM_BOOL_IN_MACRO_ARGUMENT(boolean);155}156 157////////// Implicit conversions to bool.158 159void 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 193void 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 220void 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 231void 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 239bool 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 246void 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 292void 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 307void 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 316void 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 330void ignoreImplicitConversionToBoolInMacroExpansions() {331 int integer = 3;332 333 #define CAST_TO_BOOL_IN_MACRO_BODY integer && false334 bool boolFromMacroBody = CAST_TO_BOOL_IN_MACRO_BODY;335 336 #define CAST_TO_BOOL_IN_MACRO_ARGUMENT(x) x || true337 bool boolFromMacroArgument = CAST_TO_BOOL_IN_MACRO_ARGUMENT(integer);338}339 340int implicitConversionReturnInt()341{342 return true;343 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: implicit conversion 'bool' -> 'int'344 // CHECK-FIXES: return 1;345}346 347int implicitConversionReturnIntWithParens()348{349 return (true);350 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: implicit conversion 'bool' -> 'int'351 // CHECK-FIXES: return 1;352}353 354bool implicitConversionReturnBool()355{356 return 1;357 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: implicit conversion 'int' -> 'bool'358 // CHECK-FIXES: return true;359}360 361bool implicitConversionReturnBoolWithParens()362{363 return (1);364 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: implicit conversion 'int' -> 'bool'365 // CHECK-FIXES: return true;366}367 368int 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