Message ID | 20160902151352.GH3768@redhat.com |
---|---|
State | New |
Headers | show |
On 09/02/2016 05:13 PM, Marek Polacek wrote: > diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi > index 87da1f1..38d55d4 100644 > --- gcc/doc/invoke.texi > +++ gcc/doc/invoke.texi > @@ -5437,8 +5437,8 @@ if (a < 0 && a < 0) @{ @dots{} @} > @opindex Wlogical-not-parentheses > @opindex Wno-logical-not-parentheses > Warn about logical not used on the left hand side operand of a comparison. > -This option does not warn if the RHS operand is of a boolean type. Its > -purpose is to detect suspicious code like the following: > +This option does not warn if the right operand is considered to be a Boolean > +expression. Its purpose is to detect suspicious code like the following: I think "Boolean" shouldn't be capitalized. The patch looks ok to me otherwise. > + r += !a == (b | c); I do wonder whether we should give a different warning for this though. I personally prefer code involving bools to use || to show it's a logical operation. Bit-wise may indicate mistakes where the programmer thought he was operating on integers. Bernd
On Mon, Sep 05, 2016 at 12:35:13PM +0200, Bernd Schmidt wrote: > On 09/02/2016 05:13 PM, Marek Polacek wrote: > > diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi > > index 87da1f1..38d55d4 100644 > > --- gcc/doc/invoke.texi > > +++ gcc/doc/invoke.texi > > @@ -5437,8 +5437,8 @@ if (a < 0 && a < 0) @{ @dots{} @} > > @opindex Wlogical-not-parentheses > > @opindex Wno-logical-not-parentheses > > Warn about logical not used on the left hand side operand of a comparison. > > -This option does not warn if the RHS operand is of a boolean type. Its > > -purpose is to detect suspicious code like the following: > > +This option does not warn if the right operand is considered to be a Boolean > > +expression. Its purpose is to detect suspicious code like the following: > > I think "Boolean" shouldn't be capitalized. The patch looks ok to me > otherwise. No strong opinions, but looking at https://en.wikipedia.org/wiki/Boolean_expression I see that it's capitalized there, so I think let's keep "Boolean". > > + r += !a == (b | c); > > I do wonder whether we should give a different warning for this though. I > personally prefer code involving bools to use || to show it's a logical > operation. Bit-wise may indicate mistakes where the programmer thought he > was operating on integers. Yea. I'd swear that I've seen an RFE somewhere for this in the GCC BZ, I mean to warn for bool1 * bool2, bool1 / bool2, etc. Though I'm not sure if warning for bool1 | bool2 would be desirable. Thanks, I think I'll commit this later today. Marek
On 09/05/2016 12:52 PM, Marek Polacek wrote: > On Mon, Sep 05, 2016 at 12:35:13PM +0200, Bernd Schmidt wrote: >> On 09/02/2016 05:13 PM, Marek Polacek wrote: >>> diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi >>> index 87da1f1..38d55d4 100644 >>> --- gcc/doc/invoke.texi >>> +++ gcc/doc/invoke.texi >>> @@ -5437,8 +5437,8 @@ if (a < 0 && a < 0) @{ @dots{} @} >>> @opindex Wlogical-not-parentheses >>> @opindex Wno-logical-not-parentheses >>> Warn about logical not used on the left hand side operand of a comparison. >>> -This option does not warn if the RHS operand is of a boolean type. Its >>> -purpose is to detect suspicious code like the following: >>> +This option does not warn if the right operand is considered to be a Boolean >>> +expression. Its purpose is to detect suspicious code like the following: >> >> I think "Boolean" shouldn't be capitalized. The patch looks ok to me >> otherwise. > > No strong opinions, but looking at > https://en.wikipedia.org/wiki/Boolean_expression > I see that it's capitalized there, so I think let's keep "Boolean". I looked at other occurrences in this file, and they are lower-case. Across the other texi files upper-case is also the exception. Let's ask Sandra for a ruling? Bernd
On 09/05/2016 09:55 AM, Bernd Schmidt wrote: > > > On 09/05/2016 12:52 PM, Marek Polacek wrote: >> On Mon, Sep 05, 2016 at 12:35:13PM +0200, Bernd Schmidt wrote: >>> On 09/02/2016 05:13 PM, Marek Polacek wrote: >>>> diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi >>>> index 87da1f1..38d55d4 100644 >>>> --- gcc/doc/invoke.texi >>>> +++ gcc/doc/invoke.texi >>>> @@ -5437,8 +5437,8 @@ if (a < 0 && a < 0) @{ @dots{} @} >>>> @opindex Wlogical-not-parentheses >>>> @opindex Wno-logical-not-parentheses >>>> Warn about logical not used on the left hand side operand of a >>>> comparison. >>>> -This option does not warn if the RHS operand is of a boolean type. >>>> Its >>>> -purpose is to detect suspicious code like the following: >>>> +This option does not warn if the right operand is considered to be >>>> a Boolean >>>> +expression. Its purpose is to detect suspicious code like the >>>> following: >>> >>> I think "Boolean" shouldn't be capitalized. The patch looks ok to me >>> otherwise. >> >> No strong opinions, but looking at >> https://en.wikipedia.org/wiki/Boolean_expression >> I see that it's capitalized there, so I think let's keep "Boolean". > > I looked at other occurrences in this file, and they are lower-case. > Across the other texi files upper-case is also the exception. Let's ask > Sandra for a ruling? Ummmm. There seems to be precedent for both capitalizing it and not. The C standard doesn't capitalize it (but the only place I could find where "boolean" used in a context where it wouldn't be capitalized anyway, such as the first word in a section title, is the index). The C++ standard isn't consistent, using both "Boolean" and "boolean" (and sometimes even on the same page). The documents I have handy are older drafts, though; maybe that has been cleaned up in current/final versions. Looking at some other languages, the Python documentation capitalizes: https://docs.python.org/3/library/stdtypes.html But the Scheme specification editors deliberately chose not to do so: http://www.r6rs.org/r6rs-editors/2007-April/002143.html The Haskell specification also uses lowercase: https://www.haskell.org/onlinereport/haskell2010/haskellch6.html#x13-1170006.1 Mark-Jason Dominus gave the matter some serious thought: http://blog.plover.com/lang/Boolean.html Anyway, I will be happy either way as long as the documentation is consistent. -Sandra
On Mon, Sep 05, 2016 at 10:35:26AM -0600, Sandra Loosemore wrote: > On 09/05/2016 09:55 AM, Bernd Schmidt wrote: > > > > > > On 09/05/2016 12:52 PM, Marek Polacek wrote: > > > On Mon, Sep 05, 2016 at 12:35:13PM +0200, Bernd Schmidt wrote: > > > > On 09/02/2016 05:13 PM, Marek Polacek wrote: > > > > > diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi > > > > > index 87da1f1..38d55d4 100644 > > > > > --- gcc/doc/invoke.texi > > > > > +++ gcc/doc/invoke.texi > > > > > @@ -5437,8 +5437,8 @@ if (a < 0 && a < 0) @{ @dots{} @} > > > > > @opindex Wlogical-not-parentheses > > > > > @opindex Wno-logical-not-parentheses > > > > > Warn about logical not used on the left hand side operand of a > > > > > comparison. > > > > > -This option does not warn if the RHS operand is of a boolean type. > > > > > Its > > > > > -purpose is to detect suspicious code like the following: > > > > > +This option does not warn if the right operand is considered to be > > > > > a Boolean > > > > > +expression. Its purpose is to detect suspicious code like the > > > > > following: > > > > > > > > I think "Boolean" shouldn't be capitalized. The patch looks ok to me > > > > otherwise. > > > > > > No strong opinions, but looking at > > > https://en.wikipedia.org/wiki/Boolean_expression > > > I see that it's capitalized there, so I think let's keep "Boolean". > > > > I looked at other occurrences in this file, and they are lower-case. > > Across the other texi files upper-case is also the exception. Let's ask > > Sandra for a ruling? > > Ummmm. There seems to be precedent for both capitalizing it and not. > > The C standard doesn't capitalize it (but the only place I could find where > "boolean" used in a context where it wouldn't be capitalized anyway, such as > the first word in a section title, is the index). The C++ standard isn't > consistent, using both "Boolean" and "boolean" (and sometimes even on the > same page). The documents I have handy are older drafts, though; maybe that > has been cleaned up in current/final versions. Thanks for the research! > Looking at some other languages, the Python documentation capitalizes: > > https://docs.python.org/3/library/stdtypes.html > > But the Scheme specification editors deliberately chose not to do so: > > http://www.r6rs.org/r6rs-editors/2007-April/002143.html > > The Haskell specification also uses lowercase: > > https://www.haskell.org/onlinereport/haskell2010/haskellch6.html#x13-1170006.1 > > Mark-Jason Dominus gave the matter some serious thought: > > http://blog.plover.com/lang/Boolean.html Ok, I buy that. > Anyway, I will be happy either way as long as the documentation is > consistent. Let's go with lowercase then. I'll post a cleanup patch. Marek
diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c index 399ba97..fbc8fb0 100644 --- gcc/c-family/c-common.c +++ gcc/c-family/c-common.c @@ -1479,6 +1479,36 @@ warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs) } } +/* Return true iff T is a boolean promoted to int. */ + +static bool +bool_promoted_to_int_p (tree t) +{ + return (CONVERT_EXPR_P (t) + && TREE_TYPE (t) == integer_type_node + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == BOOLEAN_TYPE); +} + +/* Return true iff EXPR only contains boolean operands, or comparisons. */ + +static bool +expr_has_boolean_operands_p (tree expr) +{ + STRIP_NOPS (expr); + + if (CONVERT_EXPR_P (expr)) + return bool_promoted_to_int_p (expr); + else if (UNARY_CLASS_P (expr)) + return expr_has_boolean_operands_p (TREE_OPERAND (expr, 0)); + else if (BINARY_CLASS_P (expr)) + return (expr_has_boolean_operands_p (TREE_OPERAND (expr, 0)) + && expr_has_boolean_operands_p (TREE_OPERAND (expr, 1))); + else if (COMPARISON_CLASS_P (expr)) + return true; + else + return false; +} + /* Warn about logical not used on the left hand side operand of a comparison. This function assumes that the LHS is inside of TRUTH_NOT_EXPR. Do not warn if RHS is of a boolean type, a logical operator, or @@ -1494,6 +1524,10 @@ warn_logical_not_parentheses (location_t location, enum tree_code code, || truth_value_p (TREE_CODE (rhs))) return; + /* Don't warn for expression like !x == ~(bool1 | bool2). */ + if (expr_has_boolean_operands_p (rhs)) + return; + /* Don't warn for !x == 0 or !y != 0, those are equivalent to !(x == 0) or !(y != 0). */ if ((code == EQ_EXPR || code == NE_EXPR) @@ -12405,9 +12439,7 @@ maybe_warn_bool_compare (location_t loc, enum tree_code code, tree op0, don't want to warn here. */ tree noncst = TREE_CODE (op0) == INTEGER_CST ? op1 : op0; /* Handle booleans promoted to integers. */ - if (CONVERT_EXPR_P (noncst) - && TREE_TYPE (noncst) == integer_type_node - && TREE_CODE (TREE_TYPE (TREE_OPERAND (noncst, 0))) == BOOLEAN_TYPE) + if (bool_promoted_to_int_p (noncst)) /* Warn. */; else if (TREE_CODE (TREE_TYPE (noncst)) != BOOLEAN_TYPE && !truth_value_p (TREE_CODE (noncst))) diff --git gcc/doc/invoke.texi gcc/doc/invoke.texi index 87da1f1..38d55d4 100644 --- gcc/doc/invoke.texi +++ gcc/doc/invoke.texi @@ -5437,8 +5437,8 @@ if (a < 0 && a < 0) @{ @dots{} @} @opindex Wlogical-not-parentheses @opindex Wno-logical-not-parentheses Warn about logical not used on the left hand side operand of a comparison. -This option does not warn if the RHS operand is of a boolean type. Its -purpose is to detect suspicious code like the following: +This option does not warn if the right operand is considered to be a Boolean +expression. Its purpose is to detect suspicious code like the following: @smallexample int a; @dots{} diff --git gcc/testsuite/c-c++-common/Wlogical-not-parentheses-3.c gcc/testsuite/c-c++-common/Wlogical-not-parentheses-3.c index e69de29..00aa747 100644 --- gcc/testsuite/c-c++-common/Wlogical-not-parentheses-3.c +++ gcc/testsuite/c-c++-common/Wlogical-not-parentheses-3.c @@ -0,0 +1,31 @@ +/* PR c/77423 */ +/* { dg-do compile } */ +/* { dg-options "-Wlogical-not-parentheses" } */ + +#ifndef __cplusplus +# define bool _Bool +#endif + +int +f (int a, bool b, bool c) +{ + int r = 0; + + r += !a == (b | c); + r += !a == (b ^ c); + r += !a == (b & c); + r += !a == ~b; + r += !a == ~(int) b; + r += !a == ((b & c) | c); + r += !a == ((b & c) | (b ^ c)); + r += !a == (int) (b ^ c); + r += !a == (int) ~b; + r += !a == ~~b; + r += !a == ~(b | c); + r += !a == ~(b | (a == 1)); + r += !a == ~(a == 1); + + r += !a == ((b & c) | (b ^ a)); /* { dg-warning "logical not is only applied to the left hand side of comparison" } */ + + return r; +}