On Jan 31, 2008 12:45 AM, DJ Delorie <[EMAIL PROTECTED]> wrote:
>
> I'm debugging an EH failure on m32c-elf (-mcpu=m32c).  The test case
> is this:
>
> extern int U();
>
> void *ra;
>
> main()
> {
>   foo((ra + U()) - 1);
> }
>
> In the context of the bug, sizeof(void *) is 32 (well, PSImode = 24
> bit) and sizeof(int) == 16.  U() returns zero in this example.
>
> So, the call is this:
>
>   foo ((ra + 0) - 1)
>
> What gcc is doing is combining the +0 and -1 into a single value,
> resulting in:
>
>   foo (ra - 1)
>
> However, it's storing the temporary sum in a 16 bit register and ZERO
> extending it to pointer size for the pointer math.  Resulting
> in this:
>
>   foo (ra + 0xffff)
>
> So, two questions:
>
> 1. What are the language rules controlling this expression, and do
>    they have any say about signed vs unsigned wrt the int->pointer
>    promotion?  Pointers are "unsigned" on m32c, in that the unused
>    bits in PSImode are assumed zero.

Ross answered this.

> 2. What part of gcc's target config would control how this expression
>    is evaluated?  If it had sign extended the value, it would have
>    worked.

The problem you are running into is that sizeof(sizetype) != sizeof(void *).
In the middle-end the type used as offset (sizetype) doesn't have a
defined signedness (it's unsigned for C, signed for Ada for example), so
we rely on the fact that its size should match that of pointers (as then
we don't need to worry about sign or zero extension).

Yeah, we should have introduced a new type and not abused sizetype
here.

You can try fixing it in expansion of POINTER_PLUS_EXPR and force
sign-extension of the offset.

Richard.

Reply via email to