diff options
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r-- | gcc/c-common.c | 142 |
1 files changed, 90 insertions, 52 deletions
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. */ |