2017-08-08 22:53:52 +08:00
|
|
|
.. title:: clang-tidy - readability-implicit-bool-conversion
|
|
|
|
|
|
|
|
readability-implicit-bool-conversion
|
|
|
|
====================================
|
|
|
|
|
|
|
|
This check can be used to find implicit conversions between built-in types and
|
|
|
|
booleans. Depending on use case, it may simply help with readability of the code,
|
|
|
|
or in some cases, point to potential bugs which remain unnoticed due to implicit
|
|
|
|
conversions.
|
|
|
|
|
|
|
|
The following is a real-world example of bug which was hiding behind implicit
|
|
|
|
``bool`` conversion:
|
|
|
|
|
|
|
|
.. code-block:: c++
|
|
|
|
|
|
|
|
class Foo {
|
|
|
|
int m_foo;
|
|
|
|
|
|
|
|
public:
|
|
|
|
void setFoo(bool foo) { m_foo = foo; } // warning: implicit conversion bool -> int
|
|
|
|
int getFoo() { return m_foo; }
|
|
|
|
};
|
|
|
|
|
|
|
|
void use(Foo& foo) {
|
|
|
|
bool value = foo.getFoo(); // warning: implicit conversion int -> bool
|
|
|
|
}
|
|
|
|
|
|
|
|
This code is the result of unsuccessful refactoring, where type of ``m_foo``
|
|
|
|
changed from ``bool`` to ``int``. The programmer forgot to change all
|
|
|
|
occurrences of ``bool``, and the remaining code is no longer correct, yet it
|
|
|
|
still compiles without any visible warnings.
|
|
|
|
|
|
|
|
In addition to issuing warnings, fix-it hints are provided to help solve the
|
|
|
|
reported issues. This can be used for improving readability of code, for
|
|
|
|
example:
|
|
|
|
|
|
|
|
.. code-block:: c++
|
|
|
|
|
|
|
|
void conversionsToBool() {
|
|
|
|
float floating;
|
|
|
|
bool boolean = floating;
|
|
|
|
// ^ propose replacement: bool boolean = floating != 0.0f;
|
|
|
|
|
|
|
|
int integer;
|
|
|
|
if (integer) {}
|
|
|
|
// ^ propose replacement: if (integer != 0) {}
|
|
|
|
|
|
|
|
int* pointer;
|
|
|
|
if (!pointer) {}
|
|
|
|
// ^ propose replacement: if (pointer == nullptr) {}
|
|
|
|
|
|
|
|
while (1) {}
|
|
|
|
// ^ propose replacement: while (true) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
void functionTakingInt(int param);
|
|
|
|
|
|
|
|
void conversionsFromBool() {
|
|
|
|
bool boolean;
|
|
|
|
functionTakingInt(boolean);
|
|
|
|
// ^ propose replacement: functionTakingInt(static_cast<int>(boolean));
|
|
|
|
|
|
|
|
functionTakingInt(true);
|
|
|
|
// ^ propose replacement: functionTakingInt(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
In general, the following conversion types are checked:
|
|
|
|
|
2018-10-02 19:38:41 +08:00
|
|
|
- integer expression/literal to boolean (conversion from a single bit bitfield
|
|
|
|
to boolean is explicitly allowed, since there's no ambiguity / information
|
|
|
|
loss in this case),
|
2017-08-08 22:53:52 +08:00
|
|
|
|
|
|
|
- floating expression/literal to boolean,
|
|
|
|
|
|
|
|
- pointer/pointer to member/``nullptr``/``NULL`` to boolean,
|
|
|
|
|
2018-11-28 00:23:39 +08:00
|
|
|
- boolean expression/literal to integer (conversion from boolean to a single
|
|
|
|
bit bitfield is explicitly allowed),
|
2017-08-08 22:53:52 +08:00
|
|
|
|
|
|
|
- boolean expression/literal to floating.
|
|
|
|
|
|
|
|
The rules for generating fix-it hints are:
|
|
|
|
|
|
|
|
- in case of conversions from other built-in type to bool, an explicit
|
|
|
|
comparison is proposed to make it clear what exaclty is being compared:
|
|
|
|
|
|
|
|
- ``bool boolean = floating;`` is changed to
|
|
|
|
``bool boolean = floating == 0.0f;``,
|
|
|
|
|
|
|
|
- for other types, appropriate literals are used (``0``, ``0u``, ``0.0f``,
|
|
|
|
``0.0``, ``nullptr``),
|
|
|
|
|
|
|
|
- in case of negated expressions conversion to bool, the proposed replacement
|
|
|
|
with comparison is simplified:
|
|
|
|
|
|
|
|
- ``if (!pointer)`` is changed to ``if (pointer == nullptr)``,
|
|
|
|
|
|
|
|
- in case of conversions from bool to other built-in types, an explicit
|
|
|
|
``static_cast`` is proposed to make it clear that a conversion is taking
|
|
|
|
place:
|
|
|
|
|
|
|
|
- ``int integer = boolean;`` is changed to
|
|
|
|
``int integer = static_cast<int>(boolean);``,
|
|
|
|
|
|
|
|
- if the conversion is performed on type literals, an equivalent literal is
|
|
|
|
proposed, according to what type is actually expected, for example:
|
|
|
|
|
|
|
|
- ``functionTakingBool(0);`` is changed to ``functionTakingBool(false);``,
|
|
|
|
|
|
|
|
- ``functionTakingInt(true);`` is changed to ``functionTakingInt(1);``,
|
|
|
|
|
|
|
|
- for other types, appropriate literals are used (``false``, ``true``, ``0``,
|
|
|
|
``1``, ``0u``, ``1u``, ``0.0f``, ``1.0f``, ``0.0``, ``1.0f``).
|
|
|
|
|
|
|
|
Some additional accommodations are made for pre-C++11 dialects:
|
|
|
|
|
|
|
|
- ``false`` literal conversion to pointer is detected,
|
|
|
|
|
|
|
|
- instead of ``nullptr`` literal, ``0`` is proposed as replacement.
|
|
|
|
|
|
|
|
Occurrences of implicit conversions inside macros and template instantiations
|
|
|
|
are deliberately ignored, as it is not clear how to deal with such cases.
|
|
|
|
|
|
|
|
Options
|
|
|
|
-------
|
|
|
|
|
|
|
|
.. option:: AllowIntegerConditions
|
|
|
|
|
|
|
|
When non-zero, the check will allow conditional integer conversions. Default
|
|
|
|
is `0`.
|
|
|
|
|
|
|
|
.. option:: AllowPointerConditions
|
|
|
|
|
|
|
|
When non-zero, the check will allow conditional pointer conversions. Default
|
|
|
|
is `0`.
|