GCC and Clang handle visibility attributes on the out-of-line definition of externally instantiated templates differently. For example in the reproducer below Clang will emit both 'foo' and 'bar' with default visibility while GCC only emits a non-hidden 'foo'.
// RUN: g++ -std=c++11 -shared -O3 test.cpp && sym_extract.py a.out // RUN: clang++ -std=c++11 -shared -O3 test.cpp && sym_extract.py a.out #define INLINE_VISIBILITY __attribute__((visibility("hidden"), always_inline)) template <class T> struct Foo { void foo(); void bar(); }; template <class T> void Foo<T>::foo() {} template <class T> inline INLINE_VISIBILITY void Foo<T>::bar() {} template struct Foo<int>;
This difference creates ABI incompatibilities between Clang and GCC built dylibs. Specifically GCC built dylibs lack definitions for various member functions of basic_string, basic_istream, basic_ostream, basic_iostream, and basic_streambuf (All of these types are externally instantiated).
Surprisingly these missing symbols don't cause many problems because the functions are marked always_inline therefore the dylib definition is rarely needed. However when an out-of-line definition is required then GCC built dylibs will fail to link. For example GCC built dylibs cannot build Clang.
This patch works around this issue by adding _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY which is used to mark externally instantiated member functions as always inline. When building the library _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY sets the symbol's visibility to "default" instead of "hidden", otherwise it acts exactly the same as _LIBCPP_INLINE_VISIBILITY.
After applying this patch GCC dylibs now contain:
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7sungetcEv
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5gbumpEi
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7sungetcEv
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9sputbackcEc
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERNS_15basic_streambufIwS2_EE
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_9basic_iosIwS2_EES6_E
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4setpEPcS4_
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6snextcEv
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE4swapERS3_
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE4swapERS3_
- _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_8ios_baseES5_E
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9pubsetbufEPcl
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE10pubseekoffExNS_8ios_base7seekdirEj
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_9basic_iosIwS2_EES6_E
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5pbumpEi
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5seekpENS_4fposI11__mbstate_tEE
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE7getlineEPcl
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sgetcEv
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERNS_15basic_streambufIcS2_EE
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_8ios_baseES5_E
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8in_availEv
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_8ios_baseES5_E
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6sbumpcEv
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_9basic_iosIcS2_EES6_E
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERc
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6snextcEv
- _ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEmw
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE7getlineEPwl
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5tellpEv
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERw
- _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7pubsyncEv
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getEPcl
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_9basic_iosIcS2_EES6_E
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7pubsyncEv
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputcEc
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5seekpExNS_8ios_base7seekdirE
- _ZNKSt3__115basic_streambufIcNS_11char_traitsIcEEE6getlocEv
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5gbumpEi
- _ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEE4swapERS3_
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5seekpENS_4fposI11__mbstate_tEE
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5tellpEv
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRS3_S4_E
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getEPwl
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRS3_S4_E
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4setgEPcS4_S4_
- _ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwmm
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4setgEPwS4_S4_
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8pubimbueERKNS_6localeE
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE4swapERS3_
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE10pubseekposENS_4fposI11__mbstate_tEEj
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5pbumpEi
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sgetcEv
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE4swapERS3_
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE10pubseekposENS_4fposI11__mbstate_tEEj
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputnEPKcl
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5seekpExNS_8ios_base7seekdirE
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sgetnEPwl
- _ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_8ios_baseES5_E
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4setpEPwS4_
- _ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sgetnEPcl
- _ZNKSt3__115basic_streambufIwNS_11char_traitsIwEEE6getlocEv
- _ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8pubimbueERKNS_6localeE
- _ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8in_availEv
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE
- _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcmm
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6sbumpcEv
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE10pubseekoffExNS_8ios_base7seekdirEj
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE
- _ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRS3_S4_E
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9sputbackcEw
- _ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwm
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sputnEPKwl
- _ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRS3_S4_E
- _ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9pubsetbufEPwl
- _ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sputcEw
This patch has no effect on Clang based builds.