[libc++] Make sure we can build libc++ with -fvisibility=hidden

Summary:
When building with -fvisibility=hidden, some symbols do not get exported from
libc++.dylib. This means that some entities are not explicitly given default
visibility in the source code, and that we rely on the fact -fvisibility=default
is the default. This commit explicitly gives default visibility to those
symbols to avoid being dependent on the command line flags used.

The commit also remove symbols from the dylib -- those symbols do not
actually need to be exported from the dylib and this should not be an
ABI break.

Finally, in the future, we may want to mark the whole std:: namespace as
having hidden visibility (to switch from opt-out to opt-in), in which
case the changes done in this commit will be required.

Reviewers: EricWF

Subscribers: mgorny, christof, dexonsmith, libcxx-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@345260 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/docs/DesignDocs/VisibilityMacros.rst b/docs/DesignDocs/VisibilityMacros.rst
index 08debbc..d0d4f0a 100644
--- a/docs/DesignDocs/VisibilityMacros.rst
+++ b/docs/DesignDocs/VisibilityMacros.rst
@@ -22,11 +22,11 @@
   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_EXTERN_VIS**
+**_LIBCPP_EXPORTED_FROM_ABI**
   Mark a symbol as being exported by the libc++ library. This attribute may
-  only be applied to objects defined in the libc++ library. On Windows this
-  macro applies `dllimport`/`dllexport` to the symbol. On all other platforms
-  this macro has no effect.
+  only be applied to objects defined in the libc++ runtime library. On Windows,
+  this macro applies `dllimport`/`dllexport` to the symbol, and on other
+  platforms it gives the symbol default visibility.
 
 **_LIBCPP_OVERRIDABLE_FUNC_VIS**
   Mark a symbol as being exported by the libc++ library, but allow it to be
diff --git a/include/__config b/include/__config
index 51068b3..f602074 100644
--- a/include/__config
+++ b/include/__config
@@ -675,21 +675,23 @@
 #  define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
 #  define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
 #  define _LIBCPP_OVERRIDABLE_FUNC_VIS
+#  define _LIBCPP_EXPORTED_FROM_ABI
 #elif defined(_LIBCPP_BUILDING_LIBRARY)
 #  define _LIBCPP_DLL_VIS __declspec(dllexport)
 #  define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
 #  define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS _LIBCPP_DLL_VIS
 #  define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_DLL_VIS
+#  define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllexport)
 #else
 #  define _LIBCPP_DLL_VIS __declspec(dllimport)
 #  define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS
 #  define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
 #  define _LIBCPP_OVERRIDABLE_FUNC_VIS
+#  define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport)
 #endif
 
 #define _LIBCPP_TYPE_VIS            _LIBCPP_DLL_VIS
 #define _LIBCPP_FUNC_VIS            _LIBCPP_DLL_VIS
-#define _LIBCPP_EXTERN_VIS          _LIBCPP_DLL_VIS
 #define _LIBCPP_EXCEPTION_ABI       _LIBCPP_DLL_VIS
 #define _LIBCPP_HIDDEN
 #define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
@@ -743,8 +745,8 @@
 #  endif
 #endif
 
-#ifndef _LIBCPP_EXTERN_VIS
-#define _LIBCPP_EXTERN_VIS
+#ifndef _LIBCPP_EXPORTED_FROM_ABI
+#  define _LIBCPP_EXPORTED_FROM_ABI __attribute__((__visibility__("default")))
 #endif
 
 #ifndef _LIBCPP_OVERRIDABLE_FUNC_VIS
diff --git a/include/__debug b/include/__debug
index d01bacd..a8788f6 100644
--- a/include/__debug
+++ b/include/__debug
@@ -74,7 +74,7 @@
 
 /// __libcpp_debug_function - The handler function called when a _LIBCPP_ASSERT
 ///    fails.
-extern _LIBCPP_EXTERN_VIS __libcpp_debug_function_type __libcpp_debug_function;
+extern _LIBCPP_EXPORTED_FROM_ABI __libcpp_debug_function_type __libcpp_debug_function;
 
 /// __libcpp_abort_debug_function - A debug handler that aborts when called.
 _LIBCPP_NORETURN _LIBCPP_FUNC_VIS
diff --git a/include/__functional_base b/include/__functional_base
index 1887974..032be99 100644
--- a/include/__functional_base
+++ b/include/__functional_base
@@ -562,7 +562,7 @@
 struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { };
 
 #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
-extern const allocator_arg_t allocator_arg;
+extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg;
 #else
 /* _LIBCPP_INLINE_VAR */ constexpr allocator_arg_t allocator_arg = allocator_arg_t();
 #endif
diff --git a/include/__locale b/include/__locale
index f43e7b4..cde9cc8 100644
--- a/include/__locale
+++ b/include/__locale
@@ -1255,13 +1255,13 @@
 };
 
 template <>
-struct __narrow_to_utf8<16>
+struct _LIBCPP_TEMPLATE_VIS __narrow_to_utf8<16>
     : public codecvt<char16_t, char, mbstate_t>
 {
     _LIBCPP_INLINE_VISIBILITY
     __narrow_to_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
 
-    ~__narrow_to_utf8();
+    _LIBCPP_EXPORTED_FROM_ABI ~__narrow_to_utf8();
 
     template <class _OutputIterator, class _CharT>
     _LIBCPP_INLINE_VISIBILITY
@@ -1289,13 +1289,13 @@
 };
 
 template <>
-struct __narrow_to_utf8<32>
+struct _LIBCPP_TEMPLATE_VIS __narrow_to_utf8<32>
     : public codecvt<char32_t, char, mbstate_t>
 {
     _LIBCPP_INLINE_VISIBILITY
     __narrow_to_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
 
-    ~__narrow_to_utf8();
+    _LIBCPP_EXPORTED_FROM_ABI ~__narrow_to_utf8();
 
     template <class _OutputIterator, class _CharT>
     _LIBCPP_INLINE_VISIBILITY
@@ -1345,13 +1345,13 @@
 };
 
 template <>
-struct __widen_from_utf8<16>
+struct _LIBCPP_TEMPLATE_VIS __widen_from_utf8<16>
     : public codecvt<char16_t, char, mbstate_t>
 {
     _LIBCPP_INLINE_VISIBILITY
     __widen_from_utf8() : codecvt<char16_t, char, mbstate_t>(1) {}
 
-    ~__widen_from_utf8();
+    _LIBCPP_EXPORTED_FROM_ABI ~__widen_from_utf8();
 
     template <class _OutputIterator>
     _LIBCPP_INLINE_VISIBILITY
@@ -1379,13 +1379,13 @@
 };
 
 template <>
-struct __widen_from_utf8<32>
+struct _LIBCPP_TEMPLATE_VIS __widen_from_utf8<32>
     : public codecvt<char32_t, char, mbstate_t>
 {
     _LIBCPP_INLINE_VISIBILITY
     __widen_from_utf8() : codecvt<char32_t, char, mbstate_t>(1) {}
 
-    ~__widen_from_utf8();
+    _LIBCPP_EXPORTED_FROM_ABI ~__widen_from_utf8();
 
     template <class _OutputIterator>
     _LIBCPP_INLINE_VISIBILITY
diff --git a/include/__mutex_base b/include/__mutex_base
index 4659ca9..da21a5f 100644
--- a/include/__mutex_base
+++ b/include/__mutex_base
@@ -76,9 +76,9 @@
 
 #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
 
-extern const defer_lock_t  defer_lock;
-extern const try_to_lock_t try_to_lock;
-extern const adopt_lock_t  adopt_lock;
+extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t  defer_lock;
+extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
+extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t  adopt_lock;
 
 #else
 
diff --git a/include/charconv b/include/charconv
index 7cb790e..c0cb9c5 100644
--- a/include/charconv
+++ b/include/charconv
@@ -89,6 +89,11 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+namespace __itoa {
+_LIBCPP_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer);
+_LIBCPP_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer);
+}
+
 #if _LIBCPP_STD_VER > 11
 
 enum class _LIBCPP_ENUM_VIS chars_format
@@ -147,9 +152,6 @@
     UINT32_C(1000000000),
 };
 
-_LIBCPP_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer);
-_LIBCPP_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer);
-
 template <typename _Tp, typename = void>
 struct _LIBCPP_HIDDEN __traits_base
 {
diff --git a/include/locale b/include/locale
index e240799..7be358e 100644
--- a/include/locale
+++ b/include/locale
@@ -2408,6 +2408,23 @@
     string_type __analyze(char __fmt, const ctype<_CharT>&);
 };
 
+#define _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(_CharT) \
+template <> _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
+template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
+template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
+template <> _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
+template <> _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
+extern template _LIBCPP_FUNC_VIS time_base::dateorder __time_get_storage<_CharT>::__do_date_order() const; \
+extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const char*); \
+extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::__time_get_storage(const string&); \
+extern template _LIBCPP_FUNC_VIS void __time_get_storage<_CharT>::init(const ctype<_CharT>&); \
+extern template _LIBCPP_FUNC_VIS __time_get_storage<_CharT>::string_type __time_get_storage<_CharT>::__analyze(char, const ctype<_CharT>&); \
+/**/
+
+_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(char)
+_LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION(wchar_t)
+#undef _LIBCPP_TIME_GET_STORAGE_EXPLICIT_INSTANTIATION
+
 template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
 class _LIBCPP_TEMPLATE_VIS time_get_byname
     : public time_get<_CharT, _InputIterator>,
diff --git a/include/thread b/include/thread
index 0629d70..8c0115f 100644
--- a/include/thread
+++ b/include/thread
@@ -151,7 +151,7 @@
     __thread_specific_ptr(const __thread_specific_ptr&);
     __thread_specific_ptr& operator=(const __thread_specific_ptr&);
 
-    static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);
+    _LIBCPP_HIDDEN static void _LIBCPP_TLS_DESTRUCTOR_CC __at_thread_exit(void*);
 
 public:
     typedef _Tp* pointer;
diff --git a/include/utility b/include/utility
index 5388585..30e26f1 100644
--- a/include/utility
+++ b/include/utility
@@ -297,7 +297,7 @@
 
 struct _LIBCPP_TEMPLATE_VIS piecewise_construct_t { };
 #if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
-extern const piecewise_construct_t piecewise_construct;// = piecewise_construct_t();
+extern _LIBCPP_EXPORTED_FROM_ABI const piecewise_construct_t piecewise_construct;// = piecewise_construct_t();
 #else
 /* _LIBCPP_INLINE_VAR */ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t();
 #endif
diff --git a/lib/abi/CHANGELOG.TXT b/lib/abi/CHANGELOG.TXT
index 4c9a597..a5451bc 100644
--- a/lib/abi/CHANGELOG.TXT
+++ b/lib/abi/CHANGELOG.TXT
@@ -16,6 +16,34 @@
 Version 7.0
 -----------
 
+* rXXXXX - Making libc++ build under -fvisibility=hidden
+
+  The change marks __thread_specific_ptr<__thread_struct>::__at_thread_exit(void*)
+  with hidden visibility. This removes a symbol from the shared libraries,
+  however this is not an ABI break because it's impossible for programs linking
+  against libc++.dylib to actually depend on that symbol. The reason is that
+  the symbol is exported from the shared library through an implicit
+  instantiation present in the dylib itself only. Furthermore, if a user's
+  dylib was implicitly instantiating __thread_specific_ptr<T>::__at_thread_exit
+  (because it's defined in the headers), marking that symbol as hidden would
+  not be an ABI break for them because none of their users could actually be
+  using the symbol in their dylib (because it's an implicit instantiation).
+
+  This change also marks __start_std_streams as hidden -- this variable is
+  only required to initialize the streams, and nobody should depend on it
+  from outside the dylib.
+
+  x86_64-linux-gnu
+  ----------------
+  Symbol removed: _ZNSt3__121__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv
+  Symbol removed: _ZNSt3__119__start_std_streamsE
+
+  x86_64-apple-darwin16.0
+  -----------------------
+  Symbol removed: __ZNSt3__221__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv
+  Symbol removed: __ZNSt3__119__start_std_streamsE
+
+
 * r338479 - Elementary string conversions for integral types
 
   The change emits __u64toa and __u32toa under std::__1::__itoa.
diff --git a/lib/abi/x86_64-apple-darwin.v1.abilist b/lib/abi/x86_64-apple-darwin.v1.abilist
index 6d01161..88cfa90 100644
--- a/lib/abi/x86_64-apple-darwin.v1.abilist
+++ b/lib/abi/x86_64-apple-darwin.v1.abilist
@@ -1197,13 +1197,11 @@
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD0Ev'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD1Ev'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119__shared_weak_countD2Ev'}
-{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__119__start_std_streamsE', 'size': 0}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119__thread_local_dataEv'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__119declare_no_pointersEPcm'}
 {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__119piecewise_constructE', 'size': 0}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__120__get_collation_nameEPKc'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__120__throw_system_errorEiPKc'}
-{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121__throw_runtime_errorEPKc'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121__undeclare_reachableEPv'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__121recursive_timed_mutex4lockEv'}
diff --git a/lib/abi/x86_64-apple-darwin.v2.abilist b/lib/abi/x86_64-apple-darwin.v2.abilist
index e77b9f0..3896b38 100644
--- a/lib/abi/x86_64-apple-darwin.v2.abilist
+++ b/lib/abi/x86_64-apple-darwin.v2.abilist
@@ -1119,13 +1119,11 @@
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_weak_countD0Ev'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_weak_countD1Ev'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__shared_weak_countD2Ev'}
-{'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__219__start_std_streamsE', 'size': 0}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219__thread_local_dataEv'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__219declare_no_pointersEPcm'}
 {'type': 'OBJECT', 'is_defined': True, 'name': '__ZNSt3__219piecewise_constructE', 'size': 0}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__220__get_collation_nameEPKc'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__220__throw_system_errorEiPKc'}
-{'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221__throw_runtime_errorEPKc'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221__undeclare_reachableEPv'}
 {'type': 'FUNC', 'is_defined': True, 'name': '__ZNSt3__221recursive_timed_mutex4lockEv'}
diff --git a/lib/abi/x86_64-unknown-linux-gnu.v1.abilist b/lib/abi/x86_64-unknown-linux-gnu.v1.abilist
index 833342c..f8af757 100644
--- a/lib/abi/x86_64-unknown-linux-gnu.v1.abilist
+++ b/lib/abi/x86_64-unknown-linux-gnu.v1.abilist
@@ -1098,13 +1098,11 @@
 {'name': '_ZNSt3__119__shared_weak_countD0Ev', 'is_defined': True, 'type': 'FUNC'}
 {'name': '_ZNSt3__119__shared_weak_countD1Ev', 'is_defined': True, 'type': 'FUNC'}
 {'name': '_ZNSt3__119__shared_weak_countD2Ev', 'is_defined': True, 'type': 'FUNC'}
-{'name': '_ZNSt3__119__start_std_streamsE', 'is_defined': True, 'type': 'OBJECT', 'size': 1}
 {'name': '_ZNSt3__119__thread_local_dataEv', 'is_defined': True, 'type': 'FUNC'}
 {'name': '_ZNSt3__119declare_no_pointersEPcm', 'is_defined': True, 'type': 'FUNC'}
 {'name': '_ZNSt3__119piecewise_constructE', 'is_defined': True, 'type': 'OBJECT', 'size': 1}
 {'name': '_ZNSt3__120__get_collation_nameEPKc', 'is_defined': True, 'type': 'FUNC'}
 {'name': '_ZNSt3__120__throw_system_errorEiPKc', 'is_defined': True, 'type': 'FUNC'}
-{'name': '_ZNSt3__121__thread_specific_ptrINS_15__thread_structEE16__at_thread_exitEPv', 'is_defined': True, 'type': 'FUNC'}
 {'name': '_ZNSt3__121__throw_runtime_errorEPKc', 'is_defined': True, 'type': 'FUNC'}
 {'name': '_ZNSt3__121__undeclare_reachableEPv', 'is_defined': True, 'type': 'FUNC'}
 {'name': '_ZNSt3__121recursive_timed_mutex4lockEv', 'is_defined': True, 'type': 'FUNC'}
diff --git a/src/iostream.cpp b/src/iostream.cpp
index 2b47cf2..66abdaf 100644
--- a/src/iostream.cpp
+++ b/src/iostream.cpp
@@ -77,7 +77,7 @@
 #endif
 ;
 
-ios_base::Init __start_std_streams;
+_LIBCPP_HIDDEN ios_base::Init __start_std_streams;
 
 ios_base::Init::Init()
 {