Hi,

in this PR submitter points out that in the -Wparentheses warning, for, eg,

char in[4]={0}, out[6];
out[1] = in[1] & 0x0F | ((in[3] & 0x3C) << 2);

warning: suggest parentheses around arithmetic in operand of ‘|’ [-Wparentheses]

the caret points to end of the expression, ie the final closing parenthesis, which is rather misleading, because the problem is actually in the first operand of '|'. Ideally I guess one would like to somehow point to that first operand, but our infrastructure (shared with the C front-end, at the moment) isn't really ready to do that, and probably we would like to use a range (more than a caret) below the whole first operand (the problem isn't really with & per se). Considering also what we are already doing elsewhere, it seems to me that a straightforward and good improvement is obtained by passing to warn_about_parentheses the location of the outer operand (together with its code), as per the attached patchlet: then in the example the caret points to the actual '|' operator mentioned in the error message. Post 4.8.0 we can imagine further improvements...

What do you think?

Thanks,
Paolo.

///////////////////////////

Index: cp/typeck.c
===================================================================
--- cp/typeck.c (revision 192130)
+++ cp/typeck.c (working copy)
@@ -3630,7 +3630,8 @@ build_x_binary_op (location_t loc, enum tree_code
       && !error_operand_p (arg2)
       && (code != LSHIFT_EXPR
          || !CLASS_TYPE_P (TREE_TYPE (arg1))))
-    warn_about_parentheses (code, arg1_code, orig_arg1, arg2_code, orig_arg2);
+    warn_about_parentheses (loc, 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);
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c (revision 192130)
+++ c-family/c-common.c (working copy)
@@ -10428,7 +10428,7 @@ warn_array_subscript_with_type_char (tree index)
    was enclosed in parentheses.  */
 
 void
-warn_about_parentheses (enum tree_code code,
+warn_about_parentheses (location_t loc, enum tree_code code,
                        enum tree_code code_left, tree arg_left,
                        enum tree_code code_right, tree arg_right)
 {
@@ -10449,26 +10449,26 @@ void
     {
     case LSHIFT_EXPR:
       if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<+%> inside %<<<%>");
+       warning_at (loc, OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<<<%>");
       else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<-%> inside %<<<%>");
+       warning_at (loc, OPT_Wparentheses,
+                   "suggest parentheses around %<-%> inside %<<<%>");
       return;
 
     case RSHIFT_EXPR:
       if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<+%> inside %<>>%>");
+       warning_at (loc, OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<>>%>");
       else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<-%> inside %<>>%>");
+       warning_at (loc, OPT_Wparentheses,
+                   "suggest parentheses around %<-%> inside %<>>%>");
       return;
 
     case TRUTH_ORIF_EXPR:
       if (code_left == TRUTH_ANDIF_EXPR || code_right == TRUTH_ANDIF_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<&&%> within %<||%>");
+       warning_at (loc, OPT_Wparentheses,
+                   "suggest parentheses around %<&&%> within %<||%>");
       return;
 
     case BIT_IOR_EXPR:
@@ -10476,18 +10476,19 @@ void
          || 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,
+       warning_at (loc, OPT_Wparentheses,
                 "suggest parentheses around arithmetic in operand of %<|%>");
       /* Check cases like x|y==z */
       else if (TREE_CODE_CLASS (code_left) == tcc_comparison
               || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+       warning_at (loc, OPT_Wparentheses,
                 "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 %<~%>");
+       warning_at (loc, OPT_Wparentheses,
+                   "suggest parentheses around operand of "
+                   "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
       return;
 
     case BIT_XOR_EXPR:
@@ -10495,44 +10496,45 @@ void
          || code_left == PLUS_EXPR || code_left == MINUS_EXPR
          || code_right == BIT_AND_EXPR
          || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
+       warning_at (loc, OPT_Wparentheses,
                 "suggest parentheses around arithmetic in operand of %<^%>");
       /* Check cases like x^y==z */
       else if (TREE_CODE_CLASS (code_left) == tcc_comparison
               || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+       warning_at (loc, OPT_Wparentheses,
                 "suggest parentheses around comparison in operand of %<^%>");
       return;
 
     case BIT_AND_EXPR:
       if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
-       warning (OPT_Wparentheses,
+       warning_at (loc, OPT_Wparentheses,
                 "suggest parentheses around %<+%> in operand of %<&%>");
       else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
+       warning_at (loc, OPT_Wparentheses,
                 "suggest parentheses around %<-%> in operand of %<&%>");
       /* Check cases like x&y==z */
       else if (TREE_CODE_CLASS (code_left) == tcc_comparison
               || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+       warning_at (loc, OPT_Wparentheses,
                 "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 %<~%>");
+       warning_at (loc, OPT_Wparentheses,
+                   "suggest parentheses around operand of "
+                   "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
       return;
 
     case EQ_EXPR:
       if (TREE_CODE_CLASS (code_left) == tcc_comparison
           || TREE_CODE_CLASS (code_right) == tcc_comparison)
-       warning (OPT_Wparentheses,
+       warning_at (loc, OPT_Wparentheses,
                 "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,
+       warning_at (loc, OPT_Wparentheses,
                 "suggest parentheses around comparison in operand of %<!=%>");
       return;
 
@@ -10544,8 +10546,9 @@ void
               || (TREE_CODE_CLASS (code_right) == tcc_comparison
                   && code_right != NE_EXPR && code_right != EQ_EXPR
                   && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))))
-       warning (OPT_Wparentheses, "comparisons like %<X<=Y<=Z%> do not "
-                "have their mathematical meaning");
+       warning_at (loc, OPT_Wparentheses,
+                   "comparisons like %<X<=Y<=Z%> do not "
+                   "have their mathematical meaning");
       return;
     }
 #undef NOT_A_BOOLEAN_EXPR_P
Index: c-family/c-common.h
===================================================================
--- c-family/c-common.h (revision 192130)
+++ c-family/c-common.h (working copy)
@@ -988,7 +988,8 @@ extern tree builtin_type_for_size (int, bool);
 extern void c_common_mark_addressable_vec (tree);
 
 extern void warn_array_subscript_with_type_char (tree);
-extern void warn_about_parentheses (enum tree_code,
+extern void warn_about_parentheses (location_t,
+                                   enum tree_code,
                                    enum tree_code, tree,
                                    enum tree_code, tree);
 extern void warn_for_unused_label (tree label);
Index: c/c-typeck.c
===================================================================
--- c/c-typeck.c        (revision 192130)
+++ c/c-typeck.c        (working copy)
@@ -3261,7 +3261,8 @@ parser_build_binary_op (location_t location, enum
   /* Check for cases such as x+y<<z which users are likely
      to misinterpret.  */
   if (warn_parentheses)
-    warn_about_parentheses (code, code1, arg1.value, code2, arg2.value);
+    warn_about_parentheses (input_location, code,
+                           code1, arg1.value, code2, arg2.value);
 
   if (warn_logical_op)
     warn_logical_operator (input_location, code, TREE_TYPE (result.value),

Reply via email to