+2017-09-04 Marek Polacek <polacek@redhat.com>
+
+ PR c/81783
+ * doc/invoke.texi: Update -Wtautological-compare documentation.
+
2017-09-04 Jeff Law <law@redhat.com>
PR tree-optimization/64910
+2017-09-04 Marek Polacek <polacek@redhat.com>
+
+ PR c/81783
+ * c-warn.c (warn_tautological_bitwise_comparison): New function.
+ (warn_tautological_cmp): Call it.
+
2017-09-01 Boris Kolpackov <boris@codesynthesis.com>
* c-opts.c (c_common_finish): Write dependency information even if
return NULL_TREE;
}
+/* Subroutine of warn_tautological_cmp. Warn about bitwise comparison
+ that always evaluate to true or false. LOC is the location of the
+ ==/!= comparison specified by CODE; LHS and RHS are the usual operands
+ of this comparison. */
+
+static void
+warn_tautological_bitwise_comparison (location_t loc, tree_code code,
+ tree lhs, tree rhs)
+{
+ if (code != EQ_EXPR && code != NE_EXPR)
+ return;
+
+ /* Extract the operands from e.g. (x & 8) == 4. */
+ tree bitop;
+ tree cst;
+ if ((TREE_CODE (lhs) == BIT_AND_EXPR
+ || TREE_CODE (lhs) == BIT_IOR_EXPR)
+ && TREE_CODE (rhs) == INTEGER_CST)
+ bitop = lhs, cst = rhs;
+ else if ((TREE_CODE (rhs) == BIT_AND_EXPR
+ || TREE_CODE (rhs) == BIT_IOR_EXPR)
+ && TREE_CODE (lhs) == INTEGER_CST)
+ bitop = rhs, cst = lhs;
+ else
+ return;
+
+ tree bitopcst;
+ if (TREE_CODE (TREE_OPERAND (bitop, 0)) == INTEGER_CST)
+ bitopcst = TREE_OPERAND (bitop, 0);
+ else if (TREE_CODE (TREE_OPERAND (bitop, 1)) == INTEGER_CST)
+ bitopcst = TREE_OPERAND (bitop, 1);
+ else
+ return;
+
+ wide_int res;
+ if (TREE_CODE (bitop) == BIT_AND_EXPR)
+ res = wi::bit_and (bitopcst, cst);
+ else
+ res = wi::bit_or (bitopcst, cst);
+
+ /* For BIT_AND only warn if (CST2 & CST1) != CST1, and
+ for BIT_OR only if (CST2 | CST1) != CST1. */
+ if (res == cst)
+ return;
+
+ if (code == EQ_EXPR)
+ warning_at (loc, OPT_Wtautological_compare,
+ "bitwise comparison always evaluates to false");
+ else
+ warning_at (loc, OPT_Wtautological_compare,
+ "bitwise comparison always evaluates to true");
+}
+
/* Warn if a self-comparison always evaluates to true or false. LOC
is the location of the comparison with code CODE, LHS and RHS are
operands of the comparison. */
|| from_macro_expansion_at (EXPR_LOCATION (rhs)))
return;
+ warn_tautological_bitwise_comparison (loc, code, lhs, rhs);
+
/* We do not warn for constants because they are typical of macro
expansions that test for features, sizeof, and similar. */
if (CONSTANT_CLASS_P (fold_for_warn (lhs))
@dots{}
if (i > i) @{ @dots{} @}
@end smallexample
+
+This warning also warns about bitwise comparisons that always evaluate
+to true or false, for instance:
+@smallexample
+if ((a & 16) == 10) @{ @dots{} @}
+@end smallexample
+will always be false.
+
This warning is enabled by @option{-Wall}.
@item -Wtrampolines
+2017-09-04 Marek Polacek <polacek@redhat.com>
+
+ PR c/81783
+ * c-c++-common/Wtautological-compare-5.c: New test.
+
2017-09-04 Jeff Law <law@redhat.com>
PR tree-optimization/64910
--- /dev/null
+/* PR c/81783 */
+/* { dg-do compile } */
+/* { dg-options "-Wtautological-compare" } */
+
+enum E { FOO = 128 };
+
+int
+f (int a)
+{
+ if ((a & 16) == 10) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if ((16 & a) == 10) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if (10 == (a & 16)) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if (10 == (16 & a)) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+
+ if ((a & 16) != 10) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if ((16 & a) != 10) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if (10 != (a & 16)) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if (10 != (16 & a)) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+
+ if ((a & 9) == 8)
+ return 1;
+ if ((9 & a) == 8)
+ return 1;
+ if (8 == (a & 9))
+ return 1;
+ if (8 == (9 & a))
+ return 1;
+
+ if ((a & 9) != 8)
+ return 1;
+ if ((9 & a) != 8)
+ return 1;
+ if (8 != (a & 9))
+ return 1;
+ if (8 != (9 & a))
+ return 1;
+
+ if ((a | 16) == 10) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if ((16 | a) == 10) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if (10 == (a | 16)) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if (10 == (16 | a)) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+
+ if ((a | 16) != 10) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if ((16 | a) != 10) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if (10 != (a | 16)) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if (10 != (16 | a)) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+
+ if ((a | 9) == 8) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if ((9 | a) == 8) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if (8 == (a | 9)) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if (8 == (9 | a)) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+
+ if ((a | 9) != 8) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if ((9 | a) != 8) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if (8 != (a | 9)) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if (8 != (9 | a)) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+
+ if ((a & 128) != 1) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if ((128 & a) != 1) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if ((a & FOO) != 1) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if ((FOO & a) != 1) /* { dg-warning "bitwise comparison always evaluates to true" } */
+ return 1;
+ if ((a & 128) == 1) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if ((128 & a) == 1) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if ((a & FOO) == 1) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+ if ((FOO & a) == 1) /* { dg-warning "bitwise comparison always evaluates to false" } */
+ return 1;
+
+#define N 0x10
+ if ((a & N) == 10) /* { dg-bogus "bitwise comparison always evaluates to false" "" { xfail *-*-* } } */
+ return 1;
+ if ((a | N) == 10) /* { dg-bogus "bitwise comparison always evaluates to false" "" { xfail *-*-* } } */
+ return 1;
+
+ return 0;
+}