Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MISRA 10.3 issue about AUTOSAR booleans

Tags:

c

misra

autosar

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]

like image 901
Oli Avatar asked Nov 25 '20 18:11

Oli


3 Answers

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.

like image 181
Lundin Avatar answered Nov 10 '22 08:11

Lundin


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.

like image 25
Andrew Avatar answered Nov 10 '22 08:11

Andrew


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:

  1. 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.

  2. 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.

like image 26
virolino Avatar answered Nov 10 '22 07:11

virolino