[libcxx] r281925 - [libc++] Fix extern template visibility for Windows

Shoaib Meenai via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 19 11:29:07 PDT 2016


Author: smeenai
Date: Mon Sep 19 13:29:07 2016
New Revision: 281925

URL: http://llvm.org/viewvc/llvm-project?rev=281925&view=rev
Log:
[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

Modified:
    libcxx/trunk/docs/DesignDocs/VisibilityMacros.rst
    libcxx/trunk/include/__config
    libcxx/trunk/src/ios.cpp
    libcxx/trunk/src/locale.cpp
    libcxx/trunk/src/string.cpp

Modified: libcxx/trunk/docs/DesignDocs/VisibilityMacros.rst
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/docs/DesignDocs/VisibilityMacros.rst?rev=281925&r1=281924&r2=281925&view=diff
==============================================================================
--- libcxx/trunk/docs/DesignDocs/VisibilityMacros.rst (original)
+++ libcxx/trunk/docs/DesignDocs/VisibilityMacros.rst Mon Sep 19 13:29:07 2016
@@ -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

Modified: libcxx/trunk/include/__config
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=281925&r1=281924&r2=281925&view=diff
==============================================================================
--- libcxx/trunk/include/__config (original)
+++ libcxx/trunk/include/__config Mon Sep 19 13:29:07 2016
@@ -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

Modified: libcxx/trunk/src/ios.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/ios.cpp?rev=281925&r1=281924&r2=281925&view=diff
==============================================================================
--- libcxx/trunk/src/ios.cpp (original)
+++ libcxx/trunk/src/ios.cpp Mon Sep 19 13:29:07 2016
@@ -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

Modified: libcxx/trunk/src/locale.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/locale.cpp?rev=281925&r1=281924&r2=281925&view=diff
==============================================================================
--- libcxx/trunk/src/locale.cpp (original)
+++ libcxx/trunk/src/locale.cpp Mon Sep 19 13:29:07 2016
@@ -6031,66 +6031,66 @@ void __throw_runtime_error(const char* m
 #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

Modified: libcxx/trunk/src/string.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/string.cpp?rev=281925&r1=281924&r2=281925&view=diff
==============================================================================
--- libcxx/trunk/src/string.cpp (original)
+++ libcxx/trunk/src/string.cpp Mon Sep 19 13:29:07 2016
@@ -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




More information about the cfe-commits mailing list