aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2015-04-24 12:10:52 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2015-04-24 12:10:52 +0000
commit8c2b7f79721cb9ef50d996ef2073210e7402c69a (patch)
tree109667391d09834474b25b70680f05eff7d00712 /gcc
parent4853031ec832b9fd29e0894016038cc9f83e31cc (diff)
downloadgcc-8c2b7f79721cb9ef50d996ef2073210e7402c69a.zip
gcc-8c2b7f79721cb9ef50d996ef2073210e7402c69a.tar.gz
gcc-8c2b7f79721cb9ef50d996ef2073210e7402c69a.tar.bz2
re PR c/63357 (Warn for P && P and P || P (same expression used multiple times in a condition))
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog3
-rw-r--r--gcc/c-family/ChangeLog4
-rw-r--r--gcc/c-family/c-common.c39
-rw-r--r--gcc/doc/invoke.texi7
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/c-c++-common/Wlogical-op-1.c109
6 files changed, 151 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4bb3679..d489b4a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 718aa2a..1eb27cd 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index b8e141e..9797e17 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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");
+ }
}
}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index a939ff7..52e2e22 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 936a164..375ad1d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..33d4f38
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wlogical-op-1.c
@@ -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) {}
+}