Consider the following code: extern bool f(int n); void g(int a, int b) { if (f(a) == 2) f(b); } gcc says nothing $ g++ -c -O2 -Wall -Wextra -ansi -pedantic mar26b.cc clang has more to say $ clang++ -c !$ clang++ -c mar26b.cc mar26b.cc:7:11: warning: comparison of constant 2 with expression of type 'bool' is always false [-Wtautological-constant-out-of-range-compare] if (f(a) == 2) ~~~~ ^ ~ 1 warning generated. I've just built gcc trunk with clang and it looks as if producing a similar warning to clang will flush out five bugs in gcc trunk.
Confirmed. The same for the C FE.
Put a break-point in build_binary_op then figure out where to warn (probably in EQ_EXPR and NE_EXPR and other logical operators). Use debug_tree() to examine the operands and figure out how to detect the correct cases.
(In reply to David Binderman from comment #0) > I've just built gcc trunk with clang and it looks as if producing > a similar warning to clang will flush out five bugs in gcc trunk. Five is now one. $ fgrep "Wtautological-constant-out-of-range-compare" mk.out ../../src/trunk/gcc/expr.c:5230:9: warning: comparison of constant -1 with expression of type 'unsigned int' is always false [-Wtautological-constant-out-of-range-compare] $ if (!SUBREG_CHECK_PROMOTED_SIGN (target, TYPE_UNSIGNED (TREE_TYPE (exp)))) { However, for a build of most of Redhat Linux with clang, there are about 460 occurrences of this warning, so it still looks to be of value for the wider world.
(In reply to David Binderman from comment #3) > $ fgrep "Wtautological-constant-out-of-range-compare" mk.out > ../../src/trunk/gcc/expr.c:5230:9: warning: comparison of constant -1 with > expression of type 'unsigned int' is always false > [-Wtautological-constant-out-of-range-compare] > $ > > if (!SUBREG_CHECK_PROMOTED_SIGN (target, > TYPE_UNSIGNED (TREE_TYPE (exp)))) > { > Actually, recent gcc/g++ both warn for your testcase in comment #1: /home/manuel/test.c:7:12: warning: comparison of constant ‘2’ with boolean expression is always false [-Wbool-compare] if (f(a) == 2) ^ David, would you mind testing with a recent revision? In those cases where Clang warns and GCC doesn't, could you figure out a minimal testcase? Thanks!
(In reply to Manuel López-Ibáñez from comment #4) > David, would you mind testing with a recent revision? In those cases where > Clang warns and GCC doesn't, could you figure out a minimal testcase? Thanks! I tested with gcc trunk revision 216125. All seems ok and so no testcase needed. This looks fixed to me, with the possible exception of the remaining warning in gcc trunk source code.
(In reply to David Binderman from comment #5) > This looks fixed to me, with the possible exception of the remaining > warning in gcc trunk source code. I think it is a different warning for which clang uses the same switch (-Wbool-compare only warns about boolean expressions). It is also not obvious that there is a bug there. Perhaps it is a false positive by Clang.
(In reply to Manuel López-Ibáñez from comment #6) > I think it is a different warning for which clang uses the same switch > (-Wbool-compare only warns about boolean expressions). It is also not > obvious that there is a bug there. Perhaps it is a false positive by Clang. I looked into this and the definition of SUBREG_CHECK_PROMOTED_SIGN around line 2200 of gcc/rtl.h seems important. #define SUBREG_CHECK_PROMOTED_SIGN(RTX, SIGN) \ ((SIGN) == SRP_POINTER ? SUBREG_PROMOTED_GET (RTX) == SRP_POINTER \ : (SIGN) == SRP_SIGNED ? SUBREG_PROMOTED_SIGNED_P (RTX) \ : SUBREG_PROMOTED_UNSIGNED_P (RTX)) Leaving aside the side issue of ? : being right associative, so some () would help clarify, I notice that const int SRP_POINTER = -1; const int SRP_SIGNED = 0; const int SRP_UNSIGNED = 1; const int SRP_SIGNED_AND_UNSIGNED = 2; so it looks as if this bitfield unsigned unsigned_flag : 1; is being compared to SRP_POINTER. One possible fix might be to change the value of SRP_POINTER to 3 and see if the problem goes away. Clang certainly seems to be finding a problem, AFAIK.
(In reply to David Binderman from comment #7) > > #define SUBREG_CHECK_PROMOTED_SIGN(RTX, SIGN) \ > ((SIGN) == SRP_POINTER ? SUBREG_PROMOTED_GET (RTX) == SRP_POINTER \ > : (SIGN) == SRP_SIGNED ? SUBREG_PROMOTED_SIGNED_P (RTX) \ > : SUBREG_PROMOTED_UNSIGNED_P (RTX)) > > Leaving aside the side issue of ? : being right associative, > so some () would help clarify, I notice that > > const int SRP_POINTER = -1; > const int SRP_SIGNED = 0; > const int SRP_UNSIGNED = 1; > const int SRP_SIGNED_AND_UNSIGNED = 2; > > so it looks as if this bitfield > > unsigned unsigned_flag : 1; > > is being compared to SRP_POINTER. One possible fix might be to change > the value of SRP_POINTER to 3 and see if the problem goes away. > > Clang certainly seems to be finding a problem, AFAIK. It seems to me that independently of the value of SRP_POINTER, the result will be always false. Thus, I don't see the bug. In any case, someone else would need to decide whether this is actually a bug or not. RTL is not my expertise.