MISRA C: 2004, bit offset error

I am using the IAR Workbench compiler with MISRA C: 2004 validation.
Fragment:

#define UNS_32 unsigned int UNS_32 arg = 3U; UNS_32 converted_arg = (UNS_32) arg; /* Error line --> */ UNS_32 irq_source = (UNS_32)(1U << converted_arg); 

MISRA error: Error [Pm136]: illegal explicit conversion from the MISRA base type "unsigned char" to "unsigned int" (Rule 10.3 of MISRA C 2004)

I do not see any unsigned char in any of the codes above.

Discussion in Why Misra posted an error here? discusses multiplication, which may have different promotion rules than moving left.

My understanding is that the compiler should push the expression to a larger data type, and not reduce the size to a smaller size.

What's going on here?

How to make code compatible with MISRA C: 2004?

Change 1:

Change the error line to:

 UNS_32 irq_source = (UNS_32)((UNS_32) 1U << converted_arg); 

does not make the mistake disappear.

+4
c misra unsigned integer-promotion iar
source share
2 answers

Second question:

How to make code compatible with MISRA C: 2004?

You can write this according to MISRA as follows:

 typedef unsigned int UNS_32; UNS_32 test(void); UNS_32 test(void) { UNS_32 original_arg = 3U; UNS_32 irq_source = 1UL << original_arg; return irq_source; } 

Back to the first question:

What's going on here?

The first rule 10.3 states that complex integer expressions must not be cast to a type wider than the base type.

One key to understanding the error message is the basic concept type, which is the MISRA-C concept. In short, the basic type of a constant is the smallest type into which it can fit. In this case, 1U has the base type unsigned char , despite the fact that it has the language type unsigned int .

The rationale for rule 10.3 is to avoid cases where the result of an operation is used in a context that is larger than the parts. A standard example of this is multiplication, where alpha and beta are 16-bit types:

 uint32_t res = alpha * beta; 

Here, if int is 16 bits, the multiplication will be done in 16 bits, the result will be converted to 32 bits. On the other hand, if int is 32 bits or more, multiplication will be performed with greater precision. Specifically, this will cause the result to be different when multiplied, say, 0x4000 and 0x10.

MISRA Rule 10.3 allowed this by establishing that the casting result is placed in a temporary cast, which is later converted to a larger type. Thus, you are forced to write code anyway.

If you intend to use 16-bit multiplication:

 uint16_t tmp = alpha * beta; uint32_t res = tmp; 

On the other hand, if the intention is a 32-bit multiplication:

 UNS_32 res = (UNS_32)alpha * (UNS_32)beta; 

So, in this case, the expression 1U << count is a potential problem. If converted_arg greater than 16 bits, this may lead to a problem when using 16-bit int s. However, MISRA allows you to write 1UL << count or (UNS_32)((UNS_32)1U << original_arg) . You mentioned that in the latter case, MISRA checker issued an error - mine is wrong, please check again.

So, as I see it, the MISRA C validator that you used correctly identified a violation of rule 10.3.

+3
source share

In C89, which is defined by the MISRA rules, the type of an integer constant, the suffix with U , is the first in the list of "unsigned int, unsigned long int" in which its value can be represented. This means that type 1U must be unsigned int .

The definition of a bit-shift operator indicates that whole shares are executed for each operand (this does not change the unsigned int ), and that the result type is the type of the advanced left operand. In this case, the result type (1U << converted_arg) , therefore, unsigned int .

The only explicit conversion here is a different value from unsigned int to unsigned int , so this should be what the compiler warns about - although there is no unsigned char in sight, which means that the control panel is an error.

Technically, this drop from unsigned int to unsigned int seems to violate rule 10.3, which states that the result of a “complex expression” can only be attributed to a narrower type - and casting to the same type clearly does not drop the narrower type of.

A throw is not needed - I would just miss it.

+3
source share

All Articles