The program below confuses gcc in such a way that it generates code loading the byte-address of bar() into the Z register, which causes icall to jump off to neverneverland. Rather, the double-byte address of bar() should be loaded into Z before the indirect call.
This bug is also present in gcc 4.0.3 and 3.4.3. avr-gcc -v gives: Target: avr Configured with: ../gcc-4.1.0/configure --prefix=/home/regehr/gcc-4.1.0-avr-bin --disable-libssp --disable-nls --target=avr Thread model: single gcc version 4.1.0 Compile with: avr-gcc -Os -Wall shifty.c -o shifty.elf Program: struct fseqp_void { void (*p) (void); char *e; }; struct fseqp_void c[2]; void bar (void) { } void foo (void) { int i; for (i=0; i<32; i++); } int main (void) { c[0].e = (char *)bar + 2; c[0].p = bar; foo (); struct fseqp_void x = c[0]; void (*start) (void) = x.p; (*start)(); return 0; } -- Summary: call through function pointer goes to wrong address Product: gcc Version: 4.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: regehr at cs dot utah dot edu GCC host triplet: i686-linux-gnu GCC target triplet: avr http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27192