Index: docs/DesignDocs/VisibilityMacros.rst =================================================================== --- docs/DesignDocs/VisibilityMacros.rst +++ docs/DesignDocs/VisibilityMacros.rst @@ -110,6 +110,35 @@ the extern template declaration) as exported on Windows, as discussed above. On all other platforms, this macro has an empty definition. +**_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS** + Mark a symbol as hidden so it will not be exported from shared libraries. This + is intended specifically for method templates of either classes marked with + `_LIBCPP_TYPE_VIS` or classes with an extern template instantiation + declaration marked with `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS`. + + When building libc++ with hidden visibility, we want explicit template + instantiations to export members, which is consistent with existing Windows + behavior. We also want classes annotated with `_LIBCPP_TYPE_VIS` to export + their members, which is again consistent with existing Windows behavior. + Both these changes are necessary for clients to be able to link against a + libc++ DSO built with hidden visibility without encountering missing symbols. + + An unfortunate side effect, however, is that method templates of classes + either marked `_LIBCPP_TYPE_VIS` or with extern template instantiation + declarations marked with `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` also get default + visibility when instantiated. These methods are often implicitly instantiated + inside other libraries which use the libc++ headers, and will therefore end up + being exported from those libraries, since those implicit instantiations will + receive default visibility. This is not acceptable for libraries that wish to + control their visibility, and led to PR30642. + + Consequently, all such problematic method templates are explicitly marked + either hidden (via this macro) or inline, so that they don't leak into client + libraries. The problematic methods were found by running + `bad-visibility-finder `_ + against the libc++ headers after making `_LIBCPP_TYPE_VIS` and + `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` expand to default visibility. + **_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY** Mark a member function of a class template as visible and always inline. This macro should only be applied to member functions of class templates that are Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -591,6 +591,7 @@ #define _LIBCPP_EXTERN_VIS _LIBCPP_DLL_VIS #define _LIBCPP_EXCEPTION_ABI _LIBCPP_DLL_VIS #define _LIBCPP_HIDDEN +#define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS #define _LIBCPP_TEMPLATE_VIS #define _LIBCPP_FUNC_VIS_ONLY #define _LIBCPP_ENUM_VIS @@ -614,6 +615,8 @@ #endif #endif +#define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDDEN + #ifndef _LIBCPP_FUNC_VIS #if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) #define _LIBCPP_FUNC_VIS __attribute__ ((__visibility__("default"))) @@ -668,7 +671,7 @@ #ifndef _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS # if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && __has_attribute(__type_visibility__) -# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __attribute__ ((__type_visibility__("default"))) +# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __attribute__ ((__visibility__("default"))) # else # define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS # endif Index: include/locale =================================================================== --- include/locale +++ include/locale @@ -623,16 +623,19 @@ ~num_get() {} template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type __do_get_floating_point (iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const; template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type __do_get_signed (iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const; template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type __do_get_unsigned (iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const; Index: include/string =================================================================== --- include/string +++ include/string @@ -792,6 +792,7 @@ basic_string(const basic_string& __str, size_type __pos, const _Allocator& __a = _Allocator()); template + _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type(), typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type* = 0);