Index: libcxx/trunk/docs/DesignDocs/VisibilityMacros.rst =================================================================== --- libcxx/trunk/docs/DesignDocs/VisibilityMacros.rst +++ libcxx/trunk/docs/DesignDocs/VisibilityMacros.rst @@ -71,6 +71,26 @@ 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 Index: libcxx/trunk/include/__config =================================================================== --- libcxx/trunk/include/__config +++ libcxx/trunk/include/__config @@ -551,15 +551,20 @@ // 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 @@ # 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 Index: libcxx/trunk/src/ios.cpp =================================================================== --- libcxx/trunk/src/ios.cpp +++ libcxx/trunk/src/ios.cpp @@ -25,19 +25,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template class basic_ios; -template class basic_ios; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ios; -template class basic_streambuf; -template class basic_streambuf; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_streambuf; -template class basic_istream; -template class basic_istream; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_istream; -template class basic_ostream; -template class basic_ostream; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_ostream; -template class basic_iostream; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_iostream; class _LIBCPP_HIDDEN __iostream_category : public __do_message Index: libcxx/trunk/src/locale.cpp =================================================================== --- libcxx/trunk/src/locale.cpp +++ libcxx/trunk/src/locale.cpp @@ -6031,66 +6031,66 @@ #endif } -template class collate; -template class collate; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate; -template class num_get; -template class num_get; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_get; -template struct __num_get; -template struct __num_get; +template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get; +template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_get; -template class num_put; -template class num_put; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS num_put; -template struct __num_put; -template struct __num_put; +template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put; +template struct _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __num_put; -template class time_get; -template class time_get; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get; -template class time_get_byname; -template class time_get_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_get_byname; -template class time_put; -template class time_put; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put; -template class time_put_byname; -template class time_put_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS time_put_byname; -template class moneypunct; -template class moneypunct; -template class moneypunct; -template class moneypunct; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct; -template class moneypunct_byname; -template class moneypunct_byname; -template class moneypunct_byname; -template class moneypunct_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS moneypunct_byname; -template class money_get; -template class money_get; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_get; -template class __money_get; -template class __money_get; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_get; -template class money_put; -template class money_put; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS money_put; -template class __money_put; -template class __money_put; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __money_put; -template class messages; -template class messages; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages; -template class messages_byname; -template class messages_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS messages_byname; -template class codecvt_byname; -template class codecvt_byname; -template class codecvt_byname; -template class codecvt_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS codecvt_byname; -template class __vector_base_common; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common; _LIBCPP_END_NAMESPACE_STD Index: libcxx/trunk/src/string.cpp =================================================================== --- libcxx/trunk/src/string.cpp +++ libcxx/trunk/src/string.cpp @@ -20,10 +20,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template class __basic_string_common; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common; -template class basic_string; -template class basic_string; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string; +template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string; template string