https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61214
Bug ID: 61214 Summary: [4.9 regression] Weird interaction between -fvisibility-inlines-hidden, inline virtuals and devirtualization Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: delr...@dolphin-emu.org Created attachment 32814 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=32814&action=edit Small test case reproducing this issue A shared library (libtest.so) is compiled using -fvisibility=hidden -fvisibility-inlines-hidden. This library exports (visibility=default) a class hierarchy with virtual inline methods: struct VISIBILITY_DEFAULT Base { virtual Base* clone() { return new Base(); }}; struct VISIBILITY_DEFAULT Foo { virtual Base* clone() { return new Foo(); }}; // + at least one method that is defined in a compilation unit, along with the vtable, typeinfo, etc. The code that uses libtest.so looks like this: Base* obj = new Foo(); obj->clone(); When this is compiled to libtest.so, Base::clone and Foo::clone are not present among the exported symbols. This did not cause issues before g++4.9 because g++ was not smart enough to determine that "obj" is always a Foo. It always issued a call through the vtable, which *is* exported by libtest.so (and contains a valid entry for Foo::clone). Now, with g++4.9 and (better) devirtualization, g++ tries to generate a direct call to Foo::clone. But instead of instantiating the inline function, it assumes the inline function is already instantiated. This fails at link time because no definition of Foo::clone can be found. Small test case attached (with Makefile, reproduces the bug on g++4.9 on Linux x86_64). In practice, s/libtest/wxWidgets/, s/Foo::clone/wxCommandEvent::Clone/. Whether this is a bug of wxWidgets that should not be using -fvisibility-inlines-hidden or a bug of g++4.9 that should be instantiating the inline function, is something you will have to debate :)