diff options
author | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2008-10-24 10:09:06 +0000 |
---|---|---|
committer | Manuel López-Ibáñez <manu@gcc.gnu.org> | 2008-10-24 10:09:06 +0000 |
commit | 100d537d7a7b5c0ef775d568ce3eefffa72f2c41 (patch) | |
tree | 700b750bc17a07e7749365330c49e0f595aaa435 | |
parent | 950d63e12fd0a69731a4c1ae313135f2d47d30a9 (diff) | |
download | gcc-100d537d7a7b5c0ef775d568ce3eefffa72f2c41.zip gcc-100d537d7a7b5c0ef775d568ce3eefffa72f2c41.tar.gz gcc-100d537d7a7b5c0ef775d568ce3eefffa72f2c41.tar.bz2 |
re PR c/7543 (no warning for always-false "if (!a & 0x4)" bitwise and on boolean value)
2008-10-24 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR c/7543
* value-prof.c (gimple_stringop_fixed_value): Use parentheses
around bit operation.
* profile.c (is_edge_inconsistent): Likewise.
* fold-const.c (truth_value_p): Move from here...
* tree.h (truth_value_p): ... to here.
* c-tree.h (c_expr): Update description of original_code.
* c-typeck.c (parser_build_unary_op): Set original_code.
(parser_build_binary_op): Update call to warn_about_parentheses.
* c-common.c (warn_about_parentheses): Take two additional
arguments of the operands. Use a switch. Quote operators
appropriately. Define macro APPEARS_TO_BE_BOOLEAN_EXPR_P.
Add warning about !x | y and !x & y.
* c-common.h (warn_about_parentheses): Update declaration.
cp/
* typeck.c (build_x_binary_op): Update call to
warn_about_parentheses.
* parser.c (cp_parser_binary_expression): Add note about passing
the correct code for unary expressions.
testsuite/
* gcc.dg/Wparentheses-11.c: New.
* g++.dg/warn/Wparentheses-25.C: New. XFAILED.
From-SVN: r141340
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/c-common.c | 142 | ||||
-rw-r--r-- | gcc/c-common.h | 5 | ||||
-rw-r--r-- | gcc/c-tree.h | 2 | ||||
-rw-r--r-- | gcc/c-typeck.c | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/parser.c | 7 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 2 | ||||
-rw-r--r-- | gcc/fold-const.c | 12 | ||||
-rw-r--r-- | gcc/profile.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wparentheses-25.C | 259 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/Wparentheses-11.c | 258 | ||||
-rw-r--r-- | gcc/tree.h | 11 | ||||
-rw-r--r-- | gcc/value-prof.c | 2 |
15 files changed, 666 insertions, 73 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 840e0eb..18b0e80 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2008-10-24 Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR c/7543 + * value-prof.c (gimple_stringop_fixed_value): Use parentheses + around bit operation. + * profile.c (is_edge_inconsistent): Likewise. + * fold-const.c (truth_value_p): Move from here... + * tree.h (truth_value_p): ... to here. + * c-tree.h (c_expr): Update description of original_code. + * c-typeck.c (parser_build_unary_op): Set original_code. + (parser_build_binary_op): Update call to warn_about_parentheses. + * c-common.c (warn_about_parentheses): Take two additional + arguments of the operands. Use a switch. Quote operators + appropriately. Define macro APPEARS_TO_BE_BOOLEAN_EXPR_P. + Add warning about !x | y and !x & y. + * c-common.h (warn_about_parentheses): Update declaration. + 2008-10-24 Jakub Jelinek <jakub@redhat.com> * Makefile.in (lang_checks_parallelized, check_gcc_parallelize, diff --git a/gcc/c-common.c b/gcc/c-common.c index 6b37c34..30acb7d 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -8076,94 +8076,132 @@ warn_array_subscript_with_type_char (tree index) /* Implement -Wparentheses for the unexpected C precedence rules, to cover cases like x + y << z which readers are likely to misinterpret. We have seen an expression in which CODE is a binary - operator used to combine expressions headed by CODE_LEFT and - CODE_RIGHT. CODE_LEFT and CODE_RIGHT may be ERROR_MARK, which - means that that side of the expression was not formed using a - binary operator, or it was enclosed in parentheses. */ + operator used to combine expressions ARG_LEFT and ARG_RIGHT, which + before folding had CODE_LEFT and CODE_RIGHT. CODE_LEFT and + CODE_RIGHT may be ERROR_MARK, which means that that side of the + expression was not formed using a binary or unary operator, or it + was enclosed in parentheses. */ void -warn_about_parentheses (enum tree_code code, enum tree_code code_left, - enum tree_code code_right) +warn_about_parentheses (enum tree_code code, + enum tree_code code_left, tree ARG_UNUSED (arg_left), + enum tree_code code_right, tree arg_right) { if (!warn_parentheses) return; - if (code == LSHIFT_EXPR || code == RSHIFT_EXPR) + /* This macro tests that the expression ARG with original tree code + CODE appears to be a boolean expression. or the result of folding a + boolean expression. */ +#define APPEARS_TO_BE_BOOLEAN_EXPR_P(CODE, ARG) \ + (truth_value_p (TREE_CODE (ARG)) \ + || TREE_CODE (TREE_TYPE (ARG)) == BOOLEAN_TYPE \ + /* Folding may create 0 or 1 integers from other expressions. */ \ + || ((CODE) != INTEGER_CST \ + && (integer_onep (ARG) || integer_zerop (ARG)))) + + switch (code) { - if (code_left == PLUS_EXPR || code_left == MINUS_EXPR - || code_right == PLUS_EXPR || code_right == MINUS_EXPR) + case LSHIFT_EXPR: + if (code_left == PLUS_EXPR || code_right == PLUS_EXPR) warning (OPT_Wparentheses, - "suggest parentheses around + or - inside shift"); - } + "suggest parentheses around %<+%> inside %<<<%>"); + else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around %<-%> inside %<<<%>"); + return; - if (code == TRUTH_ORIF_EXPR) - { - if (code_left == TRUTH_ANDIF_EXPR - || code_right == TRUTH_ANDIF_EXPR) + case RSHIFT_EXPR: + if (code_left == PLUS_EXPR || code_right == PLUS_EXPR) warning (OPT_Wparentheses, - "suggest parentheses around && within ||"); - } + "suggest parentheses around %<+%> inside %<>>%>"); + else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around %<-%> inside %<>>%>"); + return; - if (code == BIT_IOR_EXPR) - { + case TRUTH_ORIF_EXPR: + if (code_left == TRUTH_ANDIF_EXPR || code_right == TRUTH_ANDIF_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around %<&&%> within %<||%>"); + return; + + case BIT_IOR_EXPR: if (code_left == BIT_AND_EXPR || code_left == BIT_XOR_EXPR || code_left == PLUS_EXPR || code_left == MINUS_EXPR || code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR || code_right == PLUS_EXPR || code_right == MINUS_EXPR) warning (OPT_Wparentheses, - "suggest parentheses around arithmetic in operand of |"); + "suggest parentheses around arithmetic in operand of %<|%>"); /* Check cases like x|y==z */ - if (TREE_CODE_CLASS (code_left) == tcc_comparison - || TREE_CODE_CLASS (code_right) == tcc_comparison) + else if (TREE_CODE_CLASS (code_left) == tcc_comparison + || TREE_CODE_CLASS (code_right) == tcc_comparison) warning (OPT_Wparentheses, - "suggest parentheses around comparison in operand of |"); - } + "suggest parentheses around comparison in operand of %<|%>"); + /* Check cases like !x | y */ + else if (code_left == TRUTH_NOT_EXPR + && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right)) + warning (OPT_Wparentheses, "suggest parentheses around operand of" + "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>"); + return; - if (code == BIT_XOR_EXPR) - { + case BIT_XOR_EXPR: if (code_left == BIT_AND_EXPR || code_left == PLUS_EXPR || code_left == MINUS_EXPR || code_right == BIT_AND_EXPR || code_right == PLUS_EXPR || code_right == MINUS_EXPR) warning (OPT_Wparentheses, - "suggest parentheses around arithmetic in operand of ^"); + "suggest parentheses around arithmetic in operand of %<^%>"); /* Check cases like x^y==z */ - if (TREE_CODE_CLASS (code_left) == tcc_comparison - || TREE_CODE_CLASS (code_right) == tcc_comparison) + else if (TREE_CODE_CLASS (code_left) == tcc_comparison + || TREE_CODE_CLASS (code_right) == tcc_comparison) warning (OPT_Wparentheses, - "suggest parentheses around comparison in operand of ^"); - } + "suggest parentheses around comparison in operand of %<^%>"); + return; - if (code == BIT_AND_EXPR) - { - if (code_left == PLUS_EXPR || code_left == MINUS_EXPR - || code_right == PLUS_EXPR || code_right == MINUS_EXPR) + case BIT_AND_EXPR: + if (code_left == PLUS_EXPR || code_right == PLUS_EXPR) + warning (OPT_Wparentheses, + "suggest parentheses around %<+%> in operand of %<&%>"); + else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR) warning (OPT_Wparentheses, - "suggest parentheses around + or - in operand of &"); + "suggest parentheses around %<-%> in operand of %<&%>"); /* Check cases like x&y==z */ - if (TREE_CODE_CLASS (code_left) == tcc_comparison - || TREE_CODE_CLASS (code_right) == tcc_comparison) + else if (TREE_CODE_CLASS (code_left) == tcc_comparison + || TREE_CODE_CLASS (code_right) == tcc_comparison) warning (OPT_Wparentheses, - "suggest parentheses around comparison in operand of &"); - } + "suggest parentheses around comparison in operand of %<&%>"); + /* Check cases like !x & y */ + else if (code_left == TRUTH_NOT_EXPR + && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right)) + warning (OPT_Wparentheses, "suggest parentheses around operand of" + "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>"); + return; - if (code == EQ_EXPR || code == NE_EXPR) - { + case EQ_EXPR: if (TREE_CODE_CLASS (code_left) == tcc_comparison || TREE_CODE_CLASS (code_right) == tcc_comparison) warning (OPT_Wparentheses, - "suggest parentheses around comparison in operand of %s", - code == EQ_EXPR ? "==" : "!="); - } - else if (TREE_CODE_CLASS (code) == tcc_comparison) - { - if ((TREE_CODE_CLASS (code_left) == tcc_comparison - && code_left != NE_EXPR && code_left != EQ_EXPR) - || (TREE_CODE_CLASS (code_right) == tcc_comparison - && code_right != NE_EXPR && code_right != EQ_EXPR)) - warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not " + "suggest parentheses around comparison in operand of %<==%>"); + return; + case NE_EXPR: + if (TREE_CODE_CLASS (code_left) == tcc_comparison + || TREE_CODE_CLASS (code_right) == tcc_comparison) + warning (OPT_Wparentheses, + "suggest parentheses around comparison in operand of %<!=%>"); + return; + + default: + if (TREE_CODE_CLASS (code) == tcc_comparison + && ((TREE_CODE_CLASS (code_left) == tcc_comparison + && code_left != NE_EXPR && code_left != EQ_EXPR) + || (TREE_CODE_CLASS (code_right) == tcc_comparison + && code_right != NE_EXPR && code_right != EQ_EXPR))) + warning (OPT_Wparentheses, "comparisons like %<X<=Y<=Z%> do not " "have their mathematical meaning"); + return; } +#undef NOT_A_BOOLEAN_EXPR_P } /* If LABEL (a LABEL_DECL) has not been used, issue a warning. */ diff --git a/gcc/c-common.h b/gcc/c-common.h index cd4eb31..be38a60 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -912,8 +912,9 @@ extern int complete_array_type (tree *, tree, bool); extern tree builtin_type_for_size (int, bool); extern void warn_array_subscript_with_type_char (tree); -extern void warn_about_parentheses (enum tree_code, enum tree_code, - enum tree_code); +extern void warn_about_parentheses (enum tree_code, + enum tree_code, tree, + enum tree_code, tree); extern void warn_for_unused_label (tree label); extern void warn_for_div_by_zero (location_t, tree divisor); extern void warn_for_sign_compare (location_t, diff --git a/gcc/c-tree.h b/gcc/c-tree.h index 26ef664..b7430af 100644 --- a/gcc/c-tree.h +++ b/gcc/c-tree.h @@ -151,7 +151,7 @@ struct c_expr { /* The value of the expression. */ tree value; - /* Record the original binary operator of an expression, which may + /* Record the original unary/binary operator of an expression, which may have been changed by fold, STRING_CST for unparenthesized string constants, or ERROR_MARK for other expressions (including parenthesized expressions). */ diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 52042fa..27564e6 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2748,9 +2748,9 @@ parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc) { struct c_expr result; - result.original_code = ERROR_MARK; result.value = build_unary_op (loc, code, arg.value, 0); - + result.original_code = code; + if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value)) overflow_warning (result.value); @@ -2787,7 +2787,7 @@ parser_build_binary_op (location_t location, enum tree_code code, /* Check for cases such as x+y<<z which users are likely to misinterpret. */ if (warn_parentheses) - warn_about_parentheses (code, code1, code2); + warn_about_parentheses (code, code1, arg1.value, code2, arg2.value); if (TREE_CODE_CLASS (code1) != tcc_comparison) warn_logical_operator (code, arg1.value, arg2.value); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ee09f15..0293d49 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2008-10-24 Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR c/7543 + * typeck.c (build_x_binary_op): Update call to + warn_about_parentheses. + * parser.c (cp_parser_binary_expression): Add note about passing + the correct code for unary expressions. + 2008-10-24 Jakub Jelinek <jakub@redhat.com> * Make-lang.in (check-c++-subtargets): New alias for diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 519c1d6..7596048 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -6205,6 +6205,13 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, } overloaded_p = false; + /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type == + ERROR_MARK for everything that is not a binary expression. + This makes warn_about_parentheses miss some warnings that + involve unary operators. For unary expressions we should + pass the correct tree_code unless the unary expression was + surrounded by parentheses. + */ lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type, &overloaded_p, tf_warning_or_error); lhs_type = tree_type; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 9e65bdd..84ebc95 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -3158,7 +3158,7 @@ build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code, && !error_operand_p (arg2) && (code != LSHIFT_EXPR || !CLASS_TYPE_P (TREE_TYPE (arg1)))) - warn_about_parentheses (code, arg1_code, arg2_code); + warn_about_parentheses (code, arg1_code, orig_arg1, arg2_code, orig_arg2); if (processing_template_decl && expr != error_mark_node) return build_min_non_dep (code, expr, orig_arg1, orig_arg2); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 88e70d6..1eac946 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -105,7 +105,6 @@ static enum comparison_code comparison_to_compcode (enum tree_code); static enum tree_code compcode_to_comparison (enum comparison_code); static tree combine_comparisons (enum tree_code, enum tree_code, enum tree_code, tree, tree, tree); -static int truth_value_p (enum tree_code); static int operand_equal_for_comparison_p (tree, tree, tree); static int twoval_comparison_p (tree, tree *, tree *, int *); static tree eval_subst (tree, tree, tree, tree, tree); @@ -2981,17 +2980,6 @@ combine_comparisons (enum tree_code code, enum tree_code lcode, return fold_build2 (compcode_to_comparison (compcode), truth_type, ll_arg, lr_arg); } - -/* Return nonzero if CODE is a tree code that represents a truth value. */ - -static int -truth_value_p (enum tree_code code) -{ - return (TREE_CODE_CLASS (code) == tcc_comparison - || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR - || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR - || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR); -} /* Return nonzero if two operands (typically of the same tree node) are necessarily equal. If either argument has side-effects this diff --git a/gcc/profile.c b/gcc/profile.c index 976d91c..c4c7276 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -278,7 +278,7 @@ is_edge_inconsistent (VEC(edge,gc) *edges) if (!EDGE_INFO (e)->ignore) { if (e->count < 0 - && ((!e->flags & EDGE_FAKE) + && (!(e->flags & EDGE_FAKE) || !block_ends_with_call_p (e->src))) { if (dump_file) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 29fe92c..bf56e53 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-10-24 Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR c/7543 + * gcc.dg/Wparentheses-11.c: New. + * g++.dg/warn/Wparentheses-25.C: New. XFAILED. + 2008-10-24 Jakub Jelinek <jakub@redhat.com> PR middle-end/37882 diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-25.C b/gcc/testsuite/g++.dg/warn/Wparentheses-25.C new file mode 100644 index 0000000..ab00c25 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wparentheses-25.C @@ -0,0 +1,259 @@ +/* PR 7543. Test operation of -Wparentheses. Precedence warnings. + !a | b and !a & b. */ +/* { dg-do compile } */ +/* { dg-options "-Wparentheses" } */ +// C++ version of Wparentheses-11.c +int foo (int); + +int +bar (int a, int b, int c) +{ + foo (!a & b); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (b < c)); + foo (!a & (b > c)); + foo (!a & (b == c)); + foo (!a & (b != c)); + foo (!a & (b <= c)); + foo (!a & (b >= c)); + foo (!a & (b && c)); + foo (!a & (b || c)); + foo (!a & !b); + foo (!(a & b)); + foo ((!a) & b); + foo (!a & 2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (2 < c)); + foo (!a & (2 > c)); + foo (!a & (2 == c)); + foo (!a & (2 != c)); + foo (!a & (2 <= c)); + foo (!a & (2 >= c)); + foo (!a & (2 && c)); + foo (!a & (2 || c)); + foo (!a & !2); + foo (!(a & 2)); + foo ((!a) & 2); + foo (!1 & 2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & (2 < c)); + foo (!1 & (2 > c)); + foo (!1 & (2 == c)); + foo (!1 & (2 != c)); + foo (!1 & (2 <= c)); + foo (!1 & (2 >= c)); + foo (!1 & (2 && c)); + foo (!1 & (2 || c)); + foo (!1 & !2); + foo (!(1 & 2)); + + foo (!a | b); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (b < c)); + foo (!a | (b > c)); + foo (!a | (b == c)); + foo (!a | (b != c)); + foo (!a | (b <= c)); + foo (!a | (b >= c)); + foo (!a | (b && c)); + foo (!a | (b || c)); + foo (!a | !b); + foo (!(a | b)); + foo ((!a) | b); + foo (!a | 2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (2 < c)); + foo (!a | (2 > c)); + foo (!a | (2 == c)); + foo (!a | (2 != c)); + foo (!a | (2 <= c)); + foo (!a | (2 >= c)); + foo (!a | (2 && c)); + foo (!a | (2 || c)); + foo (!a | !2); + foo (!(a | 2)); + foo ((!a) | 2); + foo (!1 | 2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | (2 < c)); + foo (!1 | (2 > c)); + foo (!1 | (2 == c)); + foo (!1 | (2 != c)); + foo (!1 | (2 <= c)); + foo (!1 | (2 >= c)); + foo (!1 | (2 && c)); + foo (!1 | (2 || c)); + foo (!1 | !2); + foo (!(1 | 2)); + foo ((!1) | 2); + + foo (b & !a); /* { dg-bogus "parentheses" "bogus warning" } */ + foo ((b < c) & !a); + foo ((b > c) & !a); + foo ((b == c) & !a); + foo ((b != c) & !a); + foo ((b <= c) & !a); + foo ((b >= c) & !a); + foo ((b && c) & !a); + foo ((b || c) & !a); + foo (!b & !a); + foo (!(b & a)); + foo (b & (!a)); + foo (2 & !a); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((2 < c) & !a); + foo ((2 > c) & !a); + foo ((2 == c) & !a); + foo ((2 != c) & !a); + foo ((2 <= c) & !a); + foo ((2 >= c) & !a); + foo ((2 && c) & !a); + foo ((2 || c) & !a); + foo (!2 & !a); + foo (!(2 & a)); + foo (2 & (!a)); + foo (2 & !1); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((2 < c) & !1); + foo ((2 > c) & !1); + foo ((2 == c) & !1); + foo ((2 != c) & !1); + foo ((2 <= c) & !1); + foo ((2 >= c) & !1); + foo ((2 && c) & !1); + foo ((2 || c) & !1); + foo (!2 & !1); + foo (!(2 & 1)); + + foo (b | !a); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((b < c) | !a); + foo ((b > c) | !a); + foo ((b == c) | !a); + foo ((b != c) | !a); + foo ((b <= c) | !a); + foo ((b >= c) | !a); + foo ((b && c) | !a); + foo ((b || c) | !a); + foo (!b | !a); + foo (!(b | a)); + foo (b | (!a)); + foo (2 | !a); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((2 < c) | !a); + foo ((2 > c) | !a); + foo ((2 == c) | !a); + foo ((2 != c) | !a); + foo ((2 <= c) | !a); + foo ((2 >= c) | !a); + foo ((2 && c) | !a); + foo ((2 || c) | !a); + foo (!2 | !a); + foo (!(2 | a)); + foo (2 | (!a)); + foo (2 | !1); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((2 < c) | !1); + foo ((2 > c) | !1); + foo ((2 == c) | !1); + foo ((2 != c) | !1); + foo ((2 <= c) | !1); + foo ((2 >= c) | !1); + foo ((2 && c) | !1); + foo ((2 || c) | !1); + foo (!2 | !1); + foo (!(2 | 1)); + foo (2 | (!1)); +} + + +int +baz (int a, int b, int c) +{ + foo (!a & (b << c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (b >> c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (b + c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (b - c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (b = c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & ~b); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (b & c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (b | c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & 2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (2 << c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (2 >> c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (2 + c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (2 - c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (c = 2)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & ~2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (2 & c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a & (2 | c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & (2 << c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & (2 >> c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & (2 + c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & (2 - c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & (c = 2)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & ~2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & (2 & c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 & (2 | c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (b << c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (b >> c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (b + c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (b - c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (b = c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | ~b); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (b & c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (b | c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (2 << c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (2 >> c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (2 + c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (2 - c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (c = 2)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | ~2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (2 & c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!a | (2 | c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | (2 << c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | (2 >> c));/* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | (2 + c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | (2 - c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | (c = 2)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | ~2); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | (2 & c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo (!1 | (2 | c)); /* { dg-warning "parentheses" "correct warning" { xfail *-*-* } } */ + foo ((b << c) & !a); + foo ((b >> c) & !a); + foo ((b + c) & !a); + foo ((b - c) & !a); + foo ((b = c) & !a); + foo (~b & !a); + foo ((b & c) & !a); + foo ((b | c) & !a); + foo ((2 << c) & !a); + foo ((2 >> c) & !a); + foo ((2 + c) & !a); + foo ((2 - c) & !a); + foo ((c = 2) & !a); + foo (~2 & !a); + foo ((2 & c) & !a); + foo ((2 | c) & !a); + foo ((2 << c) & !1); + foo ((2 >> c) & !1); + foo ((2 + c) & !1); + foo ((2 - c) & !1); + foo ((c = 2) & !1); + foo (~2 & !1); + foo ((2 & c) & !1); + foo ((2 | c) & !1); + foo ((b << c) | !a); + foo ((b >> c) | !a); + foo ((b + c) | !a); + foo ((b - c) | !a); + foo ((b = c) | !a); + foo (~b | !a); + foo ((b & c) | !a); + foo ((b | c) | !a); + foo ((2 << c) | !a); + foo ((2 >> c) | !a); + foo ((2 + c) | !a); + foo ((2 - c) | !a); + foo ((c = 2) | !a); + foo (~2 | !a); + foo ((2 & c) | !a); + foo ((2 | c) | !a); + foo ((2 << c) | !1); + foo ((2 >> c) | !1); + foo ((2 + c) | !1); + foo ((2 - c) | !1); + foo ((c = 2) | !1); + foo (~2 | !1); + foo ((2 & c) | !1); + foo ((2 | c) | !1); +} diff --git a/gcc/testsuite/gcc.dg/Wparentheses-11.c b/gcc/testsuite/gcc.dg/Wparentheses-11.c new file mode 100644 index 0000000..8858a7f --- /dev/null +++ b/gcc/testsuite/gcc.dg/Wparentheses-11.c @@ -0,0 +1,258 @@ +/* PR 7543. Test operation of -Wparentheses. Precedence warnings. + !a | b and !a & b. */ +/* { dg-do compile } */ +/* { dg-options "-Wparentheses" } */ + +int foo (int); + +int +bar (int a, int b, int c) +{ + foo (!a & b); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (b < c)); + foo (!a & (b > c)); + foo (!a & (b == c)); + foo (!a & (b != c)); + foo (!a & (b <= c)); + foo (!a & (b >= c)); + foo (!a & (b && c)); + foo (!a & (b || c)); + foo (!a & !b); + foo (!(a & b)); + foo ((!a) & b); + foo (!a & 2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (2 < c)); + foo (!a & (2 > c)); + foo (!a & (2 == c)); + foo (!a & (2 != c)); + foo (!a & (2 <= c)); + foo (!a & (2 >= c)); + foo (!a & (2 && c)); + foo (!a & (2 || c)); + foo (!a & !2); + foo (!(a & 2)); + foo ((!a) & 2); + foo (!1 & 2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & (2 < c)); + foo (!1 & (2 > c)); + foo (!1 & (2 == c)); + foo (!1 & (2 != c)); + foo (!1 & (2 <= c)); + foo (!1 & (2 >= c)); + foo (!1 & (2 && c)); + foo (!1 & (2 || c)); + foo (!1 & !2); + foo (!(1 & 2)); + + foo (!a | b); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (b < c)); + foo (!a | (b > c)); + foo (!a | (b == c)); + foo (!a | (b != c)); + foo (!a | (b <= c)); + foo (!a | (b >= c)); + foo (!a | (b && c)); + foo (!a | (b || c)); + foo (!a | !b); + foo (!(a | b)); + foo ((!a) | b); + foo (!a | 2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (2 < c)); + foo (!a | (2 > c)); + foo (!a | (2 == c)); + foo (!a | (2 != c)); + foo (!a | (2 <= c)); + foo (!a | (2 >= c)); + foo (!a | (2 && c)); + foo (!a | (2 || c)); + foo (!a | !2); + foo (!(a | 2)); + foo ((!a) | 2); + foo (!1 | 2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | (2 < c)); + foo (!1 | (2 > c)); + foo (!1 | (2 == c)); + foo (!1 | (2 != c)); + foo (!1 | (2 <= c)); + foo (!1 | (2 >= c)); + foo (!1 | (2 && c)); + foo (!1 | (2 || c)); + foo (!1 | !2); + foo (!(1 | 2)); + foo ((!1) | 2); + + foo (b & !a); /* { dg-bogus "parentheses" "bogus warning" } */ + foo ((b < c) & !a); + foo ((b > c) & !a); + foo ((b == c) & !a); + foo ((b != c) & !a); + foo ((b <= c) & !a); + foo ((b >= c) & !a); + foo ((b && c) & !a); + foo ((b || c) & !a); + foo (!b & !a); + foo (!(b & a)); + foo (b & (!a)); + foo (2 & !a); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((2 < c) & !a); + foo ((2 > c) & !a); + foo ((2 == c) & !a); + foo ((2 != c) & !a); + foo ((2 <= c) & !a); + foo ((2 >= c) & !a); + foo ((2 && c) & !a); + foo ((2 || c) & !a); + foo (!2 & !a); + foo (!(2 & a)); + foo (2 & (!a)); + foo (2 & !1); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((2 < c) & !1); + foo ((2 > c) & !1); + foo ((2 == c) & !1); + foo ((2 != c) & !1); + foo ((2 <= c) & !1); + foo ((2 >= c) & !1); + foo ((2 && c) & !1); + foo ((2 || c) & !1); + foo (!2 & !1); + foo (!(2 & 1)); + + foo (b | !a); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((b < c) | !a); + foo ((b > c) | !a); + foo ((b == c) | !a); + foo ((b != c) | !a); + foo ((b <= c) | !a); + foo ((b >= c) | !a); + foo ((b && c) | !a); + foo ((b || c) | !a); + foo (!b | !a); + foo (!(b | a)); + foo (b | (!a)); + foo (2 | !a); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((2 < c) | !a); + foo ((2 > c) | !a); + foo ((2 == c) | !a); + foo ((2 != c) | !a); + foo ((2 <= c) | !a); + foo ((2 >= c) | !a); + foo ((2 && c) | !a); + foo ((2 || c) | !a); + foo (!2 | !a); + foo (!(2 | a)); + foo (2 | (!a)); + foo (2 | !1); /* { dg-bogus "parentheses" "correct warning" } */ + foo ((2 < c) | !1); + foo ((2 > c) | !1); + foo ((2 == c) | !1); + foo ((2 != c) | !1); + foo ((2 <= c) | !1); + foo ((2 >= c) | !1); + foo ((2 && c) | !1); + foo ((2 || c) | !1); + foo (!2 | !1); + foo (!(2 | 1)); + foo (2 | (!1)); +} + +int +baz (int a, int b, int c) +{ + foo (!a & (b << c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (b >> c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (b + c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (b - c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (b = c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & ~b); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (b & c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (b | c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & 2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (2 << c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (2 >> c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (2 + c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (2 - c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (c = 2)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & ~2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (2 & c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a & (2 | c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & (2 << c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & (2 >> c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & (2 + c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & (2 - c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & (c = 2)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & ~2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & (2 & c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 & (2 | c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (b << c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (b >> c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (b + c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (b - c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (b = c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | ~b); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (b & c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (b | c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (2 << c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (2 >> c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (2 + c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (2 - c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (c = 2)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | ~2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (2 & c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!a | (2 | c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | (2 << c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | (2 >> c));/* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | (2 + c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | (2 - c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | (c = 2)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | ~2); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | (2 & c)); /* { dg-warning "parentheses" "correct warning" } */ + foo (!1 | (2 | c)); /* { dg-warning "parentheses" "correct warning" } */ + foo ((b << c) & !a); + foo ((b >> c) & !a); + foo ((b + c) & !a); + foo ((b - c) & !a); + foo ((b = c) & !a); + foo (~b & !a); + foo ((b & c) & !a); + foo ((b | c) & !a); + foo ((2 << c) & !a); + foo ((2 >> c) & !a); + foo ((2 + c) & !a); + foo ((2 - c) & !a); + foo ((c = 2) & !a); + foo (~2 & !a); + foo ((2 & c) & !a); + foo ((2 | c) & !a); + foo ((2 << c) & !1); + foo ((2 >> c) & !1); + foo ((2 + c) & !1); + foo ((2 - c) & !1); + foo ((c = 2) & !1); + foo (~2 & !1); + foo ((2 & c) & !1); + foo ((2 | c) & !1); + foo ((b << c) | !a); + foo ((b >> c) | !a); + foo ((b + c) | !a); + foo ((b - c) | !a); + foo ((b = c) | !a); + foo (~b | !a); + foo ((b & c) | !a); + foo ((b | c) | !a); + foo ((2 << c) | !a); + foo ((2 >> c) | !a); + foo ((2 + c) | !a); + foo ((2 - c) | !a); + foo ((c = 2) | !a); + foo (~2 | !a); + foo ((2 & c) | !a); + foo ((2 | c) | !a); + foo ((2 << c) | !1); + foo ((2 >> c) | !1); + foo ((2 + c) | !1); + foo ((2 - c) | !1); + foo ((c = 2) | !1); + foo (~2 | !1); + foo ((2 & c) | !1); + foo ((2 | c) | !1); +} @@ -4838,6 +4838,17 @@ extern bool tree_expr_nonzero_warnv_p (tree, bool *); extern bool fold_real_zero_addition_p (const_tree, const_tree, int); +/* Return nonzero if CODE is a tree code that represents a truth value. */ +static inline bool +truth_value_p (enum tree_code code) +{ + return (TREE_CODE_CLASS (code) == tcc_comparison + || code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR + || code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR + || code == TRUTH_XOR_EXPR || code == TRUTH_NOT_EXPR); +} + + /* In builtins.c */ extern tree fold_call_expr (tree, bool); extern tree fold_builtin_fputs (tree, tree, bool, bool, tree); diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 1900faa..120a68d 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -1296,7 +1296,7 @@ gimple_stringop_fixed_value (gimple stmt, tree value, int prob, gcov_type count, { edge_iterator ei; for (ei = ei_start (bb->succs); (e34 = ei_safe_edge (ei)); ) - if (!e34->flags & EDGE_ABNORMAL) + if (!(e34->flags & EDGE_ABNORMAL)) break; } else |