Compiler: CW HC08 6.0.
Can anyone explain why I get a compiler warning from the following code?
#define SLPRQ 0x02U
CANCTL0 &= (uint8)~SLPRQ; /* "Warning : C705 Possible loss of data". */
If I however #define SLPRQ as 0x02 (signed int), I don't get a warning. I don't understand this. How exactly am I losing data if SLPRQ is unsigned int, but not if it is signed? No matter if it is signed or unsigned, no integer promotions take place: the type is already unsigned int. As the expression is unary, the "usual arithmetic conversions" don't take place either. So how can there be a "possible loss of data" when no implicit conversions exist?
I was assuming this had to do with CANCTL0 being an uint8, and if I change the type of CANCTL0 from uint8 to uint16, the warning indeed disappears. Apparently CW doesn't give a darn about my explicit typecast to uint8.
But... to confuse things further, the warning disappears if I alter the code:
This yields no warning! Even though integer promotions will silently promote the type to "int". So there is a silent change of signedness, which actually could be a grave bug. But that possible bug yields no warning.
How does any of this make sense?
Maybe the warning has something to do with the cast and the ~ operator having equal precedence, and the lack of parenthesis, i.e. whether the cast is to be applied before or after the bitwise operator.
Since the expression involves only bitwise operators, the cast would seem unnecessary to me. Additionally, would the two hexadecimal numbers 0x02U and 0x02 ever result in different values for the expression?
The order of the operator evaluation is well-defined by the C standard. The ~ operator and the (type) operator has same precedence. If they occur on the same line, they are to be evaluated right-to-left.
The typecast is there to narrow down the result of the ~ operator, which is an "int" and not an uint8 as desired. It is there to conform with MISRA-C, which is picky about always typecasting towards the intended type, no matter whether it affects the result or not.
Mac, the order of ~ and () is specified and can't be reversed. Result of these two lines is different:
int c = ~(uint8)1; // c = 0xFFFE
int c= (uint8)~1; // c = 0xFE
In the first line 1 is converted to u8, then promoted to int, then inverted. In second - ~1=0xFFFE, (uint8)0xFFFE = 0xFE.
In CANCTL0 &= (uint8)~SLPRQ; , I think, warning is generated because result of (uint8)~SLPRQ is again promoted to int just before & operation. Why compiler doesn't complain about CANCTL0 &= ~(uint8)SLPRQ; ? Isn't it because of optimizer?
This one doesn't depend on promotion rules and gives no warning:
CANCTL0 = (uint8)(CANCTL0 & ~SLPRQ);
The compiler doesn't seem consistent, it only seems to warns for implicit promotions if both operands are silently promoted, and not if just one of them is. The ~ operator only has one operand, so no warning there. If we break down these statments it seems to be the case:
CANCTL0 &= ~SLPRQ;
~(uint8) /* One uint8 operator silently promoted to int. No warning. */
(uint8) & (int) /* One uint8 operator silently promoted to int. No warning. */
While CANCTL0 &= (uint8)~SLPRQ; gives (uint8) & (uint8) and then a warning.
I guess I'll just disable the "possible loss" warning...
Do you want to say that this ^^ doesn't produce warning? But it does, unless you removed 'u' from SLPRQ define and made it signed. Yes, it's weird and compiler doesn't seem consistent on these warnings.
BTW, another weird thing:
foo(); // C1420 warning, result of function call is ignored
if(c) foo(); // no C1420 warning. Is foo() return value used in if(c) ?
> Do you want to say that this ^^ doesn't produce warning? But it does, unless you removed 'u' from SLPRQ define and made it signed. Yes, it's weird and compiler doesn't seem consistent on these warnings.
It does... ok then I don't understand a thing about these warnings, they seem completely illogical.