forked from OSchip/llvm-project
[libc++] Fix extern template visibility for Windows
On Windows, marking an `extern template class` declaration as exported actually forces an instantiation, which is not the desired behavior. Instead, the actual explicit instantiations need to be exported. Differential Revision: https://reviews.llvm.org/D24679 llvm-svn: 281925
This commit is contained in:
parent
1197a1612d
commit
190994e435
|
@ -71,6 +71,26 @@ Visibility Macros
|
|||
However since `_LIBCPP_TYPE_VIS_ONLY` is the same as `_LIBCPP_TYPE_VIS` the
|
||||
visibility is already correct. The macro has an empty definition with GCC.
|
||||
|
||||
**Windows Behavior**: `extern template` and `dllexport` are fundamentally
|
||||
incompatible *on a template class* on Windows; the former suppresses
|
||||
instantiation, while the latter forces it. Specifying both on the same
|
||||
declaration makes the template class be instantiated, which is not desirable
|
||||
inside headers. This macro therefore expands to `dllimport` outside of libc++
|
||||
but nothing inside of it (rather than expanding to `dllexport`); instead, the
|
||||
explicit instantiations themselves are marked as exported. Note that this
|
||||
applies *only* to extern template *classes*. Extern template *functions* obey
|
||||
regular import/export semantics, and applying `dllexport` directly to the
|
||||
extern template declaration is the correct thing to do for them.
|
||||
|
||||
**_LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS**
|
||||
Mark the member functions, typeinfo, and vtable of an explicit instantiation
|
||||
of a class template as being exported by the libc++ library. This attribute
|
||||
must be specified on all template class explicit instantiations.
|
||||
|
||||
It is only necessary to mark the explicit instantiation itself (as opposed to
|
||||
the extern template declaration) as exported on Windows, as discussed above.
|
||||
On all other platforms, this macro has an empty definition.
|
||||
|
||||
**_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY**
|
||||
Mark a member function of a class template as hidden and inline except when
|
||||
building the libc++ library where it marks the symbol as being exported by
|
||||
|
|
|
@ -551,15 +551,20 @@ namespace std {
|
|||
// only really useful for a DLL. _LIBCPP_DLL should be a compiler builtin define ideally...
|
||||
#if defined(_LIBCPP_DLL) && defined(cxx_EXPORTS)
|
||||
# define _LIBCPP_DLL_VIS __declspec(dllexport)
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS _LIBCPP_DLL_VIS
|
||||
#elif defined(_LIBCPP_DLL)
|
||||
# define _LIBCPP_DLL_VIS __declspec(dllimport)
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
#else
|
||||
# define _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
#endif
|
||||
#define _LIBCPP_TYPE_VIS _LIBCPP_DLL_VIS
|
||||
#define _LIBCPP_FUNC_VIS _LIBCPP_DLL_VIS
|
||||
#define _LIBCPP_EXCEPTION_ABI _LIBCPP_DLL_VIS
|
||||
#define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS
|
||||
#define _LIBCPP_HIDDEN
|
||||
#define _LIBCPP_TYPE_VIS_ONLY
|
||||
#define _LIBCPP_FUNC_VIS_ONLY
|
||||
|
@ -619,6 +624,10 @@ namespace std {
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
#endif
|
||||
|
||||
#ifndef _LIBCPP_INLINE_VISIBILITY
|
||||
#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
|
||||
#endif
|
||||
|
|
|
@ -25,19 +25,19 @@
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template class basic_ios<char>;
|
||||
template class basic_ios<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios<wchar_t>;
|
||||
|
||||
template class basic_streambuf<char>;
|
||||
template class basic_streambuf<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf<wchar_t>;
|
||||
|
||||
template class basic_istream<char>;
|
||||
template class basic_istream<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream<wchar_t>;
|
||||
|
||||
template class basic_ostream<char>;
|
||||
template class basic_ostream<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream<wchar_t>;
|
||||
|
||||
template class basic_iostream<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_iostream<char>;
|
||||
|
||||
class _LIBCPP_HIDDEN __iostream_category
|
||||
: public __do_message
|
||||
|
|
|
@ -6031,66 +6031,66 @@ void __throw_runtime_error(const char* msg)
|
|||
#endif
|
||||
}
|
||||
|
||||
template class collate<char>;
|
||||
template class collate<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;
|
||||
|
||||
template class num_get<char>;
|
||||
template class num_get<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get<wchar_t>;
|
||||
|
||||
template struct __num_get<char>;
|
||||
template struct __num_get<wchar_t>;
|
||||
template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<char>;
|
||||
template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get<wchar_t>;
|
||||
|
||||
template class num_put<char>;
|
||||
template class num_put<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put<wchar_t>;
|
||||
|
||||
template struct __num_put<char>;
|
||||
template struct __num_put<wchar_t>;
|
||||
template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<char>;
|
||||
template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put<wchar_t>;
|
||||
|
||||
template class time_get<char>;
|
||||
template class time_get<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get<wchar_t>;
|
||||
|
||||
template class time_get_byname<char>;
|
||||
template class time_get_byname<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname<wchar_t>;
|
||||
|
||||
template class time_put<char>;
|
||||
template class time_put<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put<wchar_t>;
|
||||
|
||||
template class time_put_byname<char>;
|
||||
template class time_put_byname<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname<wchar_t>;
|
||||
|
||||
template class moneypunct<char, false>;
|
||||
template class moneypunct<char, true>;
|
||||
template class moneypunct<wchar_t, false>;
|
||||
template class moneypunct<wchar_t, true>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, false>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<char, true>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, false>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct<wchar_t, true>;
|
||||
|
||||
template class moneypunct_byname<char, false>;
|
||||
template class moneypunct_byname<char, true>;
|
||||
template class moneypunct_byname<wchar_t, false>;
|
||||
template class moneypunct_byname<wchar_t, true>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, false>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<char, true>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, false>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname<wchar_t, true>;
|
||||
|
||||
template class money_get<char>;
|
||||
template class money_get<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get<wchar_t>;
|
||||
|
||||
template class __money_get<char>;
|
||||
template class __money_get<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get<wchar_t>;
|
||||
|
||||
template class money_put<char>;
|
||||
template class money_put<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put<wchar_t>;
|
||||
|
||||
template class __money_put<char>;
|
||||
template class __money_put<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put<wchar_t>;
|
||||
|
||||
template class messages<char>;
|
||||
template class messages<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages<wchar_t>;
|
||||
|
||||
template class messages_byname<char>;
|
||||
template class messages_byname<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname<wchar_t>;
|
||||
|
||||
template class codecvt_byname<char, char, mbstate_t>;
|
||||
template class codecvt_byname<wchar_t, char, mbstate_t>;
|
||||
template class codecvt_byname<char16_t, char, mbstate_t>;
|
||||
template class codecvt_byname<char32_t, char, mbstate_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char, char, mbstate_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<wchar_t, char, mbstate_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char16_t, char, mbstate_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname<char32_t, char, mbstate_t>;
|
||||
|
||||
template class __vector_base_common<true>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template class __basic_string_common<true>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
|
||||
|
||||
template class basic_string<char>;
|
||||
template class basic_string<wchar_t>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
|
||||
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>;
|
||||
|
||||
template
|
||||
string
|
||||
|
|
Loading…
Reference in New Issue