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.
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.
mov.l _ra,r3r1 ; 5 movpsi_op/2
jsr.a _U ; 7 call_value/1
sub.w #1,r0 ; 9 addhi3/5
mov.w r0,a0 ; 11 zero_extendhipsi2
mov.l r3r1,a1 ; 29 movpsi_op/2
add.l a0,a1 ; 13 addpsi3/3
push.l a1 ; 30 movpsi_op/5
jsr.a _foo ; 15 call_value/1
The zero_extend shows up in 131r.expand.
003r.original has this:
{
foo (ra + ((unsigned int) U () + -1));
}