Use __attribute__((internal_linkage)) when available.
authorEric Fiselier <eric@efcs.ca>
Sun, 25 Sep 2016 03:14:13 +0000 (03:14 +0000)
committerEric Fiselier <eric@efcs.ca>
Sun, 25 Sep 2016 03:14:13 +0000 (03:14 +0000)
Summary:
This patch has been a long time coming (Thanks @eugenis). It changes `_LIBCPP_INLINE_VISIBILITY` to use `__attribute__((internal_linkage))` instead of `__attribute__((visibility("hidden"), always_inline))`.

The point of `_LIBCPP_INLINE_VISIBILITY` is to prevent inline functions from being exported from both the libc++ library and from user libraries. This helps libc++ better manage it's ABI.
Previously this was done by forcing inlining and modifying the symbols visibility. However inlining isn't guaranteed and symbol visibility only affects shared libraries making this an imperfect solution.  `internal_linkage` improves this situation by making all symbols local to the TU they are emitted in, regardless of inlining or visibility. IIRC the effect of applying `__attribute__((internal_linkage))` to an inline function is the same as applying `static`.

For more information about the attribute see: http://lists.llvm.org/pipermail/cfe-dev/2015-October/045580.html

Most of the work for this patch was done by @eugenis.

Reviewers: mclow.lists, eugenis

Subscribers: eugenis, cfe-commits

Differential Revision: https://reviews.llvm.org/D24642

llvm-svn: 282345

libcxx/include/__config
libcxx/src/string.cpp

index 86f945dc96b1b09eb198e03b8a11991ec9b3ff00..56326af1af85264473c194357dfbdbb6561d27b3 100644 (file)
@@ -34,6 +34,7 @@
 #endif
 
 #if defined(_LIBCPP_ABI_UNSTABLE) || _LIBCPP_ABI_VERSION >= 2
+#define _LIBCPP_ABI_EXTERN_TEMPLATE_SYMBOLS_VERSION 2
 // Change short string representation so that string data starts at offset 0,
 // improving its alignment in some cases.
 #define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
@@ -49,6 +50,7 @@
 #define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
 #define _LIBCPP_ABI_VARIADIC_LOCK_GUARD
 #elif _LIBCPP_ABI_VERSION == 1
+#define _LIBCPP_ABI_EXTERN_TEMPLATE_SYMBOLS_VERSION 1
 // Feature macros for disabling pre ABI v1 features. All of these options
 // are deprecated.
 #if defined(__FreeBSD__)
@@ -629,11 +631,19 @@ namespace std {
 #endif
 
 #ifndef _LIBCPP_INLINE_VISIBILITY
-#define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
+# if __has_attribute(__internal_linkage__)
+#   define _LIBCPP_INLINE_VISIBILITY __attribute__((__internal_linkage__, __always_inline__))
+# else
+#   define _LIBCPP_INLINE_VISIBILITY __attribute__ ((__visibility__("hidden"), __always_inline__))
+# endif
 #endif
 
 #ifndef _LIBCPP_ALWAYS_INLINE
-#define _LIBCPP_ALWAYS_INLINE  __attribute__ ((__visibility__("hidden"), __always_inline__))
+# if __has_attribute(__internal_linkage__)
+#   define _LIBCPP_ALWAYS_INLINE __attribute__((__internal_linkage__, __always_inline__))
+# else
+#   define _LIBCPP_ALWAYS_INLINE  __attribute__ ((__visibility__("hidden"), __always_inline__))
+# endif
 #endif
 
 #ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
index cd644330b3a775ac8b69dd05cfd126843330ba09..4f56e40a6fa010e200e0fc43b38986747fb6c711 100644 (file)
@@ -29,6 +29,29 @@ template
     string
     operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
 
+// These external instantiations are required to maintain dylib compatibility
+// for ABI v1 when using __attribute__((internal_linkage)) as opposed to
+// __attribute__((visibility("hidden"), always_inline)).
+#if _LIBCPP_ABI_EXTERN_TEMPLATE_SYMBOLS_VERSION == 1
+template basic_string<char>::iterator
+basic_string<char>::insert(basic_string<char>::const_iterator,
+                           char const *, char const *);
+
+template basic_string<wchar_t>::iterator
+basic_string<wchar_t>::insert(basic_string<wchar_t>::const_iterator,
+                              wchar_t const *, wchar_t const *);
+
+template basic_string<char> &
+basic_string<char>::replace(basic_string<char>::const_iterator,
+                               basic_string<char>::const_iterator,
+                               char const *, char const *);
+
+template basic_string<wchar_t> &
+basic_string<wchar_t>::replace(basic_string<wchar_t>::const_iterator,
+                               basic_string<wchar_t>::const_iterator,
+                               wchar_t const *, wchar_t const *);
+#endif // _LIBCPP_ABI_EXTERN_TEMPLATE_SYMBOLS_VERSION
+
 namespace
 {