[cfe-users] -Wconversion does not produce warnings when it should

Sven Köhler via cfe-users cfe-users at lists.llvm.org
Mon Nov 16 12:36:20 PST 2020


Hi,

consider the following code:

uint16_t testa4(uint8_t x, uint8_t y) {
    return ( (uint16_t)x << 0 )
            | ( (uint16_t)y << 8 );
}
uint16_t testb3(uint16_t x, uint16_t y) {
    return x|y;
}
uint16_t testb4(uint16_t x, uint16_t y) {
    return x+y;
}
int testb4x(uint16_t x, uint16_t y) {
    return x+y;
}



I'm using clang 11.0.0 on Intel x86_64 and when I compile the above code
with -Wconversion enabled, then I see only one warning, namely for testa4.

However, according to the C standard, the expression after the return
statement has type int in all 4 cases. So why is the warning not
triggered for testb3 and testb4?

In fact, it's convenient that testb3 does not trigger a warning. Yes, x
and y are promoted to int before the bitwise or is performed, but the
result indeed fits into an uint16_t, regardless of x and y. So if clang
is smart and keeps track of the range of the expressions, then it is
understandable that there is no warning for testb3. However, then the
"keeping track of ranges" feature seems to fail for testa4, because
there a warning is indeed produced even though the two operands of the
bitwise-or are both uint16_t.

However, the case of testb4 is different. If we set x an y to 0xFFFF,
then the result will be 0x1FFFE. You can confirm that this is the case
by running testb4x. Then, shouldn't testb4 trigger a warning? The result
is clearly and int _and_ the result may not fit into an uint16_t.


I'm lost. As far as I understand, -Wconversion should issue a warning
when an int is converted to uint16_t without an explicit cast. For all I
know, x+y and x|y are ints, yet there is no warning in testb3 and
testb4. This seems like a bug to me.


Can you elaborate what is happening here?


Kind Regards,
  Sven



More information about the cfe-users mailing list