diff options
author | Shoaib Meenai <smeenai@fb.com> | 2016-09-19 18:29:07 +0000 |
---|---|---|
committer | Shoaib Meenai <smeenai@fb.com> | 2016-09-19 18:29:07 +0000 |
commit | 190994e435884229ca058362e9974a5de4c41947 (patch) | |
tree | 9b04d11dc8bc301699d23abe99ebd450a513712c /libcxx | |
parent | 1197a1612d89c019ef67e43e15f45c7615b13b4d (diff) | |
download | bcm5719-llvm-190994e435884229ca058362e9974a5de4c41947.tar.gz bcm5719-llvm-190994e435884229ca058362e9974a5de4c41947.zip |
[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
Diffstat (limited to 'libcxx')
-rw-r--r-- | libcxx/docs/DesignDocs/VisibilityMacros.rst | 20 | ||||
-rw-r--r-- | libcxx/include/__config | 11 | ||||
-rw-r--r-- | libcxx/src/ios.cpp | 18 | ||||
-rw-r--r-- | libcxx/src/locale.cpp | 86 | ||||
-rw-r--r-- | libcxx/src/string.cpp | 6 |
5 files changed, 85 insertions, 56 deletions
diff --git a/libcxx/docs/DesignDocs/VisibilityMacros.rst b/libcxx/docs/DesignDocs/VisibilityMacros.rst index d6fdb287fdd..f7d1400341f 100644 --- a/libcxx/docs/DesignDocs/VisibilityMacros.rst +++ b/libcxx/docs/DesignDocs/VisibilityMacros.rst @@ -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 diff --git a/libcxx/include/__config b/libcxx/include/__config index 15e02d68325..86f945dc96b 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -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 diff --git a/libcxx/src/ios.cpp b/libcxx/src/ios.cpp index 23e3ee0ca04..7c76ca258b2 100644 --- a/libcxx/src/ios.cpp +++ b/libcxx/src/ios.cpp @@ -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 diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp index 12f05413c60..88c37312f01 100644 --- a/libcxx/src/locale.cpp +++ b/libcxx/src/locale.cpp @@ -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 diff --git a/libcxx/src/string.cpp b/libcxx/src/string.cpp index 76d5caca549..cd644330b3a 100644 --- a/libcxx/src/string.cpp +++ b/libcxx/src/string.cpp @@ -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 |