static inline function in header file and misra c rule 8.5 problem

1.8k Views Asked by At

I'm using "IAR RL78" and "RL78-R5F10BGG" microcontroller. I also have enabled MISRA C 2004 in IAR.

I wanna define one of my functions as "inline". This inline function is supposed to be used in various c file. So I have defined the function in one of my

header files and include that header file in all c files which need the function. But my problem is because of MISRA C 8.5 rule after compilation. It says:

Error[Pm123]: there shall be no definition of objects or functions in a header file (MISRA C 2004 rule 8.5)

The following is the definition of the inline function in common.h header:

static inline int16u SET_BIT(int16u int16uVar, int16u int16uBitIndex);

#pragma inline=forced
static inline int16u SET_BIT(int16u int16uVar, int16u int16uBitIndex)
{
     int16uVar |= ( (int16u)1u << (int16uBitIndex) );

     return int16uVar ;
}

What's the problem?

Is there any way to get rid of this problem?

3

There are 3 best solutions below

3
On

MISRA-C:2004 does not cover C99, so you simply cannot use inline at all.

And because of this, the rule about function definitions in header files strikes bluntly even at inline functions. There is no way you can conform to MISRA-C:2004 with the posted code - you will have to create deviations from several required rules.


My recommendation is to upgrade to MISRA-C:2012, which has an explicit exception for this scenario (rule 5.9):

Exception
An inline function with internal linkage may be defined in more than one translation unit provided that all such definitions are made in the same header file that is included in each translation unit.

MISRA-C:2012 also requires that all inline function must declared as static (rule 8.10).

MISRA-C:2012 is a much better document in almost every way. IAR have got support for the 2012 version too and their MISRA checker should be a separate plug-in not related to the specific MCU.


Unrelated to your actual question (int16u)1u << is completely wrong and dangerous.

If you actually must have signed types (most often you don't), then you must first carry out the shift on unsigned type, then convert to signed.

This is not just needed for MISRA-C compliance, but to fix a blatant C bug that invokes undefined behavior on 8 and 16 bit MCUs, when you left shift data into the sign bit.

Correct code should be int16uVar |= (int16u)(1u << int16uBitIndex); and I believe this also sates the MISRA-C:2004 requirements about casting to the underlying type after the operation.


Also note that creating your own "garage standard" integer types is frowned upon in general - since you are using C99 you should be using stdint.h and nothing else. This is also the MISRA-C:2012 recommendation.

1
On

Thank you Lundin for your helpful reply. About the second part of your reply, I should say that in our coding style we use int16u for unsigned int types. that is

typedef unsigned int int16u

So I'm shifting the unsigned int not signed int. there is a typing error in my question and that is, I have written

int16uVar |= ( (int16u)1u << (int16uBitIndex) );

but the correct line in my code is

int16uVar |= ( (int16u)1 << (int16uBitIndex) );

I do apologize.

0
On

In simple terms, inline is not part of C90 (as covered by MISRA C:2004)

However, there is a workaround, if you adopt MISRA Compliance... this introduces the concept of Deviation Permits, and the MISRA team conveniently provide you with such a Permit for using inline (Permit/MISRA/C:2004/1.1.C.1)

Of course, most compilers simply ignore the inline qualifier anyway...

Declaration of Interest: See profile!