diff options
author | manu <manu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-05-15 20:08:21 +0000 |
---|---|---|
committer | manu <manu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-05-15 20:08:21 +0000 |
commit | 9c20c4fc5e6367117e36fd2bafb9165da1d09a93 (patch) | |
tree | 6ee4203c725a3a87b87a38848ee077c8ed6e23a3 /gcc/c-common.c | |
parent | 4b0c3b9358fff3b1bcbdf08c318dda43d4cf2510 (diff) | |
download | ppe42-gcc-9c20c4fc5e6367117e36fd2bafb9165da1d09a93.tar.gz ppe42-gcc-9c20c4fc5e6367117e36fd2bafb9165da1d09a93.zip |
2009-05-15 Manuel López-Ibáñez <manu@gcc.gnu.org>
PR 16302
* fold-const.c (make_range,build_range_check,merge_ranges): Move
declaration to...
(merge_ranges): Returns bool.
* tree.h (make_range): .. to here.
(build_range_check): Likewise.
(merge_ranges): Likewise. Renamed from merge_ranges.
* c-typeck.c (parser_build_binary_op): Update calls to
warn_logical_operator.
* c-common.c (warn_logical_operator): Add new warning.
* c-common.h (warn_logical_operator): Update declaration.
cp/
* call.c (build_new_op): Update calls to warn_logical_operator.
testsuite/
* gcc.dg/pr16302.c: New.
* g++.dg/warn/pr16302.C: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147596 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r-- | gcc/c-common.c | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c index df6673c000c..e5c3d0d2eee 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1716,14 +1716,18 @@ overflow_warning (tree value) /* Warn about uses of logical || / && operator in a context where it is likely that the bitwise equivalent was intended by the programmer. We have seen an expression in which CODE is a binary - operator used to combine expressions OP_LEFT and OP_RIGHT, which - before folding had CODE_LEFT and CODE_RIGHT. */ - + operator used to combine expressions OP_LEFT and OP_RIGHT, which before folding + had CODE_LEFT and CODE_RIGHT, into an expression of type TYPE. */ void -warn_logical_operator (location_t location, enum tree_code code, +warn_logical_operator (location_t location, enum tree_code code, tree type, enum tree_code code_left, tree op_left, enum tree_code ARG_UNUSED (code_right), tree op_right) { + int or_op = (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR); + int in0_p, in1_p, in_p; + tree low0, low1, low, high0, high1, high, lhs, rhs, tem; + bool strict_overflow_p = false; + if (code != TRUTH_ANDIF_EXPR && code != TRUTH_AND_EXPR && code != TRUTH_ORIF_EXPR @@ -1743,13 +1747,65 @@ warn_logical_operator (location_t location, enum tree_code code, && !integer_zerop (op_right) && !integer_onep (op_right)) { - if (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR) + if (or_op) warning_at (location, OPT_Wlogical_op, "logical %<or%>" " applied to non-boolean constant"); else warning_at (location, OPT_Wlogical_op, "logical %<and%>" " applied to non-boolean constant"); TREE_NO_WARNING (op_left) = true; + return; + } + + /* We do not warn for constants because they are typical of macro + expansions that test for features. */ + if (CONSTANT_CLASS_P (op_left) || CONSTANT_CLASS_P (op_right)) + return; + + /* This warning only makes sense with logical operands. */ + if (!(truth_value_p (TREE_CODE (op_left)) + || INTEGRAL_TYPE_P (TREE_TYPE (op_left))) + || !(truth_value_p (TREE_CODE (op_right)) + || INTEGRAL_TYPE_P (TREE_TYPE (op_right)))) + return; + + lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p); + rhs = make_range (op_right, &in1_p, &low1, &high1, &strict_overflow_p); + + if (lhs && TREE_CODE (lhs) == C_MAYBE_CONST_EXPR) + lhs = C_MAYBE_CONST_EXPR_EXPR (lhs); + + if (rhs && TREE_CODE (rhs) == C_MAYBE_CONST_EXPR) + rhs = C_MAYBE_CONST_EXPR_EXPR (rhs); + + /* If this is an OR operation, invert both sides; we will invert + again at the end. */ + if (or_op) + in0_p = !in0_p, in1_p = !in1_p; + + /* If both expressions are the same, if we can merge the ranges, and we + can build the range test, return it or it inverted. If one of the + ranges is always true or always false, consider it to be the same + expression as the other. */ + if ((lhs == 0 || rhs == 0 || 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 (type, + lhs != 0 ? lhs + : rhs != 0 ? rhs : integer_zero_node, + in_p, low, high))) + { + if (TREE_CODE (tem) != INTEGER_CST) + return; + + 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"); } } |