Hi, I've noticed that there is already a -Wparentheses warning for code like
int y = x == 2 ?: 1 => warning: the omitted middle operand in ?: will always be 'true', suggest explicit middle operand [-Wparentheses] But it is not emitted for code that uses bool, like: void foo(bool x) { int y = x ?: 1; and under C it is not emitted for compound expressions that end with a comparison, like: int y = (i++,i==1) ?: 1; C++ is OK, but does only miss to warn on the bool data type. The attached patch should fix these warnings. Bootstrap and reg-testing is still running, Is it OK for trunk after reg-testing? Thanks Bernd.
gcc/c-family: 2016-09-05 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-common.c (warn_for_omitted_condop): Also warn for boolean data. gcc/c: 2016-09-05 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-parser.c (c_parser_conditional_expression): Pass the rightmost COMPOUND_EXPR to warn_for_omitted_condop. testsuite: 2016-09-05 Bernd Edlinger <bernd.edlin...@hotmail.de> * c-c++-common/warn-ommitted-condop.c: Add more test cases. Index: gcc/c/c-parser.c =================================================================== --- gcc/c/c-parser.c (revision 240001) +++ gcc/c/c-parser.c (working copy) @@ -6423,16 +6423,20 @@ c_parser_conditional_expression (c_parser *parser, if (c_parser_next_token_is (parser, CPP_COLON)) { tree eptype = NULL_TREE; + tree e; middle_loc = c_parser_peek_token (parser)->location; pedwarn (middle_loc, OPT_Wpedantic, "ISO C forbids omitting the middle term of a ?: expression"); - warn_for_omitted_condop (middle_loc, cond.value); if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR) { eptype = TREE_TYPE (cond.value); cond.value = TREE_OPERAND (cond.value, 0); } + e = cond.value; + while (TREE_CODE (e) == COMPOUND_EXPR) + e = TREE_OPERAND (e, 1); + warn_for_omitted_condop (middle_loc, e); /* Make sure first operand is calculated only once. */ exp1.value = c_save_expr (default_conversion (cond.value)); if (eptype) Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 240001) +++ gcc/c-family/c-common.c (working copy) @@ -10619,7 +10619,8 @@ fold_offsetof (tree expr) void warn_for_omitted_condop (location_t location, tree cond) { - if (truth_value_p (TREE_CODE (cond))) + if (TREE_CODE (TREE_TYPE (cond)) == BOOLEAN_TYPE + || truth_value_p (TREE_CODE (cond))) warning_at (location, OPT_Wparentheses, "the omitted middle operand in ?: will always be %<true%>, " "suggest explicit middle operand"); Index: gcc/testsuite/c-c++-common/warn-ommitted-condop.c =================================================================== --- gcc/testsuite/c-c++-common/warn-ommitted-condop.c (revision 240001) +++ gcc/testsuite/c-c++-common/warn-ommitted-condop.c (working copy) @@ -1,8 +1,12 @@ /* { dg-options "-Wparentheses -ftrack-macro-expansion=0" } */ +#ifndef __cplusplus +#define bool _Bool +#endif + extern void f2 (int); -void bar (int x, int y, int z) +void bar (int x, int y, int z, bool b) { #define T(op) f2 (x op y ? : 1) #define T2(op) f2 (x op y ? 2 : 1) @@ -16,6 +20,8 @@ extern void f2 (int); T(||); /* { dg-warning "omitted middle operand" } */ T(&&); /* { dg-warning "omitted middle operand" } */ f2 (!x ? : 1); /* { dg-warning "omitted middle operand" } */ + f2 ((x,!x) ? : 1); /* { dg-warning "omitted middle operand" } */ + f2 ((x,y,!x) ? : 1); /* { dg-warning "omitted middle operand" } */ T2(<); /* { dg-bogus "omitted middle operand" } */ T2(>); /* { dg-bogus "omitted middle operand" } */ T2(==); /* { dg-bogus "omitted middle operand" } */ @@ -26,4 +32,5 @@ extern void f2 (int); T(*); /* { dg-bogus "omitted middle operand" } */ T(/); /* { dg-bogus "omitted middle operand" } */ T(^); /* { dg-bogus "omitted middle operand" } */ + f2 (b ? : 1); /* { dg-warning "omitted middle operand" } */ }