summaryrefslogtreecommitdiff
path: root/gcc/convert.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-06-15 00:40:49 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2002-06-15 00:40:49 +0000
commit124804066f712c722b351897eee9d7309e5edf32 (patch)
treefd51ff69789e0093e1ae97e5bbca49e30ec16d37 /gcc/convert.c
parent7df2ee7b945b006562a0fa9005b354da7aa8beb4 (diff)
downloadgcc-124804066f712c722b351897eee9d7309e5edf32.tar.gz
* convert.c (convert_to_integer) [LSHIFT_EXPR]: Don't pass
the truncation down when the target type is signed. [trunc1]: Use unsigned arithmetic for LSHIFT_EXPR. * fold-const.c (extract_muldiv) [NOP_EXPR]: Don't pass through the conversion if the target type is a smaller type. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@54627 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/convert.c')
-rw-r--r--gcc/convert.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/gcc/convert.c b/gcc/convert.c
index 970b05cd374..e90ce4c88d6 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -229,9 +229,11 @@ convert_to_integer (type, expr)
case LSHIFT_EXPR:
/* We can pass truncation down through left shifting
- when the shift count is a nonnegative constant. */
+ when the shift count is a nonnegative constant and
+ the target type is unsigned. */
if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST
&& tree_int_cst_sgn (TREE_OPERAND (expr, 1)) >= 0
+ && TREE_UNSIGNED (type)
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
{
/* If shift count is less than the width of the truncated type,
@@ -313,12 +315,22 @@ convert_to_integer (type, expr)
/* Don't do unsigned arithmetic where signed was wanted,
or vice versa.
Exception: if both of the original operands were
- unsigned then can safely do the work as unsigned.
+ unsigned then we can safely do the work as unsigned.
+ Exception: shift operations take their type solely
+ from the first argument.
+ Exception: the LSHIFT_EXPR case above requires that
+ we perform this operation unsigned lest we produce
+ signed-overflow undefinedness.
And we may need to do it as unsigned
if we truncate to the original size. */
if (TREE_UNSIGNED (TREE_TYPE (expr))
|| (TREE_UNSIGNED (TREE_TYPE (arg0))
- && TREE_UNSIGNED (TREE_TYPE (arg1))))
+ && (TREE_UNSIGNED (TREE_TYPE (arg1))
+ || ex_form == LSHIFT_EXPR
+ || ex_form == RSHIFT_EXPR
+ || ex_form == LROTATE_EXPR
+ || ex_form == RROTATE_EXPR))
+ || ex_form == LSHIFT_EXPR)
typex = (*lang_hooks.types.unsigned_type) (typex);
else
typex = (*lang_hooks.types.signed_type) (typex);