https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86175
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rguenth at gcc dot gnu.org --- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> --- With ld 2.30 it seems to work for me with a simple void foo () {} int main() { return 0; } > gcc-8 t.c -flto -O -Wl,-u,foo,--gc-sections -ffunction-sections --- Comment #2 from zenith432 at users dot sourceforge.net --- It's the visibility that breaks it. Try gcc-8 t.c -flto -O -Wl,-u,foo,--gc-sections -ffunction-sections -fvisibility=hidden Here's a full summary of observed behavior Without '-u foo', foo gets discarded for both LTO, non-LTO build and with any visibility. With '-u foo' On non-LTO build, foo always gets forced in regardless of visibility. The symbol's visibility is not supposed to play a role in the decision-making of applying the '-u foo'. On LTO build - if foo's visibility is either default or protected, it gets forced in. - if foo's visibility is either hidden or internal, it gets discarded. The reason I opened this bug against GCC and not LD - is that LD does not complain about an undefined foo even if '--require-defined=foo' is used in place of '-u foo'. LD believes it is force-including foo, but really gets an empty blob from the LTO plugin for foo.