While working with a rather large C++ code base and the GCC toolchain on Linux, I have encountered code which performs a boolean check as follows:
#include <stdio.h>
int main() {
bool foo = true;
if (~foo) {
// do some expensive operation
printf("This can be bad...\n");
}
return 0;
}
This looks like an obvious bug, since the ~
operator represents bit-wise NOT in C++, and not logical NOT, as it would, say, in MATLAB. The above code would always evaluate to true
Luckily, the issue caused by this bug was not major (it was just a small performance hit), but it got me thinking about how this bug hadn't been found in so much time.
Since the bit-wise operator triggers an implicit cast from the boolean to an integer, which is a promotion, there's nothing wrong with it per se. However, to me it seems as though at least something like clang-tidy
should be able to pick this up as a logical error, since it is pretty clear that in most cases, the intent is not to apply a bit-wise operation to a bool, but instead a logical one.
g++
doesn't seem to care about this issue even with -Wall -Wextra -Wconversion
enabled, which is sensible given that, as I mentioned before, this isn't against the standard. (I even tried g++
6.3, which should have a lot of new checks, and still got nothing
Using clang-tidy
with all checks enabled (which can get really noisy really fast) does warn about the implicit conversion itself ("implicit cast bool -> 'int'"), but there doesn't seem to be a specific warning related to applying bit-wise operators to booleans.
Writing the if-statement differently as if(~foo == true)
, while verbose and leading to an always-false scenario, does lead to more meaningful errors which can bring the bug into attention, but this doesn't happen when the terser if(~foo)
form is used.
Are there any ways/tools to check for such issues, which are 100% correct C++, but very likely bugs?
5.2. Bitwise OR. Along with integer operands, the bitwise OR can also be used with boolean operands. It returns true if at least one of the operands is true, otherwise, it returns false.
In the C programming language, operations can be performed on a bit level using bitwise operators. Bitwise operations are contrasted by byte-level operations which characterize the bitwise operators' logical counterparts, the AND, OR, NOT operators.
Bitwise AND It is represented by a single ampersand sign (&). Two integer expressions are written on each side of the (&) operator. The result of the bitwise AND operation is 1 if both the bits have the value as 1; otherwise, the result is always 0. As we can see, two variables are compared bit by bit.
There is -Wbool-operation
in gcc as of gcc 7:
Warn about suspicious operations on expressions of a boolean type. For instance, bitwise negation of a boolean is very likely a bug in the program. For C, this warning also warns about incrementing or decrementing a boolean, which rarely makes sense. (In C++, decrementing a boolean is always invalid. Incrementing a boolean is invalid in C++1z, and deprecated otherwise.)
This warning is enabled by -Wall.
It provides the following warning for your program:
prog.cc:6:9: warning: '~' on an expression of type bool [-Wbool-operation]
if (~foo) {
^~~
prog.cc:6:9: note: did you mean to use logical not ('!')?
Unfortunately it does not appear that clang 5 has such an option. Even turning on (quite nearly) all of the possible warnings listed here, we still don't get the expected warning (Demo) (although we do get a few interesting others).
Finally, for completeness, MSVC 19.00.23506 definitely warns (Demo) (credit to @cbuchart for pointing this out):
source_file.cpp(8): warning C4804: '~': unsafe use of type 'bool' in operation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With