From: J"orn Rennecke Date: Thu, 30 Aug 2001 12:46:52 +0000 (+0000) Subject: c-typeck.c (pointer_diff): Try to eliminate common term before doing conversions. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=95602da11cade17438211fe316b95e9dd5a68dd4;p=gcc.git c-typeck.c (pointer_diff): Try to eliminate common term before doing conversions. * c-typeck.c (pointer_diff): Try to eliminate common term before doing conversions. From-SVN: r45285 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2c2a8699f1b..4543e228274 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +Thu Aug 30 10:21:43 2001 J"orn Rennecke + + * c-typeck.c (pointer_diff): Try to eliminate common term before + doing conversions. + 2001-08-29 Geoffrey Keating * reload1.c (move2add_note_store): Correct typo checking for diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index ec89e2603ed..e28fa399d27 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -2684,6 +2684,8 @@ pointer_diff (op0, op1) tree restype = ptrdiff_type_node; tree target_type = TREE_TYPE (TREE_TYPE (op0)); + tree con0, con1, lit0, lit1; + tree orig_op1 = op1; if (pedantic || warn_pointer_arith) { @@ -2693,6 +2695,40 @@ pointer_diff (op0, op1) pedwarn ("pointer to a function used in subtraction"); } + /* If the conversion to ptrdiff_type does anything like widening or + converting a partial to an integral mode, we get a convert_expression + that is in the way to do any simplifications. + (fold-const.c doesn't know that the extra bits won't be needed. + split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a + different mode in place.) + So first try to find a common term here 'by hand'; we want to cover + at least the cases that occur in legal static initializers. */ + con0 = TREE_CODE (op0) == NOP_EXPR ? TREE_OPERAND (op0, 0) : op0; + con1 = TREE_CODE (op1) == NOP_EXPR ? TREE_OPERAND (op1, 0) : op1; + + if (TREE_CODE (con0) == PLUS_EXPR) + { + lit0 = TREE_OPERAND (con0, 1); + con0 = TREE_OPERAND (con0, 0); + } + else + lit0 = integer_zero_node; + + if (TREE_CODE (con1) == PLUS_EXPR) + { + lit1 = TREE_OPERAND (con1, 1); + con1 = TREE_OPERAND (con1, 0); + } + else + lit1 = integer_zero_node; + + if (operand_equal_p (con0, con1, 0)) + { + op0 = lit0; + op1 = lit1; + } + + /* First do the subtraction as integers; then drop through to build the divide operator. Do not do default conversions on the minus operator @@ -2701,7 +2737,7 @@ pointer_diff (op0, op1) op0 = build_binary_op (MINUS_EXPR, convert (restype, op0), convert (restype, op1), 0); /* This generates an error if op1 is pointer to incomplete type. */ - if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) + if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) error ("arithmetic on pointer to an incomplete type"); /* This generates an error if op0 is pointer to incomplete type. */