The warning introduced in bug 62183 is trigger-happy. int foo (int a, int b) { // Make it obvious that these are booleans. a = !!a; b = !!b; return !a == b; } # gcc --version gcc (Ubuntu 5.4.0-6ubuntu1~16.04.2) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # gcc -c -Wall -O2 bbb.c bbb.c: In function ‘foo’: bbb.c:8:13: warning: logical not is only applied to the left hand side of comparison [-Wlogical-not-parentheses] return !a == b; ^ This is silly and out-right illogical when "a" and "b" are booleans. "!a == b" means the same as "!(a == b)", so the warning is pointing out that I might have meant something else that, upon inspection, is seen to be the same thing. Note: by "boolean" I mean an integer with value 0 or 1.
Well, // Make it obvious that these are booleans. a = !!a; b = !!b; this isn't visible to the compiler when it analyzes return !a == b; to warn. Your example is very specific and unlike from real code so are you complaining about return !a == b; warning even when it is not immediately preceeded by a a = !!a; stmt? Then we've discussed this to death already.
Not a bug, IMHO.
The actual code I got this warning from was... if (!lower_tail == (p > phalf)) { where lower_tail is an int and p and phalf are doubles. That's simply a comparison of two booleans. Note, that the hinted-at code !(lower_tail == (p > phalf)) is dubious: comparing an int to a booleans. > this isn't visible to the compiler when it analyzes > return !a == b; I am not aware of a rule that requires the compiler to ignore context when considering warnings. It certainly does consider context when it issues "might be used uninitialized" warnings, so why not here?
Note that Clang suggests two ways to silence the warning: prog.cc:9:10: note: add parentheses after the '!' to evaluate the comparison first return !a == b; ^ ( ) prog.cc:9:10: note: add parentheses around left hand side expression to silence this warning return !a == b; ^ ( ) Also, we do not warn for actual booleans (bool). To be able to not warn based on the runtime range of variables, we would need something like VRP in the FE, and that is unlikely to be implemented in the medium future.
(In reply to M Welinder from comment #3) > The actual code I got this warning from was... > > if (!lower_tail == (p > phalf)) { > > where lower_tail is an int and p and phalf are doubles. Well, that changes things because I agree that in the above case the warning is bogus. > That's simply a comparison of two booleans. Note, that the hinted-at code > > !(lower_tail == (p > phalf)) > > is dubious: comparing an int to a booleans. > > > this isn't visible to the compiler when it analyzes > > return !a == b; > > I am not aware of a rule that requires the compiler to ignore context > when considering warnings. It certainly does consider context when > it issues "might be used uninitialized" warnings, so why not here? Because it's not done as in the frontend there is no data-flow available. So, testcase: int foo (int a, int b) { return !a == (a < b); } t.c: In function ‘foo’: t.c:4:13: warning: logical not is only applied to the left hand side of comparison [-Wlogical-not-parentheses] return !a == (a < b); ^~
(In reply to Manuel López-Ibáñez from comment #4) > Note that Clang suggests two ways to silence the warning: > > prog.cc:9:10: note: add parentheses after the '!' to evaluate the comparison > first > return !a == b; > ^ > ( ) > prog.cc:9:10: note: add parentheses around left hand side expression to > silence this warning > return !a == b; > ^ > ( ) I guess I should employ here the fix-it feature we now have... > Also, we do not warn for actual booleans (bool). This is intentional. > To be able to not warn based on the runtime range of variables, we would > need something like VRP in the FE, and that is unlikely to be implemented in > the medium future. ...if ever.
Clang doesn't warn about this.
Neither does cc1plus because comparison result has a boolean type... I'll see what I can do here.
(In reply to M Welinder from comment #3) > I am not aware of a rule that requires the compiler to ignore context > when considering warnings. It certainly does consider context when > it issues "might be used uninitialized" warnings, so why not here? Wuninitialized warnings are implemented in the middle-end. They benefit from the analysis done by optimization, but also suffer from the optimizations transforming and removing code (PR18501 and http://gcc.gnu.org/wiki/Better_Uninitialized_Warnings). Warnings in the FE, like this one, are more consistent but there is very limited analysis done in the FE (because it is harder to implement in the FE, it may slow down the compiler and would duplicate the analysis done in the middle-end for optimization).
(In reply to Richard Biener from comment #5) > int > foo (int a, int b) > { > return !a == (a < b); > } > > t.c: In function ‘foo’: > t.c:4:13: warning: logical not is only applied to the left hand side of > comparison [-Wlogical-not-parentheses] > return !a == (a < b); > ^~ Why is this not a valid warning? #include <stdio.h> void foo (int a, bool b) { printf("(!a) == b -> %d\n", (int) (!a) == b); printf("!(a == b) -> %d\n", (int) !(a == b)); } int main() { foo(2,1); } (!a) == b -> 0 !(a == b) -> 1
(In reply to Manuel López-Ibáñez from comment #4) > Note that Clang suggests two ways to silence the warning: > > prog.cc:9:10: note: add parentheses after the '!' to evaluate the comparison > first > return !a == b; > ^ > ( ) > prog.cc:9:10: note: add parentheses around left hand side expression to > silence this warning > return !a == b; > ^ > ( ) Both of these suggestions are not so good. "!(a == b)" is better written as "a != b", and "!(a) == b" is just horrible.
(In reply to Segher Boessenkool from comment #11) > Both of these suggestions are not so good. "!(a == b)" is better written > as "a != b", and "!(a) == b" is just horrible. Agreed for the former, but the latter is suggesting (!a) == b, which is IMHO clearer than ! a == b.
(In reply to Manuel López-Ibáñez from comment #12) > (In reply to Segher Boessenkool from comment #11) > > Both of these suggestions are not so good. "!(a == b)" is better written > > as "a != b", and "!(a) == b" is just horrible. > > Agreed for the former, but the latter is suggesting (!a) == b, which is IMHO > clearer than ! a == b. Ah. The parens are placed suggestively around the "a" in the suggestion, so it is misleading even :-/ (Or maybe I'm just not very good at reading).
(In reply to Manuel López-Ibáñez from comment #10) > > t.c:4:13: warning: logical not is only applied to the left hand side of > > comparison [-Wlogical-not-parentheses] > > return !a == (a < b); > > ^~ > > Why is this not a valid warning? Ah, this is on purpose to avoid too many false positives. Sorry for the noise.
Author: mpolacek Date: Mon Aug 29 18:13:13 2016 New Revision: 239833 URL: https://gcc.gnu.org/viewcvs?rev=239833&root=gcc&view=rev Log: PR c/77292 * c-common.c (warn_logical_not_parentheses): Don't warn for a comparison or a logical operator. * c-c++-common/Wlogical-not-parentheses-1.c: New test. Added: trunk/gcc/testsuite/c-c++-common/Wlogical-not-parentheses-1.c Modified: trunk/gcc/c-family/ChangeLog trunk/gcc/c-family/c-common.c trunk/gcc/testsuite/ChangeLog
Fixed.