Skip to content

Commit 9349b45

Browse files
committed
[libc++] Introduce a new attribute keyword for Clang improves compatibility with Mingw-GCC
This is affected to only Clang for MinGW target. In MinGW environment, Clang handles dllexport attribute of internal class that defined in class template in different way from GCC. This incompatibility should be fixed but breaks ABI of libc++, so introduce a new keyword to keep ABI in MinGW environment with old and patched Clang and to ensure nothing affects to other environment/platforms. The new attribute keyword _LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS does nothing in almost all situations except if included from client (not in building libc++ itself) by clang (not by GCC or others). If clang does include libc++, the keyword will be expanded to __attribute__((__exclude_from_explicit_instantiation__)), results attached class will be away from explicit instantiation declaration so will be instanciated implicitly as formar Clang does. Thus, it will no-op for old Clang that has incompatibility with MinGW-GCC or emulate old behavior for patched Clang. This attribute is attached only for std::basic_ostream::sentry and std::basic_istream::sentry. Other entities won't be affected by patching Clang so doesn't need to be annotate. Notably, at a time to introduce a new class as a non-template inner type of a class template, that class also needs to be attached _LIBCPP_INNER_CLASS_ININ_TEMPLATE_VIS.
1 parent 37af003 commit 9349b45

File tree

4 files changed

+17
-2
lines changed

4 files changed

+17
-2
lines changed

libcxx/docs/DesignDocs/VisibilityMacros.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,13 @@ Visibility Macros
9393
the extern template declaration) as exported on Windows, as discussed above.
9494
On all other platforms, this macro has an empty definition.
9595

96+
**_LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS**
97+
To let dll-importing and dll-exporting consitent on windows-gnu environment,
98+
this annotation must be attached to a non-template class that isn't marked
99+
as `dllexport` defined in a class template. Currentry here are ostream::sentry
100+
and istream::sentry only but if a time to such a new class be introduced,
101+
the class has to be attached this annotation.
102+
96103
Links
97104
=====
98105

libcxx/include/__config

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,11 @@ typedef __char32_t char32_t;
365365
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
366366
# define _LIBCPP_OVERRIDABLE_FUNC_VIS
367367
# define _LIBCPP_EXPORTED_FROM_ABI
368+
# if defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) || !__has_attribute(exclude_from_explicit_instantiation)
369+
# define _LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS
370+
# else
371+
# define _LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS __attribute__((__exclude_from_explicit_instantiation__))
372+
# endif
368373
# elif defined(_LIBCPP_BUILDING_LIBRARY)
369374
# if defined(__MINGW32__)
370375
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __declspec(dllexport)
@@ -375,11 +380,13 @@ typedef __char32_t char32_t;
375380
# endif
376381
# define _LIBCPP_OVERRIDABLE_FUNC_VIS __declspec(dllexport)
377382
# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllexport)
383+
# define _LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS
378384
# else
379385
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __declspec(dllimport)
380386
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
381387
# define _LIBCPP_OVERRIDABLE_FUNC_VIS
382388
# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport)
389+
# define _LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS
383390
# endif
384391

385392
# define _LIBCPP_HIDDEN
@@ -399,6 +406,7 @@ typedef __char32_t char32_t;
399406
# define _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_VISIBILITY("default")
400407
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_VISIBILITY("default")
401408
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
409+
# define _LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS
402410

403411
// TODO: Make this a proper customization point or remove the option to override it.
404412
# ifndef _LIBCPP_OVERRIDABLE_FUNC_VIS

libcxx/include/__ostream/basic_ostream.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ class basic_ostream : virtual public basic_ios<_CharT, _Traits> {
7171

7272
public:
7373
// 27.7.2.4 Prefix/suffix:
74-
class sentry;
74+
class _LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS sentry;
7575

7676
// 27.7.2.6 Formatted output:
7777
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_ostream& operator<<(basic_ostream& (*__pf)(basic_ostream&)) {

libcxx/include/istream

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ public:
228228
basic_istream& operator=(const basic_istream& __rhs) = delete;
229229

230230
// 27.7.1.1.3 Prefix/suffix:
231-
class sentry;
231+
class _LIBCPP_INNER_CLASS_IN_TEMPLATE_VIS sentry;
232232

233233
// 27.7.1.2 Formatted input:
234234
inline _LIBCPP_HIDE_FROM_ABI_AFTER_V1 basic_istream& operator>>(basic_istream& (*__pf)(basic_istream&)) {

0 commit comments

Comments
 (0)