4

I'm currently dealing with some MISRA issues and therefore trying to understand the integer conversion rules in C.

I'm getting a violation of MISRA-C 2004 rule 12.9 The unary minus operator shall not be applied to an expression whose underlying type is unsigned

in the code line

signed long int test = -1;

I understand that there is no negative integer constant "-1", but rather the unary minus applied to the integer constant "1" (as stated in https://en.cppreference.com/w/c/language/integer_constant).

The integer constant "1" however is of the first type in the list int, long int, unsigned long int (until C99), long long int (since C99)

I'm compling with Keil (ARM 32 bits) and the --c99 flag set, while MISRA-C 2004 seems to be based on the C90 standard.

So it seems as my SCA tool is assuming the "1" constant is of type unsigned long int (until C99), but I can't see, why it wouldn't fit in an ordinary int and therefore be signed.

To satisfy the SCA tool, one has to code

signed long int test = -1L;

or

signed long int test = -((signed long int) 1);

Is this correct behaviour or am I missing something here?

RobertAlpha
  • 75
  • 1
  • 6
  • 1
    Curious, still get 12.9 violation with `signed long int test = 0 - 1;`? – chux - Reinstate Monica Apr 02 '20 at 10:41
  • 2
    Yet another bug in whatever tool is doing the analyzing. MISRAble – M.M Apr 02 '20 at 10:42
  • 1
    Well, it is always a good idea to add suffices to make things clear. ;-) – the busybee Apr 02 '20 at 10:42
  • @chux-ReinstateMonica No, that calculation is compliant, but imo too puzzling to actually use ;) – RobertAlpha Apr 02 '20 at 13:48
  • 2
    Actually I just remembered that there is a rule against implicit conversions to different types if the expression in a so-called "complex expression" (MISRA-C term), which is defined as everything that isn't either a constant expression, a lvalue or a function return value. In this case `-1` is a constant expression (as is `0 - 1`), so that rule does not apply. – Lundin Apr 02 '20 at 14:22
  • @thebusybee Interestingly, the line `signed short int test = -1;` is not compliant, either, and since there is no short-suffix, it really seems to be a tool bug :/ – RobertAlpha Apr 02 '20 at 14:39
  • Oops. Nice find! Tools are only humans\b\b\b\b\b\bwritten by humans. :-D – the busybee Apr 02 '20 at 15:01
  • @RobertAlpha Please don't mix up the term compliant with "strange warning from my potentially broken static analyser" :) – Lundin Apr 03 '20 at 06:36

1 Answers1

5

The integer constant "1" however is of the first type in the list int, long int, unsigned long int...

Correct. Integer constants like 1 are of type int and as far as MISRA-C is concerned, the underlying type is also int. The definition is (MISRA-C:2004 6.10.4)

The term "underlying type" is defined as describing the type that would be obtained from evaluating an expression if it were not for the effects of integral promotion.

The line signed long int test = -1; is MISRA-C:2004 (and MISRA-C:2012) compliant.

  • The expression -1 contains no implicit promotions in itself. Integral promotion does not apply.
  • Thus -1 has underlying type signed int and upon assignment, it is implicitly converted to a wider integer type with the same signedness, which is fine.
  • The intention is to create a signed variable, so the rule about u suffix does not apply.
  • Furthermore, the rule 10.1 against implicit conversions from a so-called "complex expression" into different a type does not apply either, since -1 is a constant expression, not a complex expression (see MISRA-C:2004 6.10.5).

So this is yet another tool bug. The tool seems to picking the wrong underlying type of an expression, which would be a severe bug.

signed long int test = -1L; is not necessary for compliance, although it is also compliant code.

Lundin
  • 195,001
  • 40
  • 254
  • 396