Patch to expand_expr:MINUS_EXPR

Jason Merrill
Mon Oct 4 01:38:00 GMT 1999

When we would reach this point for subtracting some constant from a pointer
value, we would try to negate the constant in the POINTER_TYPE, which fails
because POINTER_TYPEs are unsigned.  So then we would take the signed_type
of that, and assume it would work.  But of course it doesn't, since the
signed_type of a POINTER_TYPE is the same, unsigned, POINTER_TYPE.  So we
would end up with a very large unsigned value.  Expanding this to RTX often
fixed the problem, as RTX has no concept of signed/unsigned, and so the
value would magically become signed again, but that doesn't work when
cross-compiling from a 32-bit host to a 64-bit target.

I don't actually understand why we're trying to do the negation here at
all, since expand_binop seems perfectly capable of doing it for us without
the semantic pitfalls, but I assume there's some reason.

1999-10-04  Jason Merrill  <>

	* expr.c (expand_expr, case MINUS_EXPR): If negation fails, just

Index: expr.c
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.174
diff -c -p -r1.174 expr.c
*** expr.c	1999/09/23 11:34:48	1.174
--- expr.c	1999/10/04 08:30:33
*************** expand_expr (exp, target, tmode, modifie
*** 7128,7148 ****
  	  tree negated = fold (build1 (NEGATE_EXPR, type,
  				       TREE_OPERAND (exp, 1)));
- 	  /* Deal with the case where we can't negate the constant
- 	     in TYPE.  */
  	  if (TREE_UNSIGNED (type) || TREE_OVERFLOW (negated))
! 	    {
! 	      tree newtype = signed_type (type);
! 	      tree newop0 = convert (newtype, TREE_OPERAND (exp, 0));
! 	      tree newop1 = convert (newtype, TREE_OPERAND (exp, 1));
! 	      tree newneg = fold (build1 (NEGATE_EXPR, newtype, newop1));
! 	      if (! TREE_OVERFLOW (newneg))
! 		return expand_expr (convert (type, 
! 					     build (PLUS_EXPR, newtype,
! 						    newop0, newneg)),
! 				    target, tmode, ro_modifier);
! 	    }
  	      exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0), negated);
--- 7128,7138 ----
  	  tree negated = fold (build1 (NEGATE_EXPR, type,
  				       TREE_OPERAND (exp, 1)));
  	  if (TREE_UNSIGNED (type) || TREE_OVERFLOW (negated))
! 	    /* If we can't negate the constant in TYPE, leave it alone and
! 	       expand_binop will negate it for us.  We used to try to do it
! 	       here in the signed version of TYPE, but that doesn't work
! 	       on POINTER_TYPEs.  */;
  	      exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0), negated);

More information about the Gcc-patches mailing list