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> 2017-09-04 Jeff Law <law@redhat.com>
PR tree-optimization/64910 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> 2017-09-01 Boris Kolpackov <boris@codesynthesis.com>
* c-opts.c (c_common_finish): Write dependency information even if * 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 *) ...@@ -321,6 +321,59 @@ find_array_ref_with_const_idx_r (tree *expr_p, int *, void *)
return NULL_TREE; 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 /* 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 is the location of the comparison with code CODE, LHS and RHS are
operands of the comparison. */ operands of the comparison. */
...@@ -337,6 +390,8 @@ warn_tautological_cmp (location_t loc, enum tree_code code, tree lhs, tree rhs) ...@@ -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))) || from_macro_expansion_at (EXPR_LOCATION (rhs)))
return; return;
warn_tautological_bitwise_comparison (loc, code, lhs, rhs);
/* We do not warn for constants because they are typical of macro /* We do not warn for constants because they are typical of macro
expansions that test for features, sizeof, and similar. */ expansions that test for features, sizeof, and similar. */
if (CONSTANT_CLASS_P (fold_for_warn (lhs)) if (CONSTANT_CLASS_P (fold_for_warn (lhs))
......
...@@ -5492,6 +5492,14 @@ int i = 1; ...@@ -5492,6 +5492,14 @@ int i = 1;
@dots{} @dots{}
if (i > i) @{ @dots{} @} if (i > i) @{ @dots{} @}
@end smallexample @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}. This warning is enabled by @option{-Wall}.
@item -Wtrampolines @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> 2017-09-04 Jeff Law <law@redhat.com>
PR tree-optimization/64910 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