bug ? : -Wpedantic -Wconversion 'short a=1; a-=1;' complaint

Jason Vas Dias jason.vas.dias@gmail.com
Wed May 16 13:58:00 GMT 2018

Great thanks for your informative response, Jim! :
On 23/04/2018, Jim Wilson <jimw@sifive.com> wrote:
> On 04/23/2018 07:11 AM, Jason Vas Dias wrote:
>> I really do not think a '-Wpedantic -Wconversion' warning should
>> be generated for the following code, but it is
>> (with GCC 6.4.1 and 7.3.1 on RHEL-7.5 Linux) :
>>   $ echo '
>>   typedef unsigned short U16_t;
>>   static void f(void)
>>   { U16_t a = 1;
>>     a-=1;
>>   }' > t.C;
> gcc@gcc.gnu.org dropped as inappropriate.  Note that gcc-bugs is output
> from our bugzilla.  Sending email here isn't very useful.  If you want a
> bug fixed, you have to open a bug report in bugzilla.  You can ask gcc
> questions on gcc help.
> In the C language, operations on short and always performed as int, and
> then converted back to short.  Subtracting one may generated a negative
> number, which converted to unsigned short will change its value.  So the
> warning seems appropriate.
> Note that -Wconversion means different things in different gcc versions.
>   It current meaning is to warn for any implicit cast that may change a
> value.  This is not very useful in general, and is not an option that I
> would recommend using by default.  In old gcc versions, -Wconversion
> warned for code that had different meaning in K&R C and ISO C.  That was
> useful, and some people used that option by default, but the option no
> longer does that.
> You can silence the warning by adding an explicit cast.
>     a = (U16_t) (a - 1);
> Jim

But I still think, in modern GCC, the behaviour of this warning option is a bug.
When I look at the code generated for the above example, I can see
the compiler is actually generating 16-bit operations:

$ gcc -std=c11 -Wall -Wextra -pedantic -Wconversion -S -o u16.s u16.c
u16.c: In function ‘f’:
u16.c:9:6: warning: conversion to ‘U16_t {aka short unsigned int}’
from ‘int’ may alter its value [-Wconversion]

But looking at the assembler generated :

	movw	$1, -2(%rbp)
	subw	$1, -2(%rbp)

we see that on x86_64 at least, the compiler is actually generating
16-bit operations on two-byte values.

I can understand that on architectures such as ARM , it might be
appropriate to generate the warning, because on that platform,
a 32-bit operation may actually be generated for the code.
But if no 32-bit operation is being generated, why issue the warning?

So it is not the case that
> In the C language, operations on short are always performed as int, and
> then converted back to short .

That may have been true with ANSI C90, but not with more recent versions
of the C language; surely GCC should know what standard & CPU it is generating
code for, and emit appropriate warnings for that standard and CPU ?

And your suggested fix illustrates my point about the warning encouraging
unnecessary casts:
> You can silence the warning by adding an explicit cast.
>     a = (U16_t) (a - 1);
Actually, in this case, gcc is clever enough to realize that a cast is
not required,
and actually generates identical code with or without the cast:

        movw	$1, -2(%rbp)
	subw	$1, -2(%rbp)

But C++ programmers are encouraged to look at any C-style "(X)y" cast as
"Create an anonymous Temporary to hold y cast to type X " .
Even though that is not what is going on here, I think the warning does
not help programmers understand what code is being generated
(the 16-bit operations) and incorrectly makes them think a 32-bit
temporary is being generated.

So I think that '-Wconversion' should have no effect if '-pedantic'
is in effect,
because that combination produces erroneous and misleading warnings .

Thanks & Best Regards,

More information about the Gcc-bugs mailing list