With this testcase: int foo (int (*cb)(void)) { return (*cb)(); } static int callback(void) { return 0; }
int main (void) { int callback (void); return foo (callback); } On x86_64 with -fPIC, the address of callback as passed to foo is incorrect. If callback isn't static, it works (through the GOT). If the declaration of callback is removed it works (computes the address as %rip minus something). As written, it does a failed combination of the two. The result is that instead of passing callback's address, it loads the first 8 bytes at callback's address and passes those. (It also erroneously claims callback is unused, but I'm guessing that's a side-effect.) The code is questionable, but my reading of the standard says it's legal and that callback is still static after the (implicitly extern) declaration. % gcc-3.4.4 -O2 -fPIC -Wall -save-temps -o bug bug.c bug.c:2: warning: 'callback' defined but not used % gcc-3.4.4 -v Reading specs from /usr/local/lib/gcc/x86_64-pc-linux-gnu/3.4.4/specs Configured with: /tmp/src/gcc-3.4.4/configure --enable-languages=c,c++ --enable-version-specific-runtime-libs --disable-shared --enable-threads --with-gnu-as --with-gnu-ld --with-pic --host=x86_64-pc-linux-gnu Thread model: posix gcc version 3.4.4 [I bootstrapped this 3.4.4; it also fails with stock 3.4.3 from RedHat.] -- Summary: x86_64 -fPIC code gen bug (extern/static linkage confusion) Product: gcc Version: 3.4.4 Status: UNCONFIRMED Severity: normal Priority: P2 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: mcoiley at yahoo dot com CC: gcc-bugs at gcc dot gnu dot org GCC build triplet: x86_64-pc-linux-gnu GCC host triplet: x86_64-pc-linux-gnu GCC target triplet: x86_64-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24106