Bug 8715 - '~' operator for unsigned char and conversion to bool
Summary: '~' operator for unsigned char and conversion to bool
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.2
: P3 enhancement
Target Milestone: 4.4.0
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2002-11-26 05:26 UTC by jozef.kosoru
Modified: 2022-10-31 01:59 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-12-10 19:17:48


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description jozef.kosoru 2002-11-26 05:26:04 UTC
gcc gives the warning when compiling the following code with -Wall:

int main()
{
    unsigned char b = '1';

    bool x = ~b;

    return 0;
}

test.cpp:5: warning: comparison of promoted ~unsigned with constant

g++ has the same behaviour.

Release:
gcc-3.2
Comment 1 Richard Earnshaw 2002-11-26 17:45:54 UTC
From: Richard Earnshaw <rearnsha@arm.com>
To: jozef.kosoru@pobox.sk
Cc: gcc-gnats@gcc.gnu.org, Richard.Earnshaw@arm.com
Subject: Re: c/8715: '~' operator for unsigned char and conversion to bool 
Date: Tue, 26 Nov 2002 17:45:54 +0000

  
 > int main()
 > {
 >     unsigned char b = '1';
 > 
 >     bool x = ~b;
 > 
 >     return 0;
 > }
 > 
 
 Which is equivalent to writing
 
 	unsigned char b = 0x31;
 	bool x = (~(int) b) != 0;
 
 which collapses to 
 
 	bool x = 1;
 
 > test.cpp:5: warning: comparison of promoted ~unsigned with constant
 
 A warning would probably seem appropriate. since no value of b can lead to 
 the x being set to 0.
 
 
 
Comment 2 Wolfgang Bangerth 2002-12-04 14:08:39 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Richard Earnshaw has already analyzed this. However, I
    concur with the submitter that the message as is is
    rather misleading.
Comment 3 Joseph S. Myers 2004-09-24 22:35:41 UTC
Bogus message only appears for C++, not C.
Comment 4 Manuel López-Ibáñez 2006-12-10 19:17:48 UTC
(In reply to comment #3)
> Bogus message only appears for C++, not C.
> 

Not anymore. I get the warning for C with gcc (GCC) 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5) using -Wsign-compare (which is included in -Wextra).

Is this really a bug?
Comment 5 Manuel López-Ibáñez 2006-12-10 19:28:36 UTC
(In reply to comment #1)
>  
>  Which is equivalent to writing
>  
>  	unsigned char b = 0x31;
>  	bool x = (~(int) b) != 0;
>  

b being promoted to int is the expected behaviour or is it just what happens currently? I don't get why it is promoted...

>  A warning would probably seem appropriate. since no value of b can lead to 
>  the x being set to 0.

What is kind of weird since I would expect any value different from 0 to set x to false.
Comment 6 Manuel López-Ibáñez 2007-01-26 16:00:55 UTC
OK. I see now. This seems hard to fix, since it is exposing the current implementation of a conversion to bool.
Comment 7 Richard Earnshaw 2007-01-26 16:46:15 UTC
(In reply to comment #6)
> OK. I see now. This seems hard to fix, since it is exposing the current
> implementation of a conversion to bool.
> 

No, it's not the 'current implementation', its the way the C and C++ standards say this has to happen.  When arithmetic operators are applied to sub-int sized operands they are first converted to int (or unsigned int if they can't be represented in int -- which is only the case when you have a machine where sizeof(unsigned short) == sizeof(unsigned int), or something similar).
Comment 8 Manuel López-Ibáñez 2007-01-26 16:56:17 UTC
(In reply to comment #7)
> (In reply to comment #6)
> > OK. I see now. This seems hard to fix, since it is exposing the current
> > implementation of a conversion to bool.
> > 
> 
> No, it's not the 'current implementation', its the way the C and C++ standards
> say this has to happen.  When arithmetic operators are applied to sub-int sized
> operands they are first converted to int (or unsigned int if they can't be
> represented in int -- which is only the case when you have a machine where
> sizeof(unsigned short) == sizeof(unsigned int), or something similar).
> 

I think I expressed myself badly. I meant that the warning is appropriate but the message is confusing because it is exposing that when doing 

bool x = ~b; 

we actually do 

bool x = (~b != 0);

So an appropriate message would say something like:

test.cpp:5: warning: '(bool) ~b' is always true


But that is hard to achieve with the current implementation.

Don't you agree?
Comment 9 Richard Earnshaw 2007-01-26 17:03:28 UTC
(In reply to comment #8)
> I meant that the warning is appropriate but
> the message is confusing because it is exposing that when doing 
> 
> bool x = ~b; 
> 
> we actually do 
> 
> bool x = (~b != 0);
> 
Or, more precisely, 
  bool x = (~(int) b) != 0;

> So an appropriate message would say something like:
> 
> test.cpp:5: warning: '(bool) ~b' is always true
 
> Don't you agree?
> 

Yes, that would be nice, but hard to implement.
Comment 10 Manuel López-Ibáñez 2007-02-16 15:33:25 UTC
(In reply to comment #9)
> (In reply to comment #8)
> > I meant that the warning is appropriate but
> > the message is confusing because it is exposing that when doing 
> > 
> > bool x = ~b; 
> > 
> > we actually do 
> > 
> > bool x = (~b != 0);
> > 
> Or, more precisely, 
>   bool x = (~(int) b) != 0;
> 
> > So an appropriate message would say something like:
> > 
> > test.cpp:5: warning: '(bool) ~b' is always true
> 
> > Don't you agree?
> > 
> 
> Yes, that would be nice, but hard to implement.
> 

Isn't any way to tell that "!= 0" was introduced by GCC rather than by the original source code?
Comment 11 Manuel López-Ibáñez 2008-08-06 16:19:03 UTC
Subject: Bug 8715

Author: manu
Date: Wed Aug  6 16:17:41 2008
New Revision: 138814

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=138814
Log:
2008-08-06  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

	PR 8715
	* c-common.c (warn_for_sign_compare): New. Handle separately the
	case that 'constant' is zero.
	* c-typeck.c (build_binary_op): Move code to c-common.c
cp/
	* typeck.c (cp_build_binary_op): Move code to c-common.c.
testsuite/
	* gcc.dg/pr8715.c: New.
	* g++.dg/warn/pr8715.C: New.

Added:
    trunk/gcc/testsuite/g++.dg/warn/pr8715.C
    trunk/gcc/testsuite/gcc.dg/pr8715.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/c-common.c
    trunk/gcc/c-common.h
    trunk/gcc/c-typeck.c
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/typeck.c
    trunk/gcc/testsuite/ChangeLog

Comment 12 Manuel López-Ibáñez 2008-08-06 16:33:41 UTC
Fixed in GCC 4.4.