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)); }