Hi! This patch makes -Wint-in-bool-context warn on suspicious integer left shifts, when the integer is signed, which is most likely some kind of programming error, for instance using "<<" instead of "<".
The warning is motivated by the fact, that an overflow on integer shift left is undefined behavior, even if gcc won't optimize the shift based on the undefined behavior. So in absence of undefined behavior the boolean result does not depend on the shift value, thus the whole shifting is pointless. Of course the warning happened to find one bug already. That is in cp/parser.c at cp_parser_condition, where we have this: bool flags = LOOKUP_ONLYCONVERTING; BUT (cp-tree.h): #define LOOKUP_ONLYCONVERTING (1 << 2) So "flags" is actually set to true, which is LOOKUP_PROTECT instead. Although I tried hard to find a test case where this changes something, I was not able to construct one. Bootstrapped and reg-tested on x86_64-pc-linux-gnu. Is it OK for trunk? Thanks Bernd.
gcc: 2016-09-25 Bernd Edlinger <bernd.edlin...@hotmail.de> * doc/invoke.texi: Update -Wint-in-bool-context. c-family: 2016-09-25 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-common.c (c_common_truthvalue_conversion): Warn for suspicious signed integer left shift in boolean context. cp: 2016-09-25 Bernd Edlinger <bernd.edlin...@hotmail.de> * parser.c (cp_parser_condition): Fix a warning. testsuite: 2016-09-25 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-c++-common/Wint-in-bool-context.c: Update test.
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 240437) +++ gcc/c-family/c-common.c (working copy) @@ -4651,6 +4651,19 @@ c_common_truthvalue_conversion (location_t locatio return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0)); + case LSHIFT_EXPR: + /* Warn on signed integer left shift, except 0 << 0, 1 << 0. */ + if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE + && !TYPE_UNSIGNED (TREE_TYPE (expr)) + && !(TREE_CODE (TREE_OPERAND (expr, 0)) == INTEGER_CST + && TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST + && (integer_zerop (TREE_OPERAND (expr, 0)) + || integer_onep (TREE_OPERAND (expr, 0))) + && integer_zerop (TREE_OPERAND (expr, 1)))) + warning_at (EXPR_LOCATION (expr), OPT_Wint_in_bool_context, + "<< on signed integer in boolean context"); + break; + case COND_EXPR: if (warn_int_in_bool_context && !from_macro_definition_at (EXPR_LOCATION (expr))) Index: gcc/cp/parser.c =================================================================== --- gcc/cp/parser.c (revision 240437) +++ gcc/cp/parser.c (working copy) @@ -11172,7 +11172,7 @@ cp_parser_condition (cp_parser* parser) { tree pushed_scope; bool non_constant_p; - bool flags = LOOKUP_ONLYCONVERTING; + int flags = LOOKUP_ONLYCONVERTING; /* Create the declaration. */ decl = start_decl (declarator, &type_specifiers, Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 240437) +++ gcc/doc/invoke.texi (working copy) @@ -5927,7 +5927,8 @@ of the C++ standard. @opindex Wno-int-in-bool-context Warn for suspicious use of integer values where boolean values are expected, such as conditional expressions (?:) using non-boolean integer constants in -boolean context, like @code{if (a <= b ? 2 : 3)}. +boolean context, like @code{if (a <= b ? 2 : 3)}. Or left shifting of a +signed integer in boolean context, like @code{for (a = 0; 1 << a; a++);}. This warning is enabled by @option{-Wall}. @item -Wno-int-to-pointer-cast Index: gcc/testsuite/c-c++-common/Wint-in-bool-context.c =================================================================== --- gcc/testsuite/c-c++-common/Wint-in-bool-context.c (revision 240437) +++ gcc/testsuite/c-c++-common/Wint-in-bool-context.c (working copy) @@ -25,5 +25,7 @@ int foo (int a, int b) if (b ? 1+1 : 1) /* { dg-warning "boolean context" } */ return 7; + for (a = 0; 1 << a; a++); /* { dg-warning "boolean context" } */ + return 0; }