150 lines · plain
1.. title:: clang-tidy - readability-implicit-bool-conversion2 3readability-implicit-bool-conversion4====================================5 6This check can be used to find implicit conversions between built-in types and7booleans. Depending on use case, it may simply help with readability of the8code, or in some cases, point to potential bugs which remain unnoticed due to9implicit conversions.10 11The following is a real-world example of bug which was hiding behind implicit12``bool`` conversion:13 14.. code-block:: c++15 16 class Foo {17 int m_foo;18 19 public:20 void setFoo(bool foo) { m_foo = foo; } // warning: implicit conversion bool -> int21 int getFoo() { return m_foo; }22 };23 24 void use(Foo& foo) {25 bool value = foo.getFoo(); // warning: implicit conversion int -> bool26 }27 28This code is the result of unsuccessful refactoring, where type of ``m_foo``29changed from ``bool`` to ``int``. The programmer forgot to change all30occurrences of ``bool``, and the remaining code is no longer correct, yet it31still compiles without any visible warnings.32 33In addition to issuing warnings, fix-it hints are provided to help solve the34reported issues. This can be used for improving readability of code, for35example:36 37.. code-block:: c++38 39 void conversionsToBool() {40 float floating;41 bool boolean = floating;42 // ^ propose replacement: bool boolean = floating != 0.0f;43 44 int integer;45 if (integer) {}46 // ^ propose replacement: if (integer != 0) {}47 48 int* pointer;49 if (!pointer) {}50 // ^ propose replacement: if (pointer == nullptr) {}51 52 while (1) {}53 // ^ propose replacement: while (true) {}54 }55 56 void functionTakingInt(int param);57 58 void conversionsFromBool() {59 bool boolean;60 functionTakingInt(boolean);61 // ^ propose replacement: functionTakingInt(static_cast<int>(boolean));62 63 functionTakingInt(true);64 // ^ propose replacement: functionTakingInt(1);65 }66 67In general, the following conversion types are checked:68 69- integer expression/literal to boolean (conversion from a single bit bitfield70 to boolean is explicitly allowed, since there's no ambiguity / information71 loss in this case),72 73- floating expression/literal to boolean,74 75- pointer/pointer to member/``nullptr``/``NULL`` to boolean,76 77- boolean expression/literal to integer (conversion from boolean to a single78 bit bitfield is explicitly allowed),79 80- boolean expression/literal to floating.81 82The rules for generating fix-it hints are:83 84- in case of conversions from other built-in type to bool, an explicit85 comparison is proposed to make it clear what exactly is being compared:86 87 - ``bool boolean = floating;`` is changed to88 ``bool boolean = floating == 0.0f;``,89 90 - for other types, appropriate literals are used (``0``, ``0u``, ``0.0f``,91 ``0.0``, ``nullptr``),92 93- in case of negated expressions conversion to bool, the proposed replacement94 with comparison is simplified:95 96 - ``if (!pointer)`` is changed to ``if (pointer == nullptr)``,97 98- in case of conversions from bool to other built-in types, an explicit99 ``static_cast`` (or a C-style cast since C23) is proposed to make it clear100 that a conversion is taking place:101 102 - ``int integer = boolean;`` is changed to103 ``int integer = static_cast<int>(boolean);``,104 105- if the conversion is performed on type literals, an equivalent literal is106 proposed, according to what type is actually expected, for example:107 108 - ``functionTakingBool(0);`` is changed to ``functionTakingBool(false);``,109 110 - ``functionTakingInt(true);`` is changed to ``functionTakingInt(1);``,111 112 - for other types, appropriate literals are used (``false``, ``true``, ``0``,113 ``1``, ``0u``, ``1u``, ``0.0f``, ``1.0f``, ``0.0``, ``1.0f``).114 115Some additional accommodations are made for pre-C++11 dialects:116 117- ``false`` literal conversion to pointer is detected,118 119- instead of ``nullptr`` literal, ``0`` is proposed as replacement.120 121Occurrences of implicit conversions inside macros and template instantiations122are deliberately ignored, as it is not clear how to deal with such cases.123 124Options125-------126 127.. option:: AllowIntegerConditions128 129 When `true`, the check will allow conditional integer conversions. Default130 is `false`.131 132.. option:: AllowPointerConditions133 134 When `true`, the check will allow conditional pointer conversions. Default135 is `false`.136 137.. option:: UseUpperCaseLiteralSuffix138 139 When `true`, the replacements will use an uppercase literal suffix in the140 provided fixes. Default is `false`.141 142 Example143 144 .. code-block:: c++145 146 uint32_t foo;147 if (foo) {}148 // ^ propose replacement default: if (foo != 0u) {}149 // ^ propose replacement with option `UseUpperCaseLiteralSuffix`: if (foo != 0U) {}150