re PR c/43772 (Errant -Wlogical-op warning when testing limits)
authorManuel López-Ibáñez <manu@gcc.gnu.org>
Sat, 5 May 2012 11:30:57 +0000 (11:30 +0000)
committerManuel López-Ibáñez <manu@gcc.gnu.org>
Sat, 5 May 2012 11:30:57 +0000 (11:30 +0000)
2012-05-05  Manuel López-Ibáñez  <manu@gcc.gnu.org>

PR c/43772
c-family/
* c-common.c (warn_logical_operator): Do not warn if either side
is already true or false.
testsuite/
* c-c++-common/pr43772.c: New.

From-SVN: r187194

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/testsuite/ChangeLog

index 1c805e8694ba0458fa413c485aff71c7bad39695..accb9850074cebf3d427fa85409227585d18399e 100644 (file)
@@ -1,3 +1,9 @@
+2012-05-05  Manuel López-Ibáñez  <manu@gcc.gnu.org>
+
+       PR c/43772
+       * c-common.c (warn_logical_operator): Do not warn if either side
+       is already true or false.
+
 2012-05-04  Manuel López-Ibáñez  <manu@gcc.gnu.org>
 
        PR c/51712
index f3a6746d7c9f8502c50527c9ea84bcad58f8ca09..04a265f97db00aa901cdf04a62a95ef618926130 100644 (file)
@@ -1612,31 +1612,50 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
           || INTEGRAL_TYPE_P (TREE_TYPE (op_right))))
     return;
 
-  lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p);
-  rhs = make_range (op_right, &in1_p, &low1, &high1, &strict_overflow_p);
 
-  if (lhs && TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
+  /* We first test whether either side separately is trivially true
+     (with OR) or trivially false (with AND).  If so, do not warn.
+     This is a common idiom for testing ranges of data types in
+     portable code.  */
+  lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p);
+  if (!lhs)
+    return;
+  if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
     lhs = C_MAYBE_CONST_EXPR_EXPR (lhs);
 
-  if (rhs && TREE_CODE (rhs) == C_MAYBE_CONST_EXPR)
+  /* If this is an OR operation, invert both sides; now, the result
+     should be always false to get a warning.  */
+  if (or_op)
+    in0_p = !in0_p;
+
+  tem = build_range_check (UNKNOWN_LOCATION, type, lhs, in0_p, low0, high0);
+  if (integer_zerop (tem))
+    return;
+
+  rhs = make_range (op_right, &in1_p, &low1, &high1, &strict_overflow_p);
+  if (!rhs)
+    return;
+  if (TREE_CODE (rhs) == C_MAYBE_CONST_EXPR)
     rhs = C_MAYBE_CONST_EXPR_EXPR (rhs);
 
-  /* If this is an OR operation, invert both sides; we will invert
-     again at the end.  */
+  /* If this is an OR operation, invert both sides; now, the result
+     should be always false to get a warning.  */
   if (or_op)
-    in0_p = !in0_p, in1_p = !in1_p;
+    in1_p = !in1_p;
 
-  /* If both expressions are the same, if we can merge the ranges, and we
-     can build the range test, return it or it inverted.  */
-  if (lhs && rhs && operand_equal_p (lhs, rhs, 0)
+  tem = build_range_check (UNKNOWN_LOCATION, type, rhs, in1_p, low1, high1);
+  if (integer_zerop (tem))
+    return;
+
+  /* If both expressions have the same operand, if we can merge the
+     ranges, and if the range test is always false, then warn.  */
+  if (operand_equal_p (lhs, rhs, 0)
       && merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
                       in1_p, low1, high1)
       && 0 != (tem = build_range_check (UNKNOWN_LOCATION,
-                                       type, lhs, in_p, low, high)))
+                                       type, lhs, in_p, low, high))
+      && integer_zerop (tem))
     {
-      if (TREE_CODE (tem) != INTEGER_CST)
-       return;
-
       if (or_op)
         warning_at (location, OPT_Wlogical_op,
                     "logical %<or%> "
index f43eb54fa3d32f6f95662ac1a810e04ffedcc3a1..d5176b847e1677c7db12c16196cd86b4b2e60ace 100644 (file)
@@ -1,3 +1,8 @@
+2012-05-05  Manuel López-Ibáñez  <manu@gcc.gnu.org>
+
+       PR c/43772
+       * c-c++-common/pr43772.c: New.
+
 2012-05-05  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/41600