Note1: I am not subscribed to the gcc list, please use reply-all. Note2: I think the clang list is moderated for the first post, but it is usually really fast. Sorry about that.
I recently implemented an optimization in LLVM to hide symbols that the we "know" are available in every DSO that uses them. This is very similar to a more generic optimization that is possible during LTO when using recent versions of the gold plugin. Unfortunately, this found a bug in both gcc and clang (or in the itanium ABI, it is not very clear). The testcase is $ cat test.h struct foo { virtual ~foo(); }; struct bar : public foo { virtual void zed(); }; $ cat def.cpp #include "test.h" void bar::zed() { } $ cat undef.cpp #include "test.h" void f() { foo *x(new bar); delete x; } Both gcc (>= 4.6) and clang will produce and undefined reference to _ZN3barD0Ev when compiling undef.cpp with optimizations: $ ~/gcc/build/gcc/xgcc -B ~/gcc/build/gcc/ -c undef.cpp -o undef.o -O3 -fPIC $ nm undef.o | grep D0 U _ZN3barD0Ev And, when using LTO, a shared library built from def.cpp has a visible vtable, but the destructor itself is not visible: $ ~/gcc/build/gcc/xgcc -B ~/gcc/build/gcc/ -c def.cpp -o def.o -O3 -flto -fPIC $ ~/gcc/build/gcc/xgcc -B ~/gcc/build/gcc/ def.o -o def.so -shared -fuse-linker-plugin $ readelf -sDW def.so | grep bar 12 7: 0000000000000931 5 OBJECT WEAK DEFAULT 13 _ZTS3bar 11 10: 0000000000001ca0 40 OBJECT WEAK DEFAULT 24 _ZTV3bar 13 14: 0000000000001cd0 24 OBJECT WEAK DEFAULT 24 _ZTI3bar 8 15: 00000000000008b0 10 FUNC GLOBAL DEFAULT 11 _ZN3bar3zedEv And the final result is that we get an undefined reference when linking: $ g++ -shared -o foo.so undef.o def.so -Wl,-z,defs undef.o:undef.cpp:function f(): error: undefined reference to 'bar::~bar()' I can see two ways of solving this and would like for both clang and gcc to implement the same: * Make sure the destructor is emitted everywhere. That is, clang and gcc have a bug in producing an undefined reference to _ZN3barD0Ev. * Make it clear that the file exporting the vtable has to export the symbols used in it. That is, the Itanium c++ abi needs clarification and so does gcc's lto plugin (and the llvm patch I am working on). In an earlier discussion on the llvm list, it was pointed out that * The second solution would probably be the most backward compatible one, as gcc (even without lto) has been producing the undefined symbol since 4.6. * If implementing the second solution, the destructor still has to be a weak symbol on OS X at least. * The first solution has the advantage that it is semantically simpler as it avoids a special case about when a function can be assumed to be available externally. * The first solution has the advantage that more symbols can be marked hidden, as the gcc lto plugin does currently. Cheers, Rafael