2016-09-16 06:27:07 +08:00
|
|
|
========================
|
|
|
|
Symbol Visibility Macros
|
|
|
|
========================
|
|
|
|
|
|
|
|
.. contents::
|
|
|
|
:local:
|
|
|
|
|
|
|
|
Overview
|
|
|
|
========
|
|
|
|
|
|
|
|
Libc++ uses various "visibility" macros in order to provide a stable ABI in
|
|
|
|
both the library and the headers. These macros work by changing the
|
|
|
|
visibility and inlining characteristics of the symbols they are applied to.
|
|
|
|
|
|
|
|
Visibility Macros
|
|
|
|
=================
|
|
|
|
|
|
|
|
**_LIBCPP_HIDDEN**
|
|
|
|
Mark a symbol as hidden so it will not be exported from shared libraries.
|
|
|
|
|
|
|
|
**_LIBCPP_FUNC_VIS**
|
|
|
|
Mark a symbol as being exported by the libc++ library. This attribute must
|
|
|
|
be applied to the declaration of all functions exported by the libc++ dylib.
|
|
|
|
|
|
|
|
**_LIBCPP_INLINE_VISIBILITY**
|
|
|
|
Mark a function as hidden and force inlining whenever possible.
|
|
|
|
|
|
|
|
**_LIBCPP_ALWAYS_INLINE**
|
|
|
|
A synonym for `_LIBCPP_INLINE_VISIBILITY`
|
|
|
|
|
|
|
|
**_LIBCPP_TYPE_VIS**
|
|
|
|
Mark a type's typeinfo and vtable as having default visibility.
|
|
|
|
`_LIBCPP_TYPE_VIS`. This macro has no effect on the visibility of the
|
|
|
|
type's member functions. This attribute cannot be used on class templates.
|
|
|
|
|
|
|
|
**GCC Behavior**: GCC does not support Clang's `type_visibility(...)`
|
|
|
|
attribute. With GCC the `visibility(...)` attribute is used and member
|
|
|
|
functions are affected.
|
|
|
|
|
|
|
|
**_LIBCPP_TYPE_VIS_ONLY**
|
|
|
|
The same as `_LIBCPP_TYPE_VIS` except that it may be applied to templates.
|
|
|
|
|
|
|
|
**Windows Behavior**: DLLs do not support dllimport/export on class templates.
|
|
|
|
The macro has an empty definition on this platform.
|
|
|
|
|
|
|
|
Note: This macro should be renamed `_LIBCPP_TEMPLATE_TYPE_VIS`.
|
|
|
|
|
|
|
|
**_LIBCPP_ENUM_VIS**
|
|
|
|
Mark the typeinfo of an enum as having default visibility. This attribute
|
|
|
|
should be applied to all enum declarations.
|
|
|
|
|
|
|
|
**Windows Behavior**: DLLs do not support importing or exporting enumeration
|
|
|
|
typeinfo. The macro has an empty definition on this platform.
|
|
|
|
|
|
|
|
**GCC Behavior**: GCC un-hides the typeinfo for enumerations by default, even
|
|
|
|
if `-fvisibility=hidden` is specified. Additionally applying a visibility
|
|
|
|
attribute to an enum class results in a warning. The macro has an empty
|
|
|
|
definition with GCC.
|
|
|
|
|
|
|
|
**_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS**
|
|
|
|
Mark the member functions, typeinfo, and vtable of the type named in
|
|
|
|
a `_LIBCPP_EXTERN_TEMPLATE` declaration as being exported by the libc++ library.
|
|
|
|
This attribute must be specified on all extern class template declarations.
|
|
|
|
|
|
|
|
This macro is used to override the `_LIBCPP_TYPE_VIS_ONLY` attribute
|
|
|
|
specified on the primary template and to export the member functions produced
|
|
|
|
by the explicit instantiation in the dylib.
|
|
|
|
|
|
|
|
**GCC Behavior**: GCC ignores visibility attributes applied the type in
|
|
|
|
extern template declarations and applying an attribute results in a warning.
|
|
|
|
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.
|
|
|
|
|
2016-09-20 02:29:07 +08:00
|
|
|
**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.
|
|
|
|
|
[libc++] Add _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY to support GCC ABI compatibility
Summary:
GCC and Clang handle visibility attributes on the out-of-line definition of externally instantiated templates differently. For example in the reproducer below Clang will emit both 'foo' and 'bar' with default visibility while GCC only emits a non-hidden 'foo'.
```
// RUN: g++ -std=c++11 -shared -O3 test.cpp && sym_extract.py a.out
// RUN: clang++ -std=c++11 -shared -O3 test.cpp && sym_extract.py a.out
#define INLINE_VISIBILITY __attribute__((visibility("hidden"), always_inline))
template <class T>
struct Foo {
void foo();
void bar();
};
template <class T>
void Foo<T>::foo() {}
template <class T>
inline INLINE_VISIBILITY
void Foo<T>::bar() {}
template struct Foo<int>;
```
This difference creates ABI incompatibilities between Clang and GCC built dylibs. Specifically GCC built dylibs lack definitions for various member functions of `basic_string`, `basic_istream`, `basic_ostream`, `basic_iostream`, and `basic_streambuf` (All of these types are externally instantiated).
Surprisingly these missing symbols don't cause many problems because the functions are marked `always_inline` therefore the dylib definition is rarely needed. However when an out-of-line definition is required then GCC built dylibs will fail to link. For example [GCC built dylibs cannot build Clang](http://stackoverflow.com/questions/39454262/clang-build-errors).
This patch works around this issue by adding `_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY` which is used to mark externally instantiated member functions as always inline. When building the library `_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY` sets the symbol's visibility to "default" instead of "hidden", otherwise it acts exactly the same as `_LIBCPP_INLINE_VISIBILITY`.
After applying this patch GCC dylibs now contain:
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7sungetcEv`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5gbumpEi`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7sungetcEv`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9sputbackcEc`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERNS_15basic_streambufIwS2_EE`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_9basic_iosIwS2_EES6_E`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4setpEPcS4_`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6snextcEv`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE4swapERS3_`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE4swapERS3_`
* `_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_8ios_baseES5_E`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE9pubsetbufEPcl`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE10pubseekoffExNS_8ios_base7seekdirEj`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_9basic_iosIwS2_EES6_E`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5pbumpEi`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5seekpENS_4fposI11__mbstate_tEE`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE7getlineEPcl`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sgetcEv`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERNS_15basic_streambufIcS2_EE`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_8ios_baseES5_E`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8in_availEv`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRNS_8ios_baseES5_E`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE6sbumpcEv`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRNS_9basic_iosIcS2_EES6_E`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getERc`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6snextcEv`
* `_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEmw`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE7getlineEPwl`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5tellpEv`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getERw`
* `_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE7pubsyncEv`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEE3getEPcl`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRNS_9basic_iosIcS2_EES6_E`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE7pubsyncEv`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputcEc`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5seekpExNS_8ios_base7seekdirE`
* `_ZNKSt3__115basic_streambufIcNS_11char_traitsIcEEE6getlocEv`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5gbumpEi`
* `_ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEE4swapERS3_`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5seekpENS_4fposI11__mbstate_tEE`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE5tellpEv`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRS3_S4_E`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEE3getEPwl`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEPFRS3_S4_E`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE4setgEPcS4_S4_`
* `_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwmm`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4setgEPwS4_S4_`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEEC1EPNS_15basic_streambufIwS2_EE`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE8pubimbueERKNS_6localeE`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE4swapERS3_`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEEC2EPNS_15basic_streambufIwS2_EE`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE10pubseekposENS_4fposI11__mbstate_tEEj`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5pbumpEi`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sgetcEv`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEE4swapERS3_`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE10pubseekposENS_4fposI11__mbstate_tEEj`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sputnEPKcl`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5seekpExNS_8ios_base7seekdirE`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sgetnEPwl`
* `_ZNSt3__113basic_ostreamIwNS_11char_traitsIwEEElsEPFRNS_8ios_baseES5_E`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE4setpEPwS4_`
* `_ZNSt3__115basic_streambufIcNS_11char_traitsIcEEE5sgetnEPcl`
* `_ZNKSt3__115basic_streambufIwNS_11char_traitsIwEEE6getlocEv`
* `_ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8pubimbueERKNS_6localeE`
* `_ZNSt3__114basic_iostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE8in_availEv`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE`
* `_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcmm`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE6sbumpcEv`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE10pubseekoffExNS_8ios_base7seekdirEj`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEEC2EPNS_15basic_streambufIcS2_EE`
* `_ZNSt3__113basic_istreamIwNS_11char_traitsIwEEErsEPFRS3_S4_E`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9sputbackcEw`
* `_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE6__initEPKwm`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sputnEPKwl`
* `_ZNSt3__113basic_istreamIcNS_11char_traitsIcEEErsEPFRS3_S4_E`
* `_ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEEC1EPNS_15basic_streambufIcS2_EE`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE9pubsetbufEPwl`
* `_ZNSt3__115basic_streambufIwNS_11char_traitsIwEEE5sputcEw`
This patch has no effect on Clang based builds.
Reviewers: mclow.lists, eugenis, danalbert, jroelofs, EricWF
Subscribers: beanz, cfe-commits, mgorny
Differential Revision: https://reviews.llvm.org/D24600
llvm-svn: 281681
2016-09-16 08:00:48 +08:00
|
|
|
**_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
|
|
|
|
the library.
|
|
|
|
|
|
|
|
This macro is used to maintain ABI compatibility for symbols that have been
|
|
|
|
historically exported by the libc++ library but are now marked inline. It
|
|
|
|
should only be applied to member functions of class templates that are
|
|
|
|
externally instantiated.
|
|
|
|
|
2016-09-16 06:27:07 +08:00
|
|
|
**_LIBCPP_EXCEPTION_ABI**
|
|
|
|
Mark the member functions, typeinfo, and vtable of the type as being exported
|
|
|
|
by the libc++ library. This macro must be applied to all *exception types*.
|
2016-09-16 10:51:26 +08:00
|
|
|
Exception types should be defined directly in namespace `std` and not the
|
|
|
|
versioning namespace. This allows throwing and catching some exception types
|
|
|
|
between libc++ and libstdc++.
|
2016-09-16 06:27:07 +08:00
|
|
|
|
2016-09-29 06:28:51 +08:00
|
|
|
**_LIBCPP_NEW_DELETE_VIS**
|
|
|
|
Mark a symbol as being exported by the libc++ library. This macro must be
|
|
|
|
applied to all `operator new` and `operator delete` overloads.
|
|
|
|
|
2016-10-12 21:48:14 +08:00
|
|
|
**Windows Behavior**: The `operator new` and `operator delete` overloads
|
|
|
|
should not be marked as `dllimport`; if they were, source files including the
|
|
|
|
`<new>` header (either directly or transitively) would lose the ability to use
|
|
|
|
local overloads of `operator new` and `operator delete`. On Windows, this
|
|
|
|
macro therefore expands to `__declspec(dllexport)` when building the library
|
|
|
|
and has an empty definition otherwise. A related caveat is that libc++ must be
|
|
|
|
included on the link line before `msvcrt.lib`, otherwise Microsoft's
|
|
|
|
definitions of `operator new` and `operator delete` inside `msvcrt.lib` will
|
|
|
|
end up being used instead of libc++'s.
|
2016-09-29 06:28:51 +08:00
|
|
|
|
2016-09-16 06:27:07 +08:00
|
|
|
Links
|
|
|
|
=====
|
|
|
|
|
|
|
|
* `[cfe-dev] Visibility in libc++ - 1 <http://lists.llvm.org/pipermail/cfe-dev/2013-July/030610.html>`_
|
|
|
|
* `[cfe-dev] Visibility in libc++ - 2 <http://lists.llvm.org/pipermail/cfe-dev/2013-August/031195.html>`_
|
|
|
|
* `[libcxx] Visibility fixes for Windows <http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20130805/085461.html>`_
|