diff options
author | manu <manu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-10-29 17:16:46 +0000 |
---|---|---|
committer | manu <manu@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-10-29 17:16:46 +0000 |
commit | 5485b95993fb050b72cda916567017a2e3698373 (patch) | |
tree | 42ccc636ef21cba0db86051f05076ac6b24aa628 /gcc/fold-const.c | |
parent | 02c52e944f67987d3e2a506e9e3e9c60282db7ae (diff) | |
download | gcc-5485b95993fb050b72cda916567017a2e3698373.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@141434 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 7a215d27cb4..1a96c3f77fc 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; |