I've been facing this MISRA violation:


Definitions:

#define A                 (1UL << 10)
#define INIT_A            ((A) | (1UL << 15))
#define INIT_A_MASK       (0xFFFFUL << 15)


#define IS_STATE_IFSET(state, val)  ((((state) & (val##_MASK)) == (val)) ? true : false)   //issue is here ?

Caller Details:

uint64_t state = 1234UL;
if (!IS_STATE_IFSET(state, INIT_A)) {
    printf("Hoo-Haa\n");
}

Misra-2012 reports Rule 20.12 violation misra_c_2012_rule_20_12_violation: macro parameter "val" is used in both expanded and raw forms

2

There are 2 best solutions below

3
Lundin On

MISRA-C thinks it's stupid idea to use the same pre-processor constant twice in the same macro, where you have it expand in one case but not expand in another.

In your macro val##_MASK will not be expanded, so you getINIT_A_MASK. But later in the very same macro val is also expanded and replaced with ((A) | (1UL << 15)).

The only acceptable solution is to rewrite all of this crazy code from scratch and get rid of all use of secret macro languages.

For example, just what is the meaning of #define A (1UL < 10)? I assume << was intended. If not for the secret macro language, bugs like these are easy to find. But instead, you injected a hard-to-find dormant bug in your application.

0
Richard at ImageCraft On

Not sure if this can ever work in any case, when you write "if (!IS_STATE_IFSET(state, INIT_A))", the INIT_A will immediately be expanded into its macro definition, and the name will not be passed to the definition of IS_STATE_IFSET in the first place. I guess this is a case where your MISRA checker is behaving differently from a real C preprocessor.