Commit bc7fe952 by Marek Polacek Committed by Marek Polacek

re PR c/81783 (-Wtautological-compare could do better)

	PR c/81783
	* c-warn.c (warn_tautological_bitwise_comparison): New function.
	(warn_tautological_cmp): Call it.

	* doc/invoke.texi: Update -Wtautological-compare documentation.

	* c-c++-common/Wtautological-compare-5.c: New test.

From-SVN: r251660
parent 8713d0f1
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
......
......@@ -321,6 +321,59 @@ find_array_ref_with_const_idx_r (tree *expr_p, int *, void *)
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. */
......@@ -337,6 +390,8 @@ warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs)
|| 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))
......
......@@ -5492,6 +5492,14 @@ int i = 1;
@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
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment