In my firm project, the AUTOSAR platform defines booleans like this
typedef unsigned char boolean;
plus
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
This is not modifiable. Then we get the MISRA 10.3 error Expression assigned to a narrower or different essential type [MISRA 2012 Rule 10.3, required] on the following two assignments (real code replaced, of course!)
boolean mybool = (boolean)FALSE;
if(some_condition)
{
mybool = (boolean)TRUE;
}
We've tried other convertions with (uint8)FALSE
or (unsigned char)FALSE
or even without a convertion mybool = TRUE;
without curing the issue. We would be happy to avoid justifying for deviation.
Does anyone has an idea of what happens and how to cure it?
@Fredrik Thanks for your first answer. I put this in a dummy header, included it in the 'culprit' .c
and run PC-Lint/MISRA on this unit
#define testTRUE 1U
boolean x = testTRUE;
boolean y = (uint8)testTRUE;
boolean z = (boolean)testTRUE;
#define testTRUE_2 1
boolean x_2 = testTRUE_2;
boolean y_2 = (uint8)testTRUE_2;
boolean z_2 = (boolean)testTRUE_2;
unsigned char x_3 = (boolean)1;
unsigned char y_3 = (boolean)testTRUE;
unsigned char z_3 = (boolean)testTRUE_2;
and get the same issue on the first 6 assignments. As to last 3 assignments, the error is not raised but perhaps hidden by this one in replacement: Use of modifier or type 'unsigned' outside of a typedef [MISRA 2012 Directive 4.6, advisory]
The thing with MISRA-C and booleans is that MISRA encourage us to "pretend" that there is a boolean type in the language and treat for example the result from relational and equality operators as "essentially boolean".
That is, treat the boolean type as C++ would. C did introduce booleans in C99, but the result of the mentioned operators is still int
, not bool
like in C++. But MISRA wants us to "pretend" that they are bool, to get the code right. In addition, MISRA-C still covers C90 where there is no standard bool
/true
/false
to be had.
So in order to get booleans to work like MISRA wants them, you need a way to tell your static analyser that boolean
, TRUE
and FALSE
is your boolean type. Otherwise the tool will treat them as int
and then you get all manner of implicit conversion warnings. I don't know how to do that on PC-Lint, but the error is a tool configuration issue.
As for the code posted, boolean mybool = FALSE;
is MISRA compliant, given that this is the "essentially boolean" type. No need to cast. And if you didn't configure the tool, no casting will save you. In general, never cast in C unless you know why you are doing it.
This is not modifiable.
I understand that AUTOSAR has some strange type requirements, that pre-date C11. Users of AUTOSAR have to live with that (and suggestions of how to get around them don't help)
Then we get the MISRA 10.3 error Expression assigned to a narrower or different essential type [MISRA 2012 Rule 10.3, required] on the following two assignments (real code replaced, of course!)
I think, at the heart of this is the apparent conflict between unsigned char
and 0
/1
(which are signed)... but this is addressed by Exception 1 of Rule 10.3 so not a violation.
But within the examples in the book there is:
bool_t bla = 0 /* Non-compliant: boolean and signed */
This implies that Exception 1 doesn't apply for booleans, which is curious!
Notwithstanding the use of the custom boolean
type rather than standard _Bool
or bool
, I suspect this may be a tool configuration issue... you need to tell PCLINT that the custom boolean
type (and TRUE
/FALSE
) is your essentially boolean type
Or failing that (ie if PCLINT doesn't have such a capability), you may need to deviate Rule 10.3
Disclaimer: See Profile!
UPDATE: I raised this question at a MISRA C WG (virtual) meeting. The agreement of the WG is that this is a false-positive, and that the Tool should be configured to cope with this - AUTOSAR users in the WG reported their configuration (albeit not using PCLINT) correctly did not flag this.
On occasion, static analysis tools have bugs - I have run into this kind of problem a few times. You might have hit one of them. It is the best if you contact the provider of the tool and ask for their opinion on the error, as well as how to fix it - either the code, or the tool. Just explain them what you explained us here.
To my knowledge, AUTOSAR is driven a lot by politics, and "science" is secondary. Therefore, many unusual or unexpected things can be found there.
I do not have a static analysis tool of any kind at the moment, so I cannot test it. But I think that the most correct way to define TRUE
and FALSE
in the context would be:
#ifndef TRUE
#define TRUE ((boolean)(1==1))
#endif
#ifndef FALSE
#define FALSE ((boolean)(1==0))
#endif
This overcomes 2 issues with the original definition:
Compilers are allowed to define their internal TRUE
and FALSE
values to any values. While FALSE
is usually (always?) 0
, TRUE
might actually have any non-zero value.
With the new definition, the TRUE
and FALSE
actually have the boolean
type.
The most recommended definition would be:
typedef enum boolean_tag
{
FALSE,
TRUE
} boolean;
which would make any other value completely illegal.
I am not sure if the following would work:
typedef enum boolean_tag
{
FALSE = (1==0),
TRUE = (1==1)
} boolean;
Comment (might not be applicable to your current situation):
Statements like
if ( boolean_variable )
{
/* do_smth */
}
are not a best practice. If I remember correctly there was even a MISRA rule to use
if (boolean_variable == TRUE)
{
/* do_smth */
}
instead - exactly in order to avoid conflicts with the inner workings of the compiler.
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