LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

CVI2013: warning: implicit conversion changes signedness: 'long' to 'int'

Solved!
Go to solution

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;
}

 

-----------------------
/* Nothing past this point should fail if the code is working as intended */
0 Kudos
Message 1 of 8
(13,652 Views)

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.

0 Kudos
Message 2 of 8
(13,644 Views)

But isn't long (here) the same as int?

And both are signed.

-----------------------
/* Nothing past this point should fail if the code is working as intended */
0 Kudos
Message 3 of 8
(13,636 Views)

long int by definition could also be longer than int, that's why I assume it's not an error but a warning.

0 Kudos
Message 4 of 8
(13,633 Views)

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.

-----------------------
/* Nothing past this point should fail if the code is working as intended */
0 Kudos
Message 5 of 8
(13,604 Views)

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

Daniel Dorroh
National Instruments
0 Kudos
Message 6 of 8
(13,525 Views)
Solution
Accepted by topic author CVI-User

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

Message 7 of 8
(13,483 Views)

Hello Peter,

 

Thanks for the effort!

 

It would be interesting to see the discussion that lead to this special case.

I'm just curious...

-----------------------
/* Nothing past this point should fail if the code is working as intended */
0 Kudos
Message 8 of 8
(13,456 Views)