aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorManuel López-Ibáñez <manu@gcc.gnu.org>2008-10-29 17:16:46 +0000
committerManuel López-Ibáñez <manu@gcc.gnu.org>2008-10-29 17:16:46 +0000
commitcdd6a337c0e1c4a07a0a45686dcaa159e51f451c (patch)
tree42ccc636ef21cba0db86051f05076ac6b24aa628 /gcc/fold-const.c
parent20ded7a68b10f9c2d1aaa94e89df494bf0ce41a0 (diff)
downloadgcc-cdd6a337c0e1c4a07a0a45686dcaa159e51f451c.zip
gcc-cdd6a337c0e1c4a07a0a45686dcaa159e51f451c.tar.gz
gcc-cdd6a337c0e1c4a07a0a45686dcaa159e51f451c.tar.bz2
re PR middle-end/11492 (Bogus warning with -Wsign-compare)
2008-10-29 Manuel Lopez-Ibanez <manu@gcc.gnu.org> PR 11492 * c-common.c (min_precision): Move to... * tree.c (tree_int_cst_min_precision): ... to here. Renamed. * tree.h (tree_int_cst_min_precision): Declare. * c-common.h (min_precision): Delete declaration. * fold-const.c (tree_binary_nonnegative_warnv_p): Handle multiplication of non-negative integer constants. * c-decl.c (check_bitfield_type_and_width): Rename min_precision to tree_int_cst_min_precision. (finish_enum): Likewise. cp/ * class.c (check_bitfield_decl): Rename min_precision to tree_int_cst_min_precision. * decl.c (finish_enum): Likewise. testsuite/ * gcc.dg/pr11492.c: New. * g++.dg/warn/pr11492.C: New. From-SVN: r141434
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 7a215d2..1a96c3f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -14016,15 +14016,38 @@ tree_binary_nonnegative_warnv_p (enum tree_code code, tree type, tree op0,
/* zero_extend(x) * zero_extend(y) is non-negative if x and y are
both unsigned and their total bits is shorter than the result. */
if (TREE_CODE (type) == INTEGER_TYPE
- && TREE_CODE (op0) == NOP_EXPR
- && TREE_CODE (op1) == NOP_EXPR)
+ && (TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == INTEGER_CST)
+ && (TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == INTEGER_CST))
{
- tree inner1 = TREE_TYPE (TREE_OPERAND (op0, 0));
- tree inner2 = TREE_TYPE (TREE_OPERAND (op1, 0));
- if (TREE_CODE (inner1) == INTEGER_TYPE && TYPE_UNSIGNED (inner1)
- && TREE_CODE (inner2) == INTEGER_TYPE && TYPE_UNSIGNED (inner2))
- return TYPE_PRECISION (inner1) + TYPE_PRECISION (inner2)
- < TYPE_PRECISION (type);
+ tree inner0 = (TREE_CODE (op0) == NOP_EXPR)
+ ? TREE_TYPE (TREE_OPERAND (op0, 0))
+ : TREE_TYPE (op0);
+ tree inner1 = (TREE_CODE (op1) == NOP_EXPR)
+ ? TREE_TYPE (TREE_OPERAND (op1, 0))
+ : TREE_TYPE (op1);
+
+ bool unsigned0 = TYPE_UNSIGNED (inner0);
+ bool unsigned1 = TYPE_UNSIGNED (inner1);
+
+ if (TREE_CODE (op0) == INTEGER_CST)
+ unsigned0 = unsigned0 || tree_int_cst_sgn (op0) >= 0;
+
+ if (TREE_CODE (op1) == INTEGER_CST)
+ unsigned1 = unsigned1 || tree_int_cst_sgn (op1) >= 0;
+
+ if (TREE_CODE (inner0) == INTEGER_TYPE && unsigned0
+ && TREE_CODE (inner1) == INTEGER_TYPE && unsigned1)
+ {
+ unsigned int precision0 = (TREE_CODE (op0) == INTEGER_CST)
+ ? tree_int_cst_min_precision (op0, /*unsignedp=*/true)
+ : TYPE_PRECISION (inner0);
+
+ unsigned int precision1 = (TREE_CODE (op1) == INTEGER_CST)
+ ? tree_int_cst_min_precision (op1, /*unsignedp=*/true)
+ : TYPE_PRECISION (inner1);
+
+ return precision0 + precision1 < TYPE_PRECISION (type);
+ }
}
return false;