gcc: how to detect bad `bool` usage
Asked Answered
H

3

8

Is there some way to detect the bad usage of bool values in code like

#include <stdbool.h>

void *foo(void)
{
    return false;
}

int bar(void)
{
    return true;
}

Both functions are accepted by gcc (8.3.1) and clang (7.0.1) without any warnings

$ gcc -Wall -W -pedantic -c x.c
$ clang -Xclang -analyzer-checker=alpha --analyze  -Wall -W -pedantic -c x.c
$ clang -Wall -W -pedantic -c x.c
$

Compiling as C++ code would detect the problem in foo() but is not an option but rest of code is C, not C++.

Are there other (-W) options or switches which would create diagnostics for these cases?

Harbert answered 16/3, 2019 at 15:24 Comment(3)
Would lint catch these? Especially an updated tool such as PCLint? See for instance invisible-island.net/personal/lint-tools.html and see this about lint pubs.opengroup.org/onlinepubs/7908799/xcu/lint.htmlCushion
Looks like there is an updated version, splint, #6881769Cushion
@RichardChambers thinks for the hint; but "splint" does not seem to understand C99+ at all and aborts when seeing variadic macros (e.g. #define log_err(_fmt, ...)).Harbert
P
2

Make the example less trivial:

bool x;

void *foo(void)
{
    return x;
}

int bar(void)
{
    return x;
}

and it want compile at all.

usually true and false are just definitions and have value 1 and 0

From the stdbool.h header file

#ifndef _STDBOOL_H
#define _STDBOOL_H

#ifndef __cplusplus

#define bool    _Bool
#define true    1
#define false   0

#else /* __cplusplus */

in your first example you just return zero and most compilers will not warn as they treat it as NULL. Try to return true and you will get the warning.

Palmer answered 16/3, 2019 at 15:37 Comment(4)
My code is some simplified variant of refactored code where functions previously returned a bool value and where converted to return richer values. The return true resp. return false was missed in the refactoring and stayed literally; I just want to detect them.Harbert
Just don't include stdbool.h (you don't need it), and you'll catch all the occurences.Acaudal
@Acaudal or if stdbool.h is buried deeper, a temporary local redefinition to "break" bool, true and false could also help identify the places to change. (don't leave it like that, but...)Idolum
@Acaudal Not a good idea. In my experience, using stdbool.h can significantly increase code readability, simply because booleans are labeled as such. Of course, I would have preferred a definition like ((_Bool)0), but I've never run into the OP's problem (even though I'm making liberal use of stdbool.h).Discalced
G
2

C defines the <stdbool.h> macros true and false as expanding to integer constant expressions of value 1 and 0 respectively. Since they're ints and bool (_Bool) in itself is an integer type, any such usage is equally valid. Even the value of the boolean expressions in C is an int and not a bool, so there is not much help for you with the bar function.

However, foo is a different beast - if the return value were true then it would be caught right away because 1 is not convertible to a pointer. false, having the integer constant value 0 is a null-pointer constant and will be converted to null pointer. You could perhaps catch the incorrect use by replacing the #include <stdbool.h> with something that does the inclusion but defines false as say 0.0 which is a falsy value but not an integer constant expression.

Gusgusba answered 16/3, 2019 at 15:59 Comment(0)
E
1

Choosing the C23 standard helps with this, as C23 has a specific boolean type, distinct from integers. Compiling your code with GCC 13 using -std=c23 gives:

warning: initialization of pointer of type 'void *' to null from a constant boolean expression [-Wbool-conversion]

However, the bool to int conversion still won't be flagged.

Extenuation answered 2/6, 2024 at 16:2 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.