3

I am somewhat stucked at a part of the code that gives MISRA C 2004 10.5 violation but am not able to figure out what exactly might be the cause.

I have defined this MACRO to get the power of 2.

The code which shows the violation is

#define tmM_pow2_16bit(x)   ((tm_uint16)((tm_uint16)1U<<((tm_uint16)x)))

The message that comes from the static analysis tool is

Shift left of signed quantity (int) [MISRA 2004 Rule 10.5, required]

Thank you

Ankit Shah
  • 97
  • 1
  • 11

3 Answers3

2

Most likely reason is that shift operator forces implicit promotion of (tm_uint16)1U to int type.

Remove the second cast to make sure that you shift unsigned type:

((tm_uint16)(1U<<((tm_uint16)x)))
user694733
  • 15,208
  • 2
  • 42
  • 68
  • Thank you for your input. I tried what you suggested but still get the following error **Violates MISRA 2004 Required Rule 10.5, Operators '~' and '<<' require recasting to underlying type for sub-integers** – Ankit Shah Aug 07 '18 at 12:16
  • @AnkitShah Sounds like a false positive by the tool then. 10.5 only applies to operands that are "small integer types", which isn't the case here. – Lundin Aug 07 '18 at 15:03
1

The problem is probably that the tool can't quite figure out what the underlying type is. I suspect it thinks the underlying type is unsigned int, since that's the type of 1U.

The cast (tm_uint16)1U is superfluous - on systems where int is 32 bit or larger, this will only force a conversion to a small integer type, which will then immediately get implicitly converted to int. That would be a MISRA-C:2004 violation, as no such implicit conversions that change the signedness may occur. I recommend studying Implicit type promotion rules.

(tm_uint16)x is also superfluous, as the right operand of the shift operators take no part in determining the result of the operand.

MISRA-C:2004 compatible code should simply be this:

#define tmM_pow2_16bit(x)   ( (tm_uint16)(1U << (x)) )

Assuming x is valid for the tm_uint16 type.

(Please note that MISRA-C also discourages the use of function-like macros.)

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    I would recommend parenthesizing `x` in the macro expansion, a much bigger problem than the MISRA-C supposed violation: `#define tmM_pow2_16bit(x) ( (tm_uint16)(1U << (x)) ) – chqrlie Aug 07 '18 at 15:44
  • 1
    @chqrlie Good point, I will fix. Oddly, that's actually not a MISRA requirement - MISRA only requires the outermost part of the expression in the macro to have parenthesis. – Lundin Aug 08 '18 at 06:14
  • The problem with MISRA's approach is they edict too many rules, not simple recommendations. If they enforced systematic macro argument parenthesization, some useful macro constructions would be disallowed. Many embedded C programmers write MISRA-C code without a good understanding of the actual meaning and consequences of all these casts and small type definitions. From my own experience auditing such projects, it makes code hard to read and does not prevent many breeds of bugs that have much worse consequences and are well hidden in a slew of insipid stupid casts. – chqrlie Aug 08 '18 at 08:49
  • 2
    @chqrlie Yeah that's the main problem with MISRA-C, you can't really use it if there isn't at least one experienced C veteran on the team, who can assist the others. Leaving beginners or intermediate skilled C programmers alone with a (often partially broken) MISRA checker tool, tends to cause more harm than good. – Lundin Aug 08 '18 at 08:54
  • Fair point @Lundin - but an unsupervised inexperienced programmer is a potential liability with or without MISRA... – Andrew Aug 09 '18 at 06:52
  • MISRA C:2012 Rule 20.7 should deal with the non-parenthesised parameters ;-) – Andrew Aug 09 '18 at 07:00
0

The tool used to check MISRA-C compliance seems broken, but in some sense, you are indeed left shifting a signed integer type int: on architectures where int is larger than 16 bits, (tm_uint16)1U is promoted to int before the shift takes place, but there is no problem since its value is positive anyway.

Note however that there is a much worse problem in this macro: x is not parenthesized in the expansion, causing unexpected behavior for non trivial expressions such as tmM_pow2_16bit(1|2).

You can probably fix the warning by removing the unnecessary casts:

#define tmM_pow2_16bit(x)   ((tm_uint16)(1U << (tm_uint16)(x)))

If the tools still complains about potential left shifting by a quantity larger than the bit-width of int, add a mask:

#define tmM_pow2_16bit(x)   ((tm_uint16)(1U << ((x) & 15U)))
chqrlie
  • 131,814
  • 10
  • 121
  • 189