re PR c/63357 (Warn for P && P and P || P (same expression used multiple times in...
authorMarek Polacek <polacek@redhat.com>
Fri, 24 Apr 2015 12:10:52 +0000 (12:10 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Fri, 24 Apr 2015 12:10:52 +0000 (12:10 +0000)
PR c/63357
* c-common.c (warn_logical_operator): Warn if the operands have the
same expressions.

* doc/invoke.texi: Update description of -Wlogical-op.

* c-c++-common/Wlogical-op-1.c: New test.

From-SVN: r222408

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/Wlogical-op-1.c [new file with mode: 0644]

index 4bb36799a17935f329174cc9c0e71092cd3b24be..d489b4a7d85f5cdaac489dfab593a6178f2f497d 100644 (file)
@@ -3,6 +3,9 @@
        PR c/61534
        * input.h (from_macro_expansion_at): Define.
 
+       PR c/63357
+       * doc/invoke.texi: Update description of -Wlogical-op.
+
 2015-04-24  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * config/arm/unknown-elf.h (ASM_OUTPUT_ALIGNED_DECL_LOCAL): fix
index 718aa2ad0a00cd58c2b7b82fbc87fa87d5e3a2bd..1eb27cd4bcec7c010ea007e4d900169202ee9b2f 100644 (file)
@@ -4,6 +4,10 @@
        * c-common.c (c_fully_fold_internal): Use OPT_Wshift_count_negative
        and OPT_Wshift_count_overflow.
 
+       PR c/63357
+       * c-common.c (warn_logical_operator): Warn if the operands have the
+       same expressions.
+
 2015-04-24  Marek Polacek  <polacek@redhat.com>
 
        PR c/61534
index b8e141eb42fed2f088cec09ed9aeb0e624f409cf..9797e1701d3fc54d409943fea7e2a93f7897dbd7 100644 (file)
@@ -1781,22 +1781,35 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
     return;
 
   /* If both expressions have the same operand, if we can merge the
-     ranges, and if the range test is always false, then warn.  */
+     ranges, ...  */
   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))
-      && integer_zerop (tem))
+                      in1_p, low1, high1))
     {
-      if (or_op)
-        warning_at (location, OPT_Wlogical_op,
-                    "logical %<or%> "
-                    "of collectively exhaustive tests is always true");
-      else
-        warning_at (location, OPT_Wlogical_op,
-                    "logical %<and%> "
-                    "of mutually exclusive tests is always false");
+      tem = build_range_check (UNKNOWN_LOCATION, type, lhs, in_p, low, high);
+      /* ... and if the range test is always false, then warn.  */
+      if (tem && integer_zerop (tem))
+       {
+         if (or_op)
+           warning_at (location, OPT_Wlogical_op,
+                       "logical %<or%> of collectively exhaustive tests is "
+                       "always true");
+         else
+           warning_at (location, OPT_Wlogical_op,
+                       "logical %<and%> of mutually exclusive tests is "
+                       "always false");
+       }
+      /* Or warn if the operands have exactly the same range, e.g.
+        A > 0 && A > 0.  */
+      else if (low0 == low1 && high0 == high1)
+       {
+         if (or_op)
+           warning_at (location, OPT_Wlogical_op,
+                       "logical %<or%> of equal expressions");
+         else
+           warning_at (location, OPT_Wlogical_op,
+                       "logical %<and%> of equal expressions");
+       }
     }
 }
 
index a939ff7467065366880be8e1141f1bcaef4045b5..52e2e2218c120afa815368dc434caad085018c06 100644 (file)
@@ -4936,7 +4936,12 @@ programmer intended to use @code{strcmp}.  This warning is enabled by
 @opindex Wno-logical-op
 Warn about suspicious uses of logical operators in expressions.
 This includes using logical operators in contexts where a
-bit-wise operator is likely to be expected.
+bit-wise operator is likely to be expected.  Also warns when
+the operands of a logical operator are the same:
+@smallexample
+extern int a;
+if (a < 0 && a < 0) @{ @dots{} @}
+@end smallexample
 
 @item -Wlogical-not-parentheses
 @opindex Wlogical-not-parentheses
index 936a164a3a26892e5ba930436c8cb95117e42e29..375ad1d5459c00261b12b9ac9165ce32fb1e9e57 100644 (file)
@@ -3,6 +3,9 @@
        PR c/65830
        * c-c++-common/pr65830.c: New test.
 
+       PR c/63357
+       * c-c++-common/Wlogical-op-1.c: New test.
+
 2015-04-24  Marek Polacek  <polacek@redhat.com>
 
        PR c/61534
diff --git a/gcc/testsuite/c-c++-common/Wlogical-op-1.c b/gcc/testsuite/c-c++-common/Wlogical-op-1.c
new file mode 100644 (file)
index 0000000..33d4f38
--- /dev/null
@@ -0,0 +1,109 @@
+/* PR c/63357 */
+/* { dg-do compile } */
+/* { dg-options "-Wlogical-op" } */
+
+#ifndef __cplusplus
+# define bool _Bool
+# define true 1
+# define false 0
+#endif
+
+extern int bar (void);
+extern int *p;
+struct R { int a, b; } S;
+
+void
+andfn (int a, int b)
+{
+  if (a && a) {}               /* { dg-warning "logical .and. of equal expressions" } */
+  if (!a && !a) {}             /* { dg-warning "logical .and. of equal expressions" } */
+  if (!!a && !!a) {}           /* { dg-warning "logical .and. of equal expressions" } */
+  if (a > 0 && a > 0) {}       /* { dg-warning "logical .and. of equal expressions" } */
+  if (a < 0 && a < 0) {}       /* { dg-warning "logical .and. of equal expressions" } */
+  if (a == 0 && a == 0) {}     /* { dg-warning "logical .and. of equal expressions" } */
+  if (a <= 0 && a <= 0) {}     /* { dg-warning "logical .and. of equal expressions" } */
+  if (a >= 0 && a >= 0) {}     /* { dg-warning "logical .and. of equal expressions" } */
+  if (a == 0 && !(a != 0)) {}  /* { dg-warning "logical .and. of equal expressions" } */
+
+  if (a && a && a) {}          /* { dg-warning "logical .and. of equal expressions" } */
+  if ((a + 1) && (a + 1)) {}   /* { dg-warning "logical .and. of equal expressions" } */
+  if ((10 * a) && (a * 10)) {} /* { dg-warning "logical .and. of equal expressions" } */
+  if (!!a && a) {}             /* { dg-warning "logical .and. of equal expressions" } */
+
+  if (*p && *p) {}             /* { dg-warning "logical .and. of equal expressions" } */
+  if (p[0] && p[0]) {}         /* { dg-warning "logical .and. of equal expressions" } */
+  if (S.a && S.a) {}           /* { dg-warning "logical .and. of equal expressions" } */
+  if ((bool) a && (bool) a) {} /* { dg-warning "logical .and. of equal expressions" } */
+  if ((unsigned) a && a) {}    /* { dg-warning "logical .and. of equal expressions" } */
+
+  /* Stay quiet here.  */
+  if (a && b) {}
+  if (!a && !b) {}
+  if (!!a && !!b) {}
+  if (a > 0 && b > 0) {}
+  if (a < 0 && b < 0) {}
+  if (a == 0 && b == 0) {}
+  if (a <= 0 && b <= 0) {}
+  if (a >= 0 && b >= 0) {}
+
+  if (a > 0 && a > 1) {}
+  if (a > -2 && a > 1) {}
+  if (a && (short) a) {}
+  if ((char) a && a) {}
+  if (++a && a) {}
+  if (++a && ++a) {}
+  if (a && --a) {}
+  if (a && a / 2) {}
+  if (bar () && bar ()) {}
+  if (p && *p) {}
+  if (p[0] && p[1]) {}
+  if (S.a && S.b) {}
+}
+
+void
+orfn (int a, int b)
+{
+  if (a || a) {}               /* { dg-warning "logical .or. of equal expressions" } */
+  if (!a || !a) {}             /* { dg-warning "logical .or. of equal expressions" } */
+  if (!!a || !!a) {}           /* { dg-warning "logical .or. of equal expressions" } */
+  if (a > 0 || a > 0) {}       /* { dg-warning "logical .or. of equal expressions" } */
+  if (a < 0 || a < 0) {}       /* { dg-warning "logical .or. of equal expressions" } */
+  if (a == 0 || a == 0) {}     /* { dg-warning "logical .or. of equal expressions" } */
+  if (a <= 0 || a <= 0) {}     /* { dg-warning "logical .or. of equal expressions" } */
+  if (a >= 0 || a >= 0) {}     /* { dg-warning "logical .or. of equal expressions" } */
+  if (a == 0 || !(a != 0)) {}  /* { dg-warning "logical .or. of equal expressions" } */
+
+  if (a || a || a) {}          /* { dg-warning "logical .or. of equal expressions" } */
+  if ((a + 1) || (a + 1)) {}   /* { dg-warning "logical .or. of equal expressions" } */
+  if ((10 * a) || (a * 10)) {} /* { dg-warning "logical .or. of equal expressions" } */
+  if (!!a || a) {}             /* { dg-warning "logical .or. of equal expressions" } */
+
+  if (*p || *p) {}             /* { dg-warning "logical .or. of equal expressions" } */
+  if (p[0] || p[0]) {}         /* { dg-warning "logical .or. of equal expressions" } */
+  if (S.a || S.a) {}           /* { dg-warning "logical .or. of equal expressions" } */
+  if ((bool) a || (bool) a) {} /* { dg-warning "logical .or. of equal expressions" } */
+  if ((unsigned) a || a) {}    /* { dg-warning "logical .or. of equal expressions" } */
+
+  /* Stay quiet here.  */
+  if (a || b) {}
+  if (!a || !b) {}
+  if (!!a || !!b) {}
+  if (a > 0 || b > 0) {}
+  if (a < 0 || b < 0) {}
+  if (a == 0 || b == 0) {}
+  if (a <= 0 || b <= 0) {}
+  if (a >= 0 || b >= 0) {}
+
+  if (a > 0 || a > 1) {}
+  if (a > -2 || a > 1) {}
+  if (a || (short) a) {}
+  if ((char) a || a) {}
+  if (++a || a) {}
+  if (++a || ++a) {}
+  if (a || --a) {}
+  if (a || a / 2) {}
+  if (bar () || bar ()) {}
+  if (p || *p) {}
+  if (p[0] || p[1]) {}
+  if (S.a || S.b) {}
+}