Skip to content

Commit 49e2967

Browse files
committedSep 15, 2016
[libc++] Fix and document visibility attributes for Clang, GCC and Windows.
Summary: This patch fixes a number of problems with the visibility macros across GCC (on Unix) and Windows (DLL import/export semantics). All of the visibility macros are now documented under `DesignDocs/VisibilityMacros.rst`. Now I'll no longer forget the subtleties of each! This patch adds two new visibility macros: * `_LIBCPP_ENUM_VIS` for controlling the typeinfo of enum types. Only Clang supports this. * `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` for redefining visibility on explicit instantiation declarations. Clang and Windows require this. After applying this patch GCC only emits one -Wattribute warning opposed to 30+. Reviewers: mclow.lists, EricWF Subscribers: beanz, mgorny, cfe-commits Differential Revision: https://reviews.llvm.org/D24602 llvm-svn: 281673
1 parent 8da42cc commit 49e2967

File tree

13 files changed

+229
-149
lines changed

13 files changed

+229
-149
lines changed
 

Diff for: ‎libcxx/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,6 @@ if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
342342
-Wno-covered-switch-default)
343343
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
344344
add_compile_flags_if_supported(
345-
-Wno-attributes # FIXME: Fix -Wattribute warnings.
346345
-Wno-literal-suffix
347346
-Wno-c++14-compat)
348347
endif()

Diff for: ‎libcxx/docs/DesignDocs/VisibilityMacros.rst

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
========================
2+
Symbol Visibility Macros
3+
========================
4+
5+
.. contents::
6+
:local:
7+
8+
Overview
9+
========
10+
11+
Libc++ uses various "visibility" macros in order to provide a stable ABI in
12+
both the library and the headers. These macros work by changing the
13+
visibility and inlining characteristics of the symbols they are applied to.
14+
15+
Visibility Macros
16+
=================
17+
18+
**_LIBCPP_HIDDEN**
19+
Mark a symbol as hidden so it will not be exported from shared libraries.
20+
21+
**_LIBCPP_FUNC_VIS**
22+
Mark a symbol as being exported by the libc++ library. This attribute must
23+
be applied to the declaration of all functions exported by the libc++ dylib.
24+
25+
**_LIBCPP_INLINE_VISIBILITY**
26+
Mark a function as hidden and force inlining whenever possible.
27+
28+
**_LIBCPP_ALWAYS_INLINE**
29+
A synonym for `_LIBCPP_INLINE_VISIBILITY`
30+
31+
**_LIBCPP_TYPE_VIS**
32+
Mark a type's typeinfo and vtable as having default visibility.
33+
`_LIBCPP_TYPE_VIS`. This macro has no effect on the visibility of the
34+
type's member functions. This attribute cannot be used on class templates.
35+
36+
**GCC Behavior**: GCC does not support Clang's `type_visibility(...)`
37+
attribute. With GCC the `visibility(...)` attribute is used and member
38+
functions are affected.
39+
40+
**_LIBCPP_TYPE_VIS_ONLY**
41+
The same as `_LIBCPP_TYPE_VIS` except that it may be applied to templates.
42+
43+
**Windows Behavior**: DLLs do not support dllimport/export on class templates.
44+
The macro has an empty definition on this platform.
45+
46+
Note: This macro should be renamed `_LIBCPP_TEMPLATE_TYPE_VIS`.
47+
48+
**_LIBCPP_ENUM_VIS**
49+
Mark the typeinfo of an enum as having default visibility. This attribute
50+
should be applied to all enum declarations.
51+
52+
**Windows Behavior**: DLLs do not support importing or exporting enumeration
53+
typeinfo. The macro has an empty definition on this platform.
54+
55+
**GCC Behavior**: GCC un-hides the typeinfo for enumerations by default, even
56+
if `-fvisibility=hidden` is specified. Additionally applying a visibility
57+
attribute to an enum class results in a warning. The macro has an empty
58+
definition with GCC.
59+
60+
**_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS**
61+
Mark the member functions, typeinfo, and vtable of the type named in
62+
a `_LIBCPP_EXTERN_TEMPLATE` declaration as being exported by the libc++ library.
63+
This attribute must be specified on all extern class template declarations.
64+
65+
This macro is used to override the `_LIBCPP_TYPE_VIS_ONLY` attribute
66+
specified on the primary template and to export the member functions produced
67+
by the explicit instantiation in the dylib.
68+
69+
**GCC Behavior**: GCC ignores visibility attributes applied the type in
70+
extern template declarations and applying an attribute results in a warning.
71+
However since `_LIBCPP_TYPE_VIS_ONLY` is the same as `_LIBCPP_TYPE_VIS` the
72+
visibility is already correct. The macro has an empty definition with GCC.
73+
74+
**_LIBCPP_EXCEPTION_ABI**
75+
Mark the member functions, typeinfo, and vtable of the type as being exported
76+
by the libc++ library. This macro must be applied to all *exception types*.
77+
Exception types must be defined directly in namespace `std` and not the
78+
versioning namespace.
79+
80+
Links
81+
=====
82+
83+
* `[cfe-dev] Visibility in libc++ - 1 <http://lists.llvm.org/pipermail/cfe-dev/2013-July/030610.html>`_
84+
* `[cfe-dev] Visibility in libc++ - 2 <http://lists.llvm.org/pipermail/cfe-dev/2013-August/031195.html>`_
85+
* `[libcxx] Visibility fixes for Windows <http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20130805/085461.html>`_

Diff for: ‎libcxx/docs/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ Design Documents
129129

130130
DesignDocs/CapturingConfigInfo
131131
DesignDocs/ABIVersioning
132+
DesignDocs/VisibilityMacros
132133

133134

134135
* `<atomic> design <http://libcxx.llvm.org/atomic_design.html>`_

Diff for: ‎libcxx/include/__config

+81-87
Original file line numberDiff line numberDiff line change
@@ -202,90 +202,6 @@
202202
#define _LIBCPP_NO_CFI
203203
#endif
204204

205-
#ifdef _WIN32
206-
207-
// only really useful for a DLL
208-
#ifdef _LIBCPP_DLL // this should be a compiler builtin define ideally...
209-
# ifdef cxx_EXPORTS
210-
# define _LIBCPP_HIDDEN
211-
# define _LIBCPP_FUNC_VIS __declspec(dllexport)
212-
# define _LIBCPP_TYPE_VIS __declspec(dllexport)
213-
# else
214-
# define _LIBCPP_HIDDEN
215-
# define _LIBCPP_FUNC_VIS __declspec(dllimport)
216-
# define _LIBCPP_TYPE_VIS __declspec(dllimport)
217-
# endif
218-
#else
219-
# define _LIBCPP_HIDDEN
220-
# define _LIBCPP_FUNC_VIS
221-
# define _LIBCPP_TYPE_VIS
222-
#endif
223-
224-
#define _LIBCPP_TYPE_VIS_ONLY
225-
#define _LIBCPP_FUNC_VIS_ONLY
226-
227-
#ifndef _LIBCPP_INLINE_VISIBILITY
228-
# ifdef _LIBCPP_MSVC
229-
# define _LIBCPP_INLINE_VISIBILITY __forceinline
230-
# else // MinGW GCC and Clang
231-
# define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__always_inline__))
232-
# endif
233-
#endif
234-
235-
#ifndef _LIBCPP_EXCEPTION_ABI
236-
#define _LIBCPP_EXCEPTION_ABI _LIBCPP_TYPE_VIS
237-
#endif
238-
239-
#ifndef _LIBCPP_ALWAYS_INLINE
240-
# ifdef _LIBCPP_MSVC
241-
# define _LIBCPP_ALWAYS_INLINE __forceinline
242-
# endif
243-
#endif
244-
245-
#endif // _WIN32
246-
247-
#ifndef _LIBCPP_HIDDEN
248-
#define _LIBCPP_HIDDEN __attribute__ ((__visibility__("hidden")))
249-
#endif
250-
251-
#ifndef _LIBCPP_FUNC_VIS
252-
#define _LIBCPP_FUNC_VIS __attribute__ ((__visibility__("default")))
253-
#endif
254-
255-
#ifndef _LIBCPP_TYPE_VIS
256-
# if __has_attribute(__type_visibility__)
257-
# define _LIBCPP_TYPE_VIS __attribute__ ((__type_visibility__("default")))
258-
# else
259-
# define _LIBCPP_TYPE_VIS __attribute__ ((__visibility__("default")))
260-
# endif
261-
#endif
262-
263-
#ifndef _LIBCPP_PREFERRED_OVERLOAD
264-
# if __has_attribute(__enable_if__)
265-
# define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, "")))
266-
# endif
267-
#endif
268-
269-
#ifndef _LIBCPP_TYPE_VIS_ONLY
270-
# define _LIBCPP_TYPE_VIS_ONLY _LIBCPP_TYPE_VIS
271-
#endif
272-
273-
#ifndef _LIBCPP_FUNC_VIS_ONLY
274-
# define _LIBCPP_FUNC_VIS_ONLY _LIBCPP_FUNC_VIS
275-
#endif
276-
277-
#ifndef _LIBCPP_INLINE_VISIBILITY
278-
#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
279-
#endif
280-
281-
#ifndef _LIBCPP_EXCEPTION_ABI
282-
#define _LIBCPP_EXCEPTION_ABI __attribute__ ((__visibility__("default")))
283-
#endif
284-
285-
#ifndef _LIBCPP_ALWAYS_INLINE
286-
#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__))
287-
#endif
288-
289205
#if defined(__clang__)
290206

291207
// _LIBCPP_ALTERNATE_STRING_LAYOUT is an old name for
@@ -581,8 +497,6 @@ using namespace _LIBCPP_NAMESPACE __attribute__((__strong__));
581497
#define _ALIGNAS(x) __declspec(align(x))
582498
#define _LIBCPP_HAS_NO_VARIADICS
583499

584-
585-
586500
#define _LIBCPP_BEGIN_NAMESPACE_STD namespace std {
587501
#define _LIBCPP_END_NAMESPACE_STD }
588502
#define _VSTD std
@@ -628,6 +542,86 @@ namespace std {
628542

629543
#endif // __clang__ || __GNUC__ || _MSC_VER || __IBMCPP__
630544

545+
546+
#ifdef _WIN32
547+
// only really useful for a DLL. _LIBCPP_DLL should be a compiler builtin define ideally...
548+
#if defined(_LIBCPP_DLL) && defined(cxx_EXPORTS)
549+
# define _LIBCPP_DLL_VIS __declspec(dllexport)
550+
#elif defined(_LIBCPP_DLL)
551+
# define _LIBCPP_DLL_VIS __declspec(dllimport)
552+
#else
553+
# define _LIBCPP_DLL_VIS
554+
#endif
555+
#define _LIBCPP_TYPE_VIS _LIBCPP_DLL_VIS
556+
#define _LIBCPP_FUNC_VIS _LIBCPP_DLL_VIS
557+
#define _LIBCPP_EXCEPTION_ABI _LIBCPP_DLL_VIS
558+
#define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS
559+
#define _LIBCPP_HIDDEN
560+
#define _LIBCPP_TYPE_VIS_ONLY
561+
#define _LIBCPP_FUNC_VIS_ONLY
562+
#define _LIBCPP_ENUM_VIS
563+
#define _LIBCPP_INLINE_VISIBILITY __forceinline
564+
#define _LIBCPP_ALWAYS_INLINE __forceinline
565+
#endif // _WIN32
566+
567+
#ifndef _LIBCPP_HIDDEN
568+
#define _LIBCPP_HIDDEN __attribute__ ((__visibility__("hidden")))
569+
#endif
570+
571+
#ifndef _LIBCPP_FUNC_VIS
572+
#define _LIBCPP_FUNC_VIS __attribute__ ((__visibility__("default")))
573+
#endif
574+
575+
#ifndef _LIBCPP_TYPE_VIS
576+
# if __has_attribute(__type_visibility__)
577+
# define _LIBCPP_TYPE_VIS __attribute__ ((__type_visibility__("default")))
578+
# else
579+
# define _LIBCPP_TYPE_VIS __attribute__ ((__visibility__("default")))
580+
# endif
581+
#endif
582+
583+
#ifndef _LIBCPP_TYPE_VIS_ONLY
584+
# define _LIBCPP_TYPE_VIS_ONLY _LIBCPP_TYPE_VIS
585+
#endif
586+
587+
#ifndef _LIBCPP_FUNC_VIS_ONLY
588+
# define _LIBCPP_FUNC_VIS_ONLY _LIBCPP_FUNC_VIS
589+
#endif
590+
591+
#ifndef _LIBCPP_EXCEPTION_ABI
592+
#define _LIBCPP_EXCEPTION_ABI __attribute__ ((__visibility__("default")))
593+
#endif
594+
595+
#ifndef _LIBCPP_ENUM_VIS
596+
# if __has_attribute(__type_visibility__)
597+
# define _LIBCPP_ENUM_VIS __attribute__ ((__type_visibility__("default")))
598+
# else
599+
# define _LIBCPP_ENUM_VIS
600+
# endif
601+
#endif
602+
603+
#ifndef _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
604+
# if __has_attribute(__type_visibility__)
605+
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __attribute__ ((__visibility__("default")))
606+
# else
607+
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
608+
# endif
609+
#endif
610+
611+
#ifndef _LIBCPP_INLINE_VISIBILITY
612+
#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
613+
#endif
614+
615+
#ifndef _LIBCPP_ALWAYS_INLINE
616+
#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__))
617+
#endif
618+
619+
#ifndef _LIBCPP_PREFERRED_OVERLOAD
620+
# if __has_attribute(__enable_if__)
621+
# define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, "")))
622+
# endif
623+
#endif
624+
631625
#ifndef _LIBCPP_HAS_NO_NOEXCEPT
632626
# define _NOEXCEPT noexcept
633627
# define _NOEXCEPT_(x) noexcept(x)
@@ -716,7 +710,7 @@ template <unsigned> struct __static_assert_check {};
716710
_LIBCPP_ALWAYS_INLINE operator int() const {return __v_;} \
717711
};
718712
#else // _LIBCPP_HAS_NO_STRONG_ENUMS
719-
#define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_TYPE_VIS_ONLY x
713+
#define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_ENUM_VIS x
720714
#define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x)
721715
#endif // _LIBCPP_HAS_NO_STRONG_ENUMS
722716

Diff for: ‎libcxx/include/__locale

+6-6
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,8 @@ collate<_CharT>::do_hash(const char_type* __lo, const char_type* __hi) const
269269
return static_cast<long>(__h);
270270
}
271271

272-
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS collate<char>)
273-
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS collate<wchar_t>)
272+
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<char>)
273+
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS collate<wchar_t>)
274274

275275
// template <class CharT> class collate_byname;
276276

@@ -1178,10 +1178,10 @@ codecvt_byname<_InternT, _ExternT, _StateT>::~codecvt_byname()
11781178
{
11791179
}
11801180

1181-
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname<char, char, mbstate_t>)
1182-
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname<wchar_t, char, mbstate_t>)
1183-
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname<char16_t, char, mbstate_t>)
1184-
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_TYPE_VIS codecvt_byname<char32_t, char, mbstate_t>)
1181+
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char, char, mbstate_t>)
1182+
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<wchar_t, char, mbstate_t>)
1183+
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char16_t, char, mbstate_t>)
1184+
_LIBCPP_EXTERN_TEMPLATE2(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS codecvt_byname<char32_t, char, mbstate_t>)
11851185

11861186
_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void __throw_runtime_error(const char*);
11871187

Diff for: ‎libcxx/include/__string

+2-1
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,8 @@ __str_find_last_not_of(const _CharT *__p, _SizeT __sz,
701701
}
702702

703703
template<class _Ptr>
704-
size_t _LIBCPP_INLINE_VISIBILITY __do_string_hash(_Ptr __p, _Ptr __e)
704+
inline _LIBCPP_INLINE_VISIBILITY
705+
size_t __do_string_hash(_Ptr __p, _Ptr __e)
705706
{
706707
typedef typename iterator_traits<_Ptr>::value_type value_type;
707708
return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));

Diff for: ‎libcxx/include/experimental/filesystem

+4-4
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ struct _LIBCPP_TYPE_VIS space_info
249249
uintmax_t available;
250250
};
251251

252-
enum class _LIBCPP_TYPE_VIS file_type : signed char
252+
enum class _LIBCPP_ENUM_VIS file_type : signed char
253253
{
254254
none = 0,
255255
not_found = -1,
@@ -263,7 +263,7 @@ enum class _LIBCPP_TYPE_VIS file_type : signed char
263263
unknown = 8
264264
};
265265

266-
enum class _LIBCPP_TYPE_VIS perms : unsigned
266+
enum class _LIBCPP_ENUM_VIS perms : unsigned
267267
{
268268
none = 0,
269269

@@ -323,7 +323,7 @@ _LIBCPP_INLINE_VISIBILITY
323323
inline perms& operator^=(perms& _LHS, perms _RHS)
324324
{ return _LHS = _LHS ^ _RHS; }
325325

326-
enum class _LIBCPP_TYPE_VIS copy_options : unsigned short
326+
enum class _LIBCPP_ENUM_VIS copy_options : unsigned short
327327
{
328328
none = 0,
329329
skip_existing = 1,
@@ -367,7 +367,7 @@ inline copy_options& operator^=(copy_options& _LHS, copy_options _RHS)
367367
{ return _LHS = _LHS ^ _RHS; }
368368

369369

370-
enum class directory_options : unsigned char
370+
enum class _LIBCPP_ENUM_VIS directory_options : unsigned char
371371
{
372372
none = 0,
373373
follow_directory_symlink = 1,

Diff for: ‎libcxx/include/istream

+3-3
Original file line numberDiff line numberDiff line change
@@ -1741,9 +1741,9 @@ operator>>(basic_istream<_CharT, _Traits>& __is, bitset<_Size>& __x)
17411741
return __is;
17421742
}
17431743

1744-
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS basic_istream<char>)
1745-
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS basic_istream<wchar_t>)
1746-
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_TYPE_VIS basic_iostream<char>)
1744+
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_istream<char>)
1745+
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_istream<wchar_t>)
1746+
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_iostream<char>)
17471747

17481748
_LIBCPP_END_NAMESPACE_STD
17491749

0 commit comments

Comments
 (0)
Please sign in to comment.