aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-typeck.c38
2 files changed, 42 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2c2a869..4543e22 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
* reload1.c (move2add_note_store): Correct typo checking for
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index ec89e26..e28fa39 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. */