This is another try to get to the bottom of http://crbug.com/56471 hummer:delta thakis$ cat string16.ii typedef long unsigned int size_t; namespace std { template<typename _CharT> class basic_string { private: struct _Rep { void _M_clone(); }; }; template<typename _CharT> void basic_string<_CharT>::_Rep::_M_clone() {} } typedef unsigned short char16; extern template class std::basic_string<char16>; template class std::basic_string<char16>; _M_clone becomes a private external symbol in gcc with -fvisibility=hidden: hummer:delta thakis$ gcc -c string16.ii -fvisibility=hidden hummer:delta thakis$ nm -m string16.o 0000000000000010 (__TEXT,__eh_frame) non-external EH_frame1 0000000000000000 (__TEXT,__text) private external __ZNSbItE4_Rep8_M_cloneEv 0000000000000030 (__TEXT,__eh_frame) private external __ZNSbItE4_Rep8_M_cloneEv.eh (undefined) external ___gxx_personality_v0 It doesn't do that in clang: hummer:delta thakis$ ~/src/llvm/Release+Asserts/bin/clang -c string16.ii -fvisibility=hidden hummer:delta thakis$ nm -m string16.o 0000000000000010 (__TEXT,__eh_frame) non-external EH_frame0 0000000000000000 (__TEXT,__textcoal_nt) weak external __ZNSbItE4_Rep8_M_cloneEv 0000000000000028 (__TEXT,__eh_frame) weak external __ZNSbItE4_Rep8_M_cloneEv.eh It works fine in clang if I move the method out of the containing inner struct or make the class not a template class.
Simpler repro case: template<typename T> class C { struct Inner { void f(); }; }; template<typename T> void C<T>::Inner::f() {} extern template class C<unsigned>; template class C<unsigned>;
Patch attempt at http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20100920/034875.html
Fixed in r114874.