EricWF created this revision.
EricWF added reviewers: mclow.lists, eugenis, danalbert, jroelofs.
EricWF added a subscriber: cfe-commits.
Herald added subscribers: mgorny, beanz.

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.



https://reviews.llvm.org/D24600

Files:
  CMakeLists.txt
  include/__config
  include/istream
  include/ostream
  include/streambuf
  include/string
  utils/sym_check/sym_diff.py

Index: utils/sym_check/sym_diff.py
===================================================================
--- utils/sym_check/sym_diff.py
+++ utils/sym_check/sym_diff.py
@@ -24,6 +24,10 @@
         help='Only print symbol names',
         action='store_true', default=False)
     parser.add_argument(
+        '--removed-only', dest='removed_only',
+        help='Only print removed symbols',
+        action='store_true', default=False)
+    parser.add_argument(
         '-o', '--output', dest='output',
         help='The output file. stdout is used if not given',
         type=str, action='store', default=None)
@@ -41,6 +45,8 @@
     new_syms_list = util.extract_or_load(args.new_syms)
 
     added, removed, changed = diff.diff(old_syms_list, new_syms_list)
+    if args.removed_only:
+        added = {}
     report, is_break = diff.report_diff(added, removed, changed,
                                         names_only=args.names_only,
                                         demangle=args.demangle)
Index: include/string
===================================================================
--- include/string
+++ include/string
@@ -1430,7 +1430,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz, size_type __reserve)
 {
@@ -1455,7 +1455,7 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz)
 {
@@ -1593,7 +1593,7 @@
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c)
 {
@@ -1690,7 +1690,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _InputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename enable_if
 <
     __is_exactly_input_iterator<_InputIterator>::value,
@@ -1718,7 +1718,7 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _ForwardIterator>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename enable_if
 <
     __is_forward_iterator<_ForwardIterator>::value,
Index: include/streambuf
===================================================================
--- include/streambuf
+++ include/streambuf
@@ -220,7 +220,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 locale
 basic_streambuf<_CharT, _Traits>::pubimbue(const locale& __loc)
 {
@@ -231,23 +231,23 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 locale
 basic_streambuf<_CharT, _Traits>::getloc() const
 {
     return __loc_;
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_streambuf<_CharT, _Traits>*
 basic_streambuf<_CharT, _Traits>::pubsetbuf(char_type* __s, streamsize __n)
 {
     return setbuf(__s, __n);
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_streambuf<_CharT, _Traits>::pos_type
 basic_streambuf<_CharT, _Traits>::pubseekoff(off_type __off,
                                              ios_base::seekdir __way,
@@ -257,24 +257,24 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_streambuf<_CharT, _Traits>::pos_type
 basic_streambuf<_CharT, _Traits>::pubseekpos(pos_type __sp,
                                              ios_base::openmode __which)
 {
     return seekpos(__sp, __which);
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 int
 basic_streambuf<_CharT, _Traits>::pubsync()
 {
     return sync();
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 streamsize
 basic_streambuf<_CharT, _Traits>::in_avail()
 {
@@ -284,7 +284,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_streambuf<_CharT, _Traits>::int_type
 basic_streambuf<_CharT, _Traits>::snextc()
 {
@@ -294,7 +294,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_streambuf<_CharT, _Traits>::int_type
 basic_streambuf<_CharT, _Traits>::sbumpc()
 {
@@ -304,7 +304,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_streambuf<_CharT, _Traits>::int_type
 basic_streambuf<_CharT, _Traits>::sgetc()
 {
@@ -314,15 +314,15 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 streamsize
 basic_streambuf<_CharT, _Traits>::sgetn(char_type* __s, streamsize __n)
 {
     return xsgetn(__s, __n);
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_streambuf<_CharT, _Traits>::int_type
 basic_streambuf<_CharT, _Traits>::sputbackc(char_type __c)
 {
@@ -332,7 +332,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_streambuf<_CharT, _Traits>::int_type
 basic_streambuf<_CharT, _Traits>::sungetc()
 {
@@ -342,7 +342,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_streambuf<_CharT, _Traits>::int_type
 basic_streambuf<_CharT, _Traits>::sputc(char_type __c)
 {
@@ -353,7 +353,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 streamsize
 basic_streambuf<_CharT, _Traits>::sputn(const char_type* __s, streamsize __n)
 {
@@ -411,15 +411,15 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_streambuf<_CharT, _Traits>::gbump(int __n)
 {
     __ninp_ += __n;
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_streambuf<_CharT, _Traits>::setg(char_type* __gbeg, char_type* __gnext,
                                                           char_type* __gend)
@@ -430,15 +430,15 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_streambuf<_CharT, _Traits>::pbump(int __n)
 {
     __nout_ += __n;
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_streambuf<_CharT, _Traits>::setp(char_type* __pbeg, char_type* __pend)
 {
Index: include/ostream
===================================================================
--- include/ostream
+++ include/ostream
@@ -164,13 +164,13 @@
     virtual ~basic_ostream();
 protected:
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY
     basic_ostream(basic_ostream&& __rhs);
 #endif
 
     // 27.7.2.3 Assign/swap
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY
     basic_ostream& operator=(basic_ostream&& __rhs);
 #endif
     void swap(basic_ostream& __rhs);
@@ -275,23 +275,21 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>::basic_ostream(basic_streambuf<char_type, traits_type>* __sb)
 {
     this->init(__sb);
 }
 
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>::basic_ostream(basic_ostream&& __rhs)
 {
     this->move(__rhs);
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>&
 basic_ostream<_CharT, _Traits>::operator=(basic_ostream&& __rhs)
 {
@@ -307,23 +305,23 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_ostream<_CharT, _Traits>::swap(basic_ostream& __rhs)
 {
     basic_ios<char_type, traits_type>::swap(__rhs);
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>&
 basic_ostream<_CharT, _Traits>::operator<<(basic_ostream& (*__pf)(basic_ostream&))
 {
     return __pf(*this);
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>&
 basic_ostream<_CharT, _Traits>::operator<<(basic_ios<char_type, traits_type>&
                                            (*__pf)(basic_ios<char_type,traits_type>&))
@@ -333,7 +331,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>&
 basic_ostream<_CharT, _Traits>::operator<<(ios_base& (*__pf)(ios_base&))
 {
@@ -989,7 +987,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 typename basic_ostream<_CharT, _Traits>::pos_type
 basic_ostream<_CharT, _Traits>::tellp()
 {
@@ -999,7 +997,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>&
 basic_ostream<_CharT, _Traits>::seekp(pos_type __pos)
 {
@@ -1013,7 +1011,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>&
 basic_ostream<_CharT, _Traits>::seekp(off_type __off, ios_base::seekdir __dir)
 {
Index: include/istream
===================================================================
--- include/istream
+++ include/istream
@@ -188,12 +188,12 @@
     virtual ~basic_istream();
 protected:
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY
     basic_istream(basic_istream&& __rhs);
 #endif
     // 27.7.1.1.2 Assign/swap:
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY
     basic_istream& operator=(basic_istream&& __rhs);
 #endif
     void swap(basic_istream& __rhs);
@@ -304,7 +304,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>::basic_istream(basic_streambuf<char_type, traits_type>* __sb)
     : __gc_(0)
 {
@@ -314,16 +314,14 @@
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>::basic_istream(basic_istream&& __rhs)
     : __gc_(__rhs.__gc_)
 {
     __rhs.__gc_ = 0;
     this->move(__rhs);
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::operator=(basic_istream&& __rhs)
 {
@@ -339,7 +337,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_istream<_CharT, _Traits>::swap(basic_istream& __rhs)
 {
@@ -725,15 +723,15 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::operator>>(basic_istream& (*__pf)(basic_istream&))
 {
     return __pf(*this);
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::operator>>(basic_ios<char_type, traits_type>&
                                            (*__pf)(basic_ios<char_type, traits_type>&))
@@ -743,7 +741,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::operator>>(ios_base& (*__pf)(ios_base&))
 {
@@ -947,7 +945,7 @@
 }
 
 template<class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::get(char_type& __c)
 {
@@ -1006,7 +1004,7 @@
 }
 
 template<class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n)
 {
@@ -1068,7 +1066,7 @@
 }
 
 template<class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __sb)
 {
@@ -1129,7 +1127,7 @@
 }
 
 template<class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n)
 {
@@ -1507,37 +1505,35 @@
     virtual ~basic_iostream();
 protected:
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY
     basic_iostream(basic_iostream&& __rhs);
 #endif
 
     // assign/swap
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-    _LIBCPP_INLINE_VISIBILITY
+    inline _LIBCPP_INLINE_VISIBILITY
     basic_iostream& operator=(basic_iostream&& __rhs);
 #endif
     void swap(basic_iostream& __rhs);
 public:
 };
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 basic_iostream<_CharT, _Traits>::basic_iostream(basic_streambuf<char_type, traits_type>* __sb)
     : basic_istream<_CharT, _Traits>(__sb)
 {
 }
 
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
 basic_iostream<_CharT, _Traits>::basic_iostream(basic_iostream&& __rhs)
     : basic_istream<_CharT, _Traits>(_VSTD::move(__rhs))
 {
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
 basic_iostream<_CharT, _Traits>&
 basic_iostream<_CharT, _Traits>::operator=(basic_iostream&& __rhs)
 {
@@ -1553,7 +1549,7 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
+inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
 void
 basic_iostream<_CharT, _Traits>::swap(basic_iostream& __rhs)
 {
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -232,6 +232,12 @@
 # endif
 #endif
 
+#ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+# ifdef _LIBCPP_MSVC
+#   define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __forceinline
+# endif
+#endif
+
 #ifndef _LIBCPP_EXCEPTION_ABI
 #define _LIBCPP_EXCEPTION_ABI _LIBCPP_TYPE_VIS
 #endif
@@ -286,6 +292,14 @@
 #define _LIBCPP_ALWAYS_INLINE  __attribute__ ((__visibility__("hidden"), __always_inline__))
 #endif
 
+#ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+# ifdef _LIBCPP_BUILDING_LIBRARY
+#   define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__((__visibility__("default"), __always_inline__))
+# else
+#   define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
+# endif
+#endif
+
 #if defined(__clang__)
 
 // _LIBCPP_ALTERNATE_STRING_LAYOUT is an old name for
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -330,6 +330,8 @@
 # headers
 add_compile_flags_if_supported(-nostdinc++)
 
+add_definitions(-D_LIBCPP_BUILDING_LIBRARY)
+
 # Warning flags ===============================================================
 add_definitions(-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 add_compile_flags_if_supported(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to