Skip to content

Commit bad28c4

Browse files
committed
[libc++] Make _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS export members
When building libc++ with hidden visibility, we want explicit template instantiations to export members. This is consistent with existing Windows behavior, and is necessary for clients to be able to link against a hidden visibility built libc++ without running into lots of missing symbols. An unfortunate side effect, however, is that any template methods of a class with an explicit instantiation will get default visibility when instantiated, unless the methods are explicitly marked inline or hidden visibility. This is not desirable for clients of libc++ headers who wish to control their visibility, and led to PR30642. Annotate all problematic methods with an explicit visibility specifier to avoid this. The problematic methods were found by running https://github.com/smeenai/bad-visibility-finder against the libc++ headers after making the _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS change. The methods were marked with the new _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS macro, which was created for this purpose. It should be noted that _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS was originally intended to expand to default visibility, and was changed to expanding to default type visibility to fix PR30642. The visibility macro documentation was not updated accordingly, however, so this change makes the macro consistent with its documentation again, while explicitly fixing the methods which resulted in that PR. Differential Revision: https://reviews.llvm.org/D29157 llvm-svn: 296731
1 parent 414fbb4 commit bad28c4

File tree

5 files changed

+66
-17
lines changed

5 files changed

+66
-17
lines changed

libcxx/docs/DesignDocs/VisibilityMacros.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,35 @@ Visibility Macros
110110
the extern template declaration) as exported on Windows, as discussed above.
111111
On all other platforms, this macro has an empty definition.
112112

113+
**_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS**
114+
Mark a symbol as hidden so it will not be exported from shared libraries. This
115+
is intended specifically for method templates of either classes marked with
116+
`_LIBCPP_TYPE_VIS` or classes with an extern template instantiation
117+
declaration marked with `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS`.
118+
119+
When building libc++ with hidden visibility, we want explicit template
120+
instantiations to export members, which is consistent with existing Windows
121+
behavior. We also want classes annotated with `_LIBCPP_TYPE_VIS` to export
122+
their members, which is again consistent with existing Windows behavior.
123+
Both these changes are necessary for clients to be able to link against a
124+
libc++ DSO built with hidden visibility without encountering missing symbols.
125+
126+
An unfortunate side effect, however, is that method templates of classes
127+
either marked `_LIBCPP_TYPE_VIS` or with extern template instantiation
128+
declarations marked with `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` also get default
129+
visibility when instantiated. These methods are often implicitly instantiated
130+
inside other libraries which use the libc++ headers, and will therefore end up
131+
being exported from those libraries, since those implicit instantiations will
132+
receive default visibility. This is not acceptable for libraries that wish to
133+
control their visibility, and led to PR30642.
134+
135+
Consequently, all such problematic method templates are explicitly marked
136+
either hidden (via this macro) or inline, so that they don't leak into client
137+
libraries. The problematic methods were found by running
138+
`bad-visibility-finder <https://github.com/smeenai/bad-visibility-finder>`_
139+
against the libc++ headers after making `_LIBCPP_TYPE_VIS` and
140+
`_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` expand to default visibility.
141+
113142
**_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY**
114143
Mark a member function of a class template as visible and always inline. This
115144
macro should only be applied to member functions of class templates that are

libcxx/include/__config

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ namespace std {
591591
#define _LIBCPP_EXTERN_VIS _LIBCPP_DLL_VIS
592592
#define _LIBCPP_EXCEPTION_ABI _LIBCPP_DLL_VIS
593593
#define _LIBCPP_HIDDEN
594+
#define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
594595
#define _LIBCPP_TEMPLATE_VIS
595596
#define _LIBCPP_FUNC_VIS_ONLY
596597
#define _LIBCPP_ENUM_VIS
@@ -614,6 +615,9 @@ namespace std {
614615
#endif
615616
#endif
616617

618+
// The inline should be removed once PR32114 is resolved
619+
#define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS inline _LIBCPP_HIDDEN
620+
617621
#ifndef _LIBCPP_FUNC_VIS
618622
#if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
619623
#define _LIBCPP_FUNC_VIS __attribute__ ((__visibility__("default")))
@@ -668,7 +672,7 @@ namespace std {
668672

669673
#ifndef _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
670674
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && __has_attribute(__type_visibility__)
671-
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __attribute__ ((__type_visibility__("default")))
675+
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __attribute__ ((__visibility__("default")))
672676
# else
673677
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
674678
# endif

libcxx/include/locale

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -623,17 +623,20 @@ protected:
623623
~num_get() {}
624624

625625
template <class _Fp>
626-
inline iter_type __do_get_floating_point
626+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
627+
iter_type __do_get_floating_point
627628
(iter_type __b, iter_type __e, ios_base& __iob,
628629
ios_base::iostate& __err, _Fp& __v) const;
629630

630631
template <class _Signed>
631-
inline iter_type __do_get_signed
632+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
633+
iter_type __do_get_signed
632634
(iter_type __b, iter_type __e, ios_base& __iob,
633635
ios_base::iostate& __err, _Signed& __v) const;
634636

635637
template <class _Unsigned>
636-
inline iter_type __do_get_unsigned
638+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
639+
iter_type __do_get_unsigned
637640
(iter_type __b, iter_type __e, ios_base& __iob,
638641
ios_base::iostate& __err, _Unsigned& __v) const;
639642

libcxx/include/string

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ public:
792792
basic_string(const basic_string& __str, size_type __pos,
793793
const _Allocator& __a = _Allocator());
794794
template<class _Tp>
795+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
795796
basic_string(const _Tp& __t, size_type __pos, size_type __n,
796797
const allocator_type& __a = allocator_type(),
797798
typename enable_if<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value, void>::type* = 0);
@@ -927,7 +928,8 @@ public:
927928
basic_string& append(__self_view __sv) { return append(__sv.data(), __sv.size()); }
928929
basic_string& append(const basic_string& __str, size_type __pos, size_type __n=npos);
929930
template <class _Tp>
930-
inline typename enable_if
931+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
932+
typename enable_if
931933
<
932934
__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
933935
basic_string&
@@ -937,9 +939,11 @@ public:
937939
basic_string& append(const value_type* __s);
938940
basic_string& append(size_type __n, value_type __c);
939941
template <class _ForwardIterator>
940-
inline basic_string& __append_forward_unsafe(_ForwardIterator, _ForwardIterator);
942+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
943+
basic_string& __append_forward_unsafe(_ForwardIterator, _ForwardIterator);
941944
template<class _InputIterator>
942-
inline typename enable_if
945+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
946+
typename enable_if
943947
<
944948
__is_exactly_input_iterator<_InputIterator>::value
945949
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
@@ -952,7 +956,8 @@ public:
952956
return *this;
953957
}
954958
template<class _ForwardIterator>
955-
inline typename enable_if
959+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
960+
typename enable_if
956961
<
957962
__is_forward_iterator<_ForwardIterator>::value
958963
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
@@ -988,7 +993,8 @@ public:
988993
#endif
989994
basic_string& assign(const basic_string& __str, size_type __pos, size_type __n=npos);
990995
template <class _Tp>
991-
inline typename enable_if
996+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
997+
typename enable_if
992998
<
993999
__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
9941000
basic_string&
@@ -998,15 +1004,17 @@ public:
9981004
basic_string& assign(const value_type* __s);
9991005
basic_string& assign(size_type __n, value_type __c);
10001006
template<class _InputIterator>
1001-
inline typename enable_if
1007+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1008+
typename enable_if
10021009
<
10031010
__is_exactly_input_iterator<_InputIterator>::value
10041011
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
10051012
basic_string&
10061013
>::type
10071014
assign(_InputIterator __first, _InputIterator __last);
10081015
template<class _ForwardIterator>
1009-
inline typename enable_if
1016+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1017+
typename enable_if
10101018
<
10111019
__is_forward_iterator<_ForwardIterator>::value
10121020
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
@@ -1023,7 +1031,8 @@ public:
10231031
_LIBCPP_INLINE_VISIBILITY
10241032
basic_string& insert(size_type __pos1, __self_view __sv) { return insert(__pos1, __sv.data(), __sv.size()); }
10251033
template <class _Tp>
1026-
inline typename enable_if
1034+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1035+
typename enable_if
10271036
<
10281037
__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
10291038
basic_string&
@@ -1037,15 +1046,17 @@ public:
10371046
_LIBCPP_INLINE_VISIBILITY
10381047
iterator insert(const_iterator __pos, size_type __n, value_type __c);
10391048
template<class _InputIterator>
1040-
inline typename enable_if
1049+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1050+
typename enable_if
10411051
<
10421052
__is_exactly_input_iterator<_InputIterator>::value
10431053
|| !__libcpp_string_gets_noexcept_iterator<_InputIterator>::value,
10441054
iterator
10451055
>::type
10461056
insert(const_iterator __pos, _InputIterator __first, _InputIterator __last);
10471057
template<class _ForwardIterator>
1048-
inline typename enable_if
1058+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1059+
typename enable_if
10491060
<
10501061
__is_forward_iterator<_ForwardIterator>::value
10511062
&& __libcpp_string_gets_noexcept_iterator<_ForwardIterator>::value,
@@ -1070,7 +1081,8 @@ public:
10701081
basic_string& replace(size_type __pos1, size_type __n1, __self_view __sv) { return replace(__pos1, __n1, __sv.data(), __sv.size()); }
10711082
basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2=npos);
10721083
template <class _Tp>
1073-
inline typename enable_if
1084+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1085+
typename enable_if
10741086
<
10751087
__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value,
10761088
basic_string&
@@ -1090,7 +1102,8 @@ public:
10901102
_LIBCPP_INLINE_VISIBILITY
10911103
basic_string& replace(const_iterator __i1, const_iterator __i2, size_type __n, value_type __c);
10921104
template<class _InputIterator>
1093-
inline typename enable_if
1105+
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
1106+
typename enable_if
10941107
<
10951108
__is_input_iterator<_InputIterator>::value,
10961109
basic_string&

libcxx/lib/abi/CHANGELOG.TXT

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ New entries should be added directly below the "Version" header.
1616
Version 5.0
1717
-----------
1818

19-
* rTBD - Remove std::num_get template methods which should be inline
19+
* r296729 - Remove std::num_get template methods which should be inline
2020

2121
These functions should never have had visible definitions in the dylib but
2222
since they were previously not specified with 'inline' they accidentally

0 commit comments

Comments
 (0)