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
* 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
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");
+ }
}
}
@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
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
--- /dev/null
+/* 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) {}
+}