Skip to content

feat: enforcing MISRA compliant Boolean values #7110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

anshgoyalevil
Copy link

This PR adds a literal to boolean style check.

bool x = 1;  // Warning: Boolean variable assigned a numeric literal '1'. Consider using 'true' instead.
bool y = 0;  // Warning: Boolean variable assigned a numeric literal '0'. Consider using 'false' instead.

ref: commaai/panda#1876, commaai/panda#2105

Signed-off-by: Ansh Goyal <anshgoyal1704@gmail.com>
@okias
Copy link

okias commented Dec 16, 2024

damn, I'm too slow. Anyway, shouldn't this go into addons/misra.py ? I would guess Rule 23.6

@anshgoyalevil
Copy link
Author

Thanks for the suggestion, @okias. I am fairly new to this MISRA thing. I just read the discussion in the thread commaai/panda#1876 and this way looked like what adding the check into ustream meant.

Can you please help identify if that's the right way to do that? Adding a check into upstream without explicitly defining an addon code.

@okias
Copy link

okias commented Dec 17, 2024

In general, a C++ solution like the one you wrote looks better, but I understood it as part of the MISRA plugin—something like this: okias@6b3d84a. The code doesn't detect the initial bool x = 1;, only bool x; x = 1;. This was also my first attempt with cppcheck..

@anshgoyalevil
Copy link
Author

Thanks. Now I get the point. I would implement it the MISRA plugin way if this one is rejected by the maintainers.
Can you please review it @danmar

@danmar
Copy link
Owner

danmar commented Dec 22, 2024

Hi, sorry for the late review. I spontanously feel this might be too "stylistic" in nature. It's not to find "buggy" code, is it? What bugs could it lead to? Normally I like if "style" checkers have a motivation to prevent some possible bugs. For instance; unread variables can for instance indicate an overlook.

I wouldn't normally write bool x=1; myself explicitly.

In my humble opinion it does not violate MISRA 23.6 but it does violate 10.3 and Cppcheck Premium writes a warning about it.

@danmar
Copy link
Owner

danmar commented Dec 22, 2024

The implementation: I don't have major complaints. It's pretty good. But some test cases is needed and also I think a ticket should be added in trac and the release notes would need to mention the new checker..

@anshgoyalevil
Copy link
Author

Thanks for the inputs. This would not help prevent bugs to the code but would help increase readability at some places. I would add the required test cases.

Can you please elaborate that trac thing. How can I file a ticket out there?

@danmar
Copy link
Owner

danmar commented Jan 1, 2025

This would not help prevent bugs to the code but would help increase readability at some places. I would add the required test cases.

well.. I don't know why anybody would WANT to do this.. but still I don't have a very good feeling about this. This is not the high prio findings users want to see. Could you try to write a checker that looks for "mistakes" somehow? I believe trac has many suggestions as inspiration.

https://trac.cppcheck.net

to get an account on trac you'll need to send a htpasswd hash to me. You can generate a htpasswd hash online, google "htpasswd hash generator"

@tralamazza
Copy link

tralamazza commented Feb 13, 2025

This looks to be MISRA 10.x territory.
Why is the check restricted to literal 0 and 1?
Any prvalue zero of an integral, floating point and unscoped enum plus nullptr converts to false, any other value to true.
I don't see a use case for initializing a bool from any other literal than true or false.

https://cpp.godbolt.org/z/qW4K1facc

@wienans
Copy link
Contributor

wienans commented Feb 22, 2025

Checked the Misra Plugin and currently it is checked here if a bool gets assigned a value bigger than 0 or 1

cppcheck/addons/misra.py

Lines 2328 to 2329 in 85423bd

if bitsOfEssentialType(lhs) < bitsOfEssentialType(rhs) and (lhs != "bool" or tok.astOperand2.str not in ('0','1')):
self.reportError(tok, 10, 3)

This looks to be MISRA 10.x territory. Why is the check restricted to literal 0 and 1? Any prvalue zero of an integral, floating point and unscoped enum plus nullptr converts to false, any other value to true. I don't see a use case for initializing a bool from any other literal than true or false.

https://cpp.godbolt.org/z/qW4K1facc

And additionally i checked your code against the Warnings

10.3 was found for

bool bint_t = -1;
bool bflt_f = 0.f;
bool bflt_t = 20.f;

and the following was false negative:

bool bint_f = 0; // expected as 0 and 1 are allowed as value, but actually the essential type changes

enum Foo {
    BAR = 0,
    BAZ = 7
};

bool benuml_f = BAR; // semi expected as 0 and 1 are allowed for the value but actually cppcheck does not deuce it to 0 or 1
bool benuml_t = BAZ;

bool bnull_f{NULL}; // only direct init
bool bnull_t = &bnull_f;

This is because the Essential Type

def getEssentialType(expr):
for the Enums and the {NULL} as well as &bnull_f is not handled here and returns None at the end of the function, even if they have a valueType assigned to them. Similar is true for the keywords true and false they both have a value type assigned to them in the dump file but they both also return None from the Essential Type function and therefore the check stops due to one of the sides having a None Type.

And maybe i am tripping but seeing https://gitlab.com/MISRA/MISRA-C/MISRA-C-2012/tools/-/blob/main/misra_c_2012__headlines_for_cppcheck%20-%20AMD1+AMD2.txt?ref_type=heads#L180
i think all of them should be a 10.3 as @tralamazza says. It states that it shouldn't be narrower, where you could debate if you directly assign 0 and 1 is okay, but i think all other parts should fail as the essential type changes, which is the second part of the rule.

@danmar
Copy link
Owner

danmar commented Feb 24, 2025

if you change misra.py rule 10.3 so that it warns I am not against it.

@danmar
Copy link
Owner

danmar commented Feb 24, 2025

I have the feeling that C89 does not have a "bool" type. And one possible way to use bools would be:

typedef int bool;
#define true 1
#define false 0
bool x = true;

my guess this is why misra.py is written as it is.

@wienans
Copy link
Contributor

wienans commented Feb 24, 2025

I have the feeling that C89 does not have a "bool" type. And one possible way to use bools would be:

typedef int bool;
#define true 1
#define false 0
bool x = true;

my guess this is why misra.py is written as it is.

Actually true 🤔 stdbool was added in C99. Maybe dependent on Code Standard for C89 allow 0 and 1 and for C99 not?

@danmar
Copy link
Owner

danmar commented Feb 27, 2025

Maybe dependent on Code Standard for C89 allow 0 and 1 and for C99 not?

Sounds good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants