Compiling the following program ends up in "main.c:(.text+0x2): warning: internal error: out of range error"
================= main.c ================ //Dummy func void foo(void) {} //Table with address manipulation void (* const pFuncTable[]) (void) = { foo + 0, foo + 1, //need odd offset }; int main(int argc, char* argv[]) { //Call table pFuncTable[1](); return 1; } Looking into the generated assembler gives: pFuncTable: .word gs(foo) .word foo+1 Which is wrong. It should have been gs(foo + 1) or perhaps gs(foo)+1 But the true wrong thing is that gcc out smarts the table (since it's const) and directly does: "call foo+1". This gives the internal error. Even worse is that the compiler does not stop!! IMHO it should stop here, instead it generates this final assembly: 000000a6 <main>: a6: 0e 94 00 00 call 0 ; 0x0 <__vectors> aa: 81 e0 ldi r24, 0x01 ; 1 ac: 90 e0 ldi r25, 0x00 ; 0 ae: 08 95 ret Before I post a note to the existing bug report (it's probably related with http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27192 ) I want to know what foo + 1 is supposed to do. GCC seems to mix up byte address (for lpm) and word addresses (for ijmp/jmp//icall/call). Is it supposed to increment the byte address or the word address? I guess byte addresses are what it's supposed to be, since calling foo + 2 ends up in calling foo + 2 bytes. Leaving foo + 1 as illegal address. And I just found another nasty error: //Dummy func void foo(void) {} //Table with address manipulation void (* const pFuncTable[]) (void) = { foo + 4, //need odd offset }; int main(int argc, char* argv[]) { //Call table pFuncTable[0](); return 1; } This will generate a correct call (4 bytes after foo) but the value in the table is not left shifted! Meaning that a call via the table will generate a call to the wrong address, while the original call is ok. Wouter _______________________________________________ AVR-GCC-list mailing list AVR-GCC-list@nongnu.org http://lists.nongnu.org/mailman/listinfo/avr-gcc-list