10-24-2013 03:46 AM
What is Clang trying to tell me with this warning?
int f( void ) { int i1 = 4; int i2 = 1l << ( i1 - 1 ); // ^^ warning: implicit conversion changes signedness: 'long' to 'int' [-Wsign-conversion] return i2; }
Solved! Go to Solution.
10-24-2013 05:17 AM
I would assume that It tries to tell you that type conversion may result in the loss of data, i.e. bits. Because one of the bits is used to indicate sign a truncation from long to int may loose this sign information.
10-24-2013 06:00 AM
But isn't long (here) the same as int?
And both are signed.
10-24-2013 06:15 AM
long int by definition could also be longer than int, that's why I assume it's not an error but a warning.
10-29-2013 04:42 AM
Agreed. But if that warning is shown because of a possible portability issue, then why is this OK:
int f( long l ) { return l; }
It's an implicit 'long' to 'int' conversion, too.
11-27-2013 12:55 PM
Hi,
I am currently looking into this warning. I believe clang is giving you a warning because you are using a data type sensitive operator, <<
. If you replace <<
with +
, for example, clang does not give this warning. I can update this post when I have more definitive information.
Thanks,
Daniel
12-03-2013 05:01 AM
Hello CVI-User!
The explanation is rather technical...
The result type of the shift expression is 'signed long'. The target type of the initialization is 'signed int'. Clang injects an implicit conversion from 'signed long' to 'signed int' and checks various properties of the conversion.
In particular, clang tests if the sign of the value might change during the conversion. For this test, clang computes the "value range" of the source '1L << (i1 - 1)' and the "value range" of the target 'int i2'. The warning indicates that the signs of the source and target ranges do not match.
The value range of the source depends on the expression '1L << (i1 - 1)' and here clang is applying a special case:
[excerpt from GetExprRange in the clang 2.9 source code]
// Left shift gets black-listed based on a judgement call. // ...except that we want to treat '1 << (blah)' as logically // positive. It's an important idiom.
So the source value range is: 32-bit wide, positive.
The value range of the target depends on the type of 'i2' and it's the default value range for 'signed int': 32-bit wide, positive or negative.
In other words: '1L << (i1 - 1)' is considered positive (unsigned) and it is converted to a signed value.
Note that this is really a special case and that you do not get the warning for other values:
int i2 = 2l << ( i1 - 1 ); //no warning
Unfortunately, I cannot explain why clang doesn't just compare source and target types, why it computes values ranges, and why '1 << (blah)' is treated specially. I don't know.
Peter
12-04-2013 03:30 AM
Hello Peter,
Thanks for the effort!
It would be interesting to see the discussion that lead to this special case.
I'm just curious...