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
This commit is contained in:
J"orn Rennecke 2001-08-30 12:46:52 +00:00 committed by Joern Rennecke
parent f232e4a500
commit 95602da11c
2 changed files with 42 additions and 1 deletions

View File

@ -1,3 +1,8 @@
Thu Aug 30 10:21:43 2001 J"orn Rennecke <amylaar@redhat.com>
* c-typeck.c (pointer_diff): Try to eliminate common term before
doing conversions.
2001-08-29 Geoffrey Keating <geoffk@redhat.com> 2001-08-29 Geoffrey Keating <geoffk@redhat.com>
* reload1.c (move2add_note_store): Correct typo checking for * reload1.c (move2add_note_store): Correct typo checking for

View File

@ -2684,6 +2684,8 @@ pointer_diff (op0, op1)
tree restype = ptrdiff_type_node; tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (TREE_TYPE (op0)); tree target_type = TREE_TYPE (TREE_TYPE (op0));
tree con0, con1, lit0, lit1;
tree orig_op1 = op1;
if (pedantic || warn_pointer_arith) if (pedantic || warn_pointer_arith)
{ {
@ -2693,6 +2695,40 @@ pointer_diff (op0, op1)
pedwarn ("pointer to a function used in subtraction"); 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; /* First do the subtraction as integers;
then drop through to build the divide operator. then drop through to build the divide operator.
Do not do default conversions on the minus 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), op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
convert (restype, op1), 0); convert (restype, op1), 0);
/* This generates an error if op1 is pointer to incomplete type. */ /* 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"); error ("arithmetic on pointer to an incomplete type");
/* This generates an error if op0 is pointer to incomplete type. */ /* This generates an error if op0 is pointer to incomplete type. */