re PR c++/54194 (misleading suggestion about arithmetic in operand of '|')
authorPaolo Carlini <paolo.carlini@oracle.com>
Tue, 9 Oct 2012 10:01:31 +0000 (10:01 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 9 Oct 2012 10:01:31 +0000 (10:01 +0000)
2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/54194
* tree.h: Add EXPR_LOC_OR_LOC.

c-family/
2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/54194
* c-common.c (warn_about_parentheses): Add location_t parameter;
use EXPR_LOC_OR_LOC.
* c-common.h: Update declaration.

c/
2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/54194
* c-typeck.c (parser_build_binary_op): Update warn_about_parentheses
call.

/cp
2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/54194
* typeck.c (build_x_binary_op): Update warn_about_parentheses call.
* parser.c (cp_parser_binary_expression): Use SET_EXPR_LOCATION
on current.lhs.

/testsuite
2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/54194
* g++.dg/warn/Wparentheses-26.C: Adjust.
* g++.dg/warn/Wparentheses-27.C: New.

From-SVN: r192246

13 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wparentheses-26.C
gcc/testsuite/g++.dg/warn/Wparentheses-27.C [new file with mode: 0644]
gcc/tree.h

index 9e78f04..9967ecf 100644 (file)
@@ -1,3 +1,8 @@
+2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/54194
+       * tree.h: Add EXPR_LOC_OR_LOC.
+
 2012-10-09  Nick Clifton  <nickc@redhat.com>
 
        PR rtl-optimization/54739
index c86eb69..470d1b6 100644 (file)
@@ -1,3 +1,10 @@
+2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/54194
+       * c-common.c (warn_about_parentheses): Add location_t parameter;
+       use EXPR_LOC_OR_LOC.
+       * c-common.h: Update declaration.
+
 2012-10-09  Marc Glisse  <marc.glisse@inria.fr>
 
        PR c++/54427
index edd25aa..b918648 100644 (file)
@@ -10527,7 +10527,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)
 {
@@ -10547,104 +10547,147 @@ warn_about_parentheses (enum tree_code code,
   switch (code)
     {
     case LSHIFT_EXPR:
-      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<+%> inside %<<<%>");
-      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<-%> inside %<<<%>");
+      if (code_left == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<<<%>");
+      else if (code_right == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<<<%>");
+      else if (code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<-%> inside %<<<%>");
+      else if (code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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 %<>>%>");
-      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
-                "suggest parentheses around %<-%> inside %<>>%>");
+      if (code_left == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<>>%>");
+      else if (code_right == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<+%> inside %<>>%>");
+      else if (code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<-%> inside %<>>%>");
+      else if (code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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 %<||%>");
+      if (code_left == TRUTH_ANDIF_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around %<&&%> within %<||%>");
+      else if (code_right == TRUTH_ANDIF_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), 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,
+         || code_left == PLUS_EXPR || code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around arithmetic in operand of %<|%>");
+      else if (code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR
+              || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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,
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<|%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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 (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                   "suggest parentheses around operand of "
+                   "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
       return;
 
     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,
+         || code_left == PLUS_EXPR || code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around arithmetic in operand of %<^%>");
+      else if (code_right == BIT_AND_EXPR
+              || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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,
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<^%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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,
+      if (code_left == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around %<+%> in operand of %<&%>");
+      else if (code_right == PLUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
                 "suggest parentheses around %<+%> in operand of %<&%>");
-      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
-       warning (OPT_Wparentheses,
+      else if (code_left == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around %<-%> in operand of %<&%>");
+      else if (code_right == MINUS_EXPR)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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,
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<&%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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 (EXPR_LOC_OR_LOC (arg_left, 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,
+      if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<==%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, 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,
+      if (TREE_CODE_CLASS (code_left) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<!=%>");
+      else if (TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning_at (EXPR_LOC_OR_LOC (arg_right, loc), 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
+      if (TREE_CODE_CLASS (code) == tcc_comparison)
+       {
+         if (TREE_CODE_CLASS (code_left) == tcc_comparison
                && code_left != NE_EXPR && code_left != EQ_EXPR
                && INTEGRAL_TYPE_P (TREE_TYPE (arg_left)))
-              || (TREE_CODE_CLASS (code_right) == tcc_comparison
+           warning_at (EXPR_LOC_OR_LOC (arg_left, loc), OPT_Wparentheses,
+                       "comparisons like %<X<=Y<=Z%> do not "
+                       "have their mathematical meaning");
+         else if (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");
+                  && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))
+           warning_at (EXPR_LOC_OR_LOC (arg_right, loc), OPT_Wparentheses,
+                       "comparisons like %<X<=Y<=Z%> do not "
+                       "have their mathematical meaning");
+       }
       return;
     }
 #undef NOT_A_BOOLEAN_EXPR_P
index 481c3ed..cb18b4e 100644 (file)
@@ -989,7 +989,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 93c72f0..2a3f9a0 100644 (file)
@@ -1,3 +1,9 @@
+2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/54194
+       * c-typeck.c (parser_build_binary_op): Update warn_about_parentheses
+       call.
+
 2012-10-09  Marc Glisse  <marc.glisse@inria.fr>
 
        PR c++/54427
index ae6b348..4855933 100644 (file)
@@ -3254,7 +3254,8 @@ 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, 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),
index 4c1d01a..ab91500 100644 (file)
@@ -1,3 +1,10 @@
+2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/54194
+       * typeck.c (build_x_binary_op): Update warn_about_parentheses call.
+       * parser.c (cp_parser_binary_expression): Use SET_EXPR_LOCATION
+       on current.lhs.
+
 2012-10-09  Marc Glisse  <marc.glisse@inria.fr>
 
        PR c++/54427
index 52a152d..e2b355a 100644 (file)
@@ -7472,6 +7472,8 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
                                         rhs, rhs_type, &overload,
                                         tf_warning_or_error);
       current.lhs_type = current.tree_type;
+      if (EXPR_P (current.lhs))
+       SET_EXPR_LOCATION (current.lhs, current.loc);
 
       /* If the binary operator required the use of an overloaded operator,
         then this expression cannot be an integral constant-expression.
index 94e17c5..13e75ab 100644 (file)
@@ -3680,7 +3680,8 @@ build_x_binary_op (location_t loc, enum tree_code code, tree arg1,
       && !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 5ef31cc..eb34647 100644 (file)
@@ -1,3 +1,9 @@
+2012-10-09  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/54194
+       * g++.dg/warn/Wparentheses-26.C: Adjust.
+       * g++.dg/warn/Wparentheses-27.C: New.
+
 2012-10-09  Marc Glisse  <marc.glisse@inria.fr>
 
        PR c++/54427
index 6fd4417..4525bfd 100644 (file)
@@ -4,23 +4,23 @@
 template<int i, int j = ((i + 7) >> 3)> class foo1 { };
 typedef foo1<10> bar1;
 
-template<int i, int j = (i + 7 >> 3)> class foo2 { };
-typedef foo2<10> bar2;  // { dg-warning "suggest parentheses around '\\+'" }
+template<int i, int j = (i + 7 >> 3)> class foo2 { };  // { dg-warning "suggest parentheses around '\\+'" }
+typedef foo2<10> bar2;
 
 template<int i, int j = (100 >> (i + 2))> class foo3 { };
 typedef foo3<3> bar3;
 
-template<int i, int j = (100 >> i + 2)> class foo4 { }; 
-typedef foo4<3> bar4;   // { dg-warning "suggest parentheses around '\\+'" }
+template<int i, int j = (100 >> i + 2)> class foo4 { }; // { dg-warning "suggest parentheses around '\\+'" }
+typedef foo4<3> bar4;
 
 template<int i, int j = (i + 7) | 3> class foo5 { };
 typedef foo5<10> bar5;
 
-template<int i, int j = i + 7 | 3> class foo6 { };
-typedef foo6<10> bar6;  // { dg-warning "suggest parentheses around arithmetic" }
+template<int i, int j = i + 7 | 3> class foo6 { }; // { dg-warning "suggest parentheses around arithmetic" }
+typedef foo6<10> bar6;
 
 template<int i, int j = 3 | (i + 7)> class foo7 { };
 typedef foo7<10> bar7;
 
-template<int i, int j = 3 | i + 7> class foo8 { };
-typedef foo8<10> bar8;  // { dg-warning "suggest parentheses around arithmetic" }
+template<int i, int j = 3 | i + 7> class foo8 { }; // { dg-warning "suggest parentheses around arithmetic" } 
+typedef foo8<10> bar8;
diff --git a/gcc/testsuite/g++.dg/warn/Wparentheses-27.C b/gcc/testsuite/g++.dg/warn/Wparentheses-27.C
new file mode 100644 (file)
index 0000000..7c05f7e
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/54194
+// { dg-options "-Wparentheses" }
+
+int main()
+{
+  char in[4] = { 0 };
+  in[1] = in[1] & 0x0F | ((in[3] & 0x3C) << 2); // { dg-warning "17:suggest parentheses" }
+}
index e7cef18..12e7948 100644 (file)
@@ -1619,7 +1619,10 @@ struct GTY(()) tree_constructor {
   != UNKNOWN_LOCATION)
 /* The location to be used in a diagnostic about this expression.  Do not
    use this macro if the location will be assigned to other expressions.  */
-#define EXPR_LOC_OR_HERE(NODE) (EXPR_HAS_LOCATION (NODE) ? (NODE)->exp.locus : input_location)
+#define EXPR_LOC_OR_HERE(NODE) (EXPR_HAS_LOCATION (NODE) \
+                               ? (NODE)->exp.locus : input_location)
+#define EXPR_LOC_OR_LOC(NODE, LOCUS) (EXPR_HAS_LOCATION (NODE) \
+                                     ? (NODE)->exp.locus : (LOCUS))
 #define EXPR_FILENAME(NODE) LOCATION_FILE (EXPR_CHECK ((NODE))->exp.locus)
 #define EXPR_LINENO(NODE) LOCATION_LINE (EXPR_CHECK (NODE)->exp.locus)