EricWF updated this revision to Diff 71574.
EricWF added a comment.

- Update the patch based on r281673.
- Add doc for `_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY`
- Move all uses of `_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY` to the first 
declaration in order to support `__attribute__((internal_linkage))`. I took the 
liberty of moving many of the definitions in-line to reduce duplication.




https://reviews.llvm.org/D24600

Files:
  CMakeLists.txt
  docs/DesignDocs/VisibilityMacros.rst
  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
@@ -1269,19 +1269,24 @@
                  __align_it<sizeof(value_type) < __alignment ?
                             __alignment/sizeof(value_type) : 1 > (__s+1)) - 1;}
 
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     void __init(const value_type* __s, size_type __sz, size_type __reserve);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     void __init(const value_type* __s, size_type __sz);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     void __init(size_type __n, value_type __c);
 
     template <class _InputIterator>
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     typename enable_if
     <
         __is_exactly_input_iterator<_InputIterator>::value,
         void
     >::type
     __init(_InputIterator __first, _InputIterator __last);
 
     template <class _ForwardIterator>
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     typename enable_if
     <
         __is_forward_iterator<_ForwardIterator>::value,
@@ -1430,9 +1435,9 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
-void
-basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz, size_type __reserve)
+void basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s,
+                                                       size_type __sz,
+                                                       size_type __reserve)
 {
     if (__reserve > max_size())
         this->__throw_length_error();
@@ -1455,7 +1460,6 @@
 }
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::__init(const value_type* __s, size_type __sz)
 {
@@ -1593,7 +1597,6 @@
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
 template <class _CharT, class _Traits, class _Allocator>
-inline _LIBCPP_INLINE_VISIBILITY
 void
 basic_string<_CharT, _Traits, _Allocator>::__init(size_type __n, value_type __c)
 {
@@ -1690,7 +1693,6 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _InputIterator>
-inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
     __is_exactly_input_iterator<_InputIterator>::value,
@@ -1718,7 +1720,6 @@
 
 template <class _CharT, class _Traits, class _Allocator>
 template <class _ForwardIterator>
-inline _LIBCPP_INLINE_VISIBILITY
 typename enable_if
 <
     __is_forward_iterator<_ForwardIterator>::value,
Index: include/streambuf
===================================================================
--- include/streambuf
+++ include/streambuf
@@ -132,32 +132,96 @@
     virtual ~basic_streambuf();
 
     // 27.6.2.2.1 locales:
-    locale pubimbue(const locale& __loc);
-    locale getloc() const;
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    locale pubimbue(const locale& __loc) {
+        imbue(__loc);
+        locale __r = __loc_;
+        __loc_ = __loc;
+        return __r;
+    }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    locale getloc() const { return __loc_; }
 
     // 27.6.2.2.2 buffer and positioning:
-    basic_streambuf* pubsetbuf(char_type* __s, streamsize __n);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_streambuf* pubsetbuf(char_type* __s, streamsize __n)
+    { return setbuf(__s, __n); }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     pos_type pubseekoff(off_type __off, ios_base::seekdir __way,
-                        ios_base::openmode __which = ios_base::in | ios_base::out);
+                        ios_base::openmode __which = ios_base::in | ios_base::out)
+    { return seekoff(__off, __way, __which); }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     pos_type pubseekpos(pos_type __sp,
-                        ios_base::openmode __which = ios_base::in | ios_base::out);
-    int pubsync();
+                        ios_base::openmode __which = ios_base::in | ios_base::out)
+    { return seekpos(__sp, __which); }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    int pubsync() { return sync(); }
 
     // Get and put areas:
     // 27.6.2.2.3 Get area:
-    streamsize in_avail();
-    int_type snextc();
-    int_type sbumpc();
-    int_type sgetc();
-    streamsize sgetn(char_type* __s, streamsize __n);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    streamsize in_avail() {
+        if (__ninp_ < __einp_)
+            return static_cast<streamsize>(__einp_ - __ninp_);
+        return showmanyc();
+    }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    int_type snextc() {
+        if (sbumpc() == traits_type::eof())
+            return traits_type::eof();
+        return sgetc();
+    }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    int_type sbumpc() {
+        if (__ninp_ == __einp_)
+            return uflow();
+        return traits_type::to_int_type(*__ninp_++);
+    }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    int_type sgetc() {
+        if (__ninp_ == __einp_)
+            return underflow();
+        return traits_type::to_int_type(*__ninp_);
+    }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    streamsize sgetn(char_type* __s, streamsize __n)
+    { return xsgetn(__s, __n); }
 
     // 27.6.2.2.4 Putback:
-    int_type sputbackc(char_type __c);
-    int_type sungetc();
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    int_type sputbackc(char_type __c) {
+        if (__binp_ == __ninp_ || !traits_type::eq(__c, __ninp_[-1]))
+            return pbackfail(traits_type::to_int_type(__c));
+        return traits_type::to_int_type(*--__ninp_);
+    }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    int_type sungetc() {
+        if (__binp_ == __ninp_)
+          return pbackfail();
+        return traits_type::to_int_type(*--__ninp_);
+    }
 
     // 27.6.2.2.5 Put area:
-    int_type sputc(char_type __c);
-    streamsize sputn(const char_type* __s, streamsize __n);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    int_type sputc(char_type __c) {
+        if (__nout_ == __eout_)
+            return overflow(traits_type::to_int_type(__c));
+        *__nout_++ = __c;
+        return traits_type::to_int_type(__c);
+    }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    streamsize sputn(const char_type* __s, streamsize __n)
+    { return xsputn(__s, __n); }
 
 protected:
     basic_streambuf();
@@ -169,15 +233,30 @@
     _LIBCPP_ALWAYS_INLINE char_type* eback() const {return __binp_;}
     _LIBCPP_ALWAYS_INLINE char_type* gptr()  const {return __ninp_;}
     _LIBCPP_ALWAYS_INLINE char_type* egptr() const {return __einp_;}
-    void gbump(int __n);
-    void setg(char_type* __gbeg, char_type* __gnext, char_type* __gend);
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    void gbump(int __n) { __ninp_ += __n; }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    void setg(char_type* __gbeg, char_type* __gnext, char_type* __gend) {
+        __binp_ = __gbeg;
+        __ninp_ = __gnext;
+        __einp_ = __gend;
+    }
 
     // 27.6.2.3.3 Put area:
     _LIBCPP_ALWAYS_INLINE char_type* pbase() const {return __bout_;}
     _LIBCPP_ALWAYS_INLINE char_type* pptr()  const {return __nout_;}
     _LIBCPP_ALWAYS_INLINE char_type* epptr() const {return __eout_;}
-    void pbump(int __n);
-    void setp(char_type* __pbeg, char_type* __pend);
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    void pbump(int __n) { __nout_ += __n; }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    void setp(char_type* __pbeg, char_type* __pend) {
+        __bout_ = __nout_ = __pbeg;
+        __eout_ = __pend;
+    }
 
     // 27.6.2.4 virtual functions:
     // 27.6.2.4.1 Locales:
@@ -220,147 +299,6 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-locale
-basic_streambuf<_CharT, _Traits>::pubimbue(const locale& __loc)
-{
-    imbue(__loc);
-    locale __r = __loc_;
-    __loc_ = __loc;
-    return __r;
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-locale
-basic_streambuf<_CharT, _Traits>::getloc() const
-{
-    return __loc_;
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_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
-typename basic_streambuf<_CharT, _Traits>::pos_type
-basic_streambuf<_CharT, _Traits>::pubseekoff(off_type __off,
-                                             ios_base::seekdir __way,
-                                             ios_base::openmode __which)
-{
-    return seekoff(__off, __way, __which);
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_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
-int
-basic_streambuf<_CharT, _Traits>::pubsync()
-{
-    return sync();
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-streamsize
-basic_streambuf<_CharT, _Traits>::in_avail()
-{
-    if (__ninp_ < __einp_)
-        return static_cast<streamsize>(__einp_ - __ninp_);
-    return showmanyc();
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-typename basic_streambuf<_CharT, _Traits>::int_type
-basic_streambuf<_CharT, _Traits>::snextc()
-{
-    if (sbumpc() == traits_type::eof())
-        return traits_type::eof();
-    return sgetc();
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-typename basic_streambuf<_CharT, _Traits>::int_type
-basic_streambuf<_CharT, _Traits>::sbumpc()
-{
-    if (__ninp_ == __einp_)
-        return uflow();
-    return traits_type::to_int_type(*__ninp_++);
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-typename basic_streambuf<_CharT, _Traits>::int_type
-basic_streambuf<_CharT, _Traits>::sgetc()
-{
-    if (__ninp_ == __einp_)
-        return underflow();
-    return traits_type::to_int_type(*__ninp_);
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_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
-typename basic_streambuf<_CharT, _Traits>::int_type
-basic_streambuf<_CharT, _Traits>::sputbackc(char_type __c)
-{
-    if (__binp_ == __ninp_ || !traits_type::eq(__c, __ninp_[-1]))
-        return pbackfail(traits_type::to_int_type(__c));
-    return traits_type::to_int_type(*--__ninp_);
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-typename basic_streambuf<_CharT, _Traits>::int_type
-basic_streambuf<_CharT, _Traits>::sungetc()
-{
-    if (__binp_ == __ninp_)
-        return pbackfail();
-    return traits_type::to_int_type(*--__ninp_);
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-typename basic_streambuf<_CharT, _Traits>::int_type
-basic_streambuf<_CharT, _Traits>::sputc(char_type __c)
-{
-    if (__nout_ == __eout_)
-        return overflow(traits_type::to_int_type(__c));
-    *__nout_++ = __c;
-    return traits_type::to_int_type(__c);
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-streamsize
-basic_streambuf<_CharT, _Traits>::sputn(const char_type* __s, streamsize __n)
-{
-    return xsputn(__s, __n);
-}
-
-template <class _CharT, class _Traits>
 basic_streambuf<_CharT, _Traits>::basic_streambuf()
     : __binp_(0),
       __ninp_(0),
@@ -411,42 +349,6 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-void
-basic_streambuf<_CharT, _Traits>::gbump(int __n)
-{
-    __ninp_ += __n;
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-void
-basic_streambuf<_CharT, _Traits>::setg(char_type* __gbeg, char_type* __gnext,
-                                                          char_type* __gend)
-{
-    __binp_ = __gbeg;
-    __ninp_ = __gnext;
-    __einp_ = __gend;
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-void
-basic_streambuf<_CharT, _Traits>::pbump(int __n)
-{
-    __nout_ += __n;
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-void
-basic_streambuf<_CharT, _Traits>::setp(char_type* __pbeg, char_type* __pend)
-{
-    __bout_ = __nout_ = __pbeg;
-    __eout_ = __pend;
-}
-
-template <class _CharT, class _Traits>
 void
 basic_streambuf<_CharT, _Traits>::imbue(const locale&)
 {
Index: include/ostream
===================================================================
--- include/ostream
+++ include/ostream
@@ -160,20 +160,24 @@
     typedef typename traits_type::off_type off_type;
 
     // 27.7.2.2 Constructor/destructor:
-    explicit basic_ostream(basic_streambuf<char_type, traits_type>* __sb);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    explicit basic_ostream(basic_streambuf<char_type, traits_type>* __sb)
+    { this->init(__sb); }
     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);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    void swap(basic_ostream& __rhs)
+    { basic_ios<char_type, traits_type>::swap(__rhs); }
 
 #ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS
     basic_ostream           (const basic_ostream& __rhs) = delete;
@@ -188,10 +192,19 @@
     class _LIBCPP_TYPE_VIS_ONLY sentry;
 
     // 27.7.2.6 Formatted output:
-    basic_ostream& operator<<(basic_ostream& (*__pf)(basic_ostream&));
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_ostream& operator<<(basic_ostream& (*__pf)(basic_ostream&))
+    { return __pf(*this); }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     basic_ostream& operator<<(basic_ios<char_type, traits_type>&
-                              (*__pf)(basic_ios<char_type,traits_type>&));
-    basic_ostream& operator<<(ios_base& (*__pf)(ios_base&));
+                              (*__pf)(basic_ios<char_type,traits_type>&))
+    { __pf(*this); return *this; }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_ostream& operator<<(ios_base& (*__pf)(ios_base&))
+    { __pf(*this); return *this; }
+
     basic_ostream& operator<<(bool __n);
     basic_ostream& operator<<(short __n);
     basic_ostream& operator<<(unsigned short __n);
@@ -213,8 +226,11 @@
     basic_ostream& flush();
 
     // 27.7.2.5 seeks:
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     pos_type tellp();
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     basic_ostream& seekp(pos_type __pos);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     basic_ostream& seekp(off_type __off, ios_base::seekdir __dir);
 
 protected:
@@ -274,24 +290,15 @@
     }
 }
 
-template <class _CharT, class _Traits>
-inline _LIBCPP_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,41 +314,6 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_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
-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
-basic_ostream<_CharT, _Traits>&
-basic_ostream<_CharT, _Traits>::operator<<(basic_ios<char_type, traits_type>&
-                                           (*__pf)(basic_ios<char_type,traits_type>&))
-{
-    __pf(*this);
-    return *this;
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-basic_ostream<_CharT, _Traits>&
-basic_ostream<_CharT, _Traits>::operator<<(ios_base& (*__pf)(ios_base&))
-{
-    __pf(*this);
-    return *this;
-}
-
-template <class _CharT, class _Traits>
 basic_ostream<_CharT, _Traits>&
 basic_ostream<_CharT, _Traits>::operator<<(basic_streambuf<char_type, traits_type>* __sb)
 {
@@ -989,7 +961,6 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
 typename basic_ostream<_CharT, _Traits>::pos_type
 basic_ostream<_CharT, _Traits>::tellp()
 {
@@ -999,7 +970,6 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
 basic_ostream<_CharT, _Traits>&
 basic_ostream<_CharT, _Traits>::seekp(pos_type __pos)
 {
@@ -1013,7 +983,6 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_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
@@ -184,19 +184,26 @@
     typedef typename traits_type::off_type off_type;
 
     // 27.7.1.1.1 Constructor/destructor:
-    explicit basic_istream(basic_streambuf<char_type, traits_type>* __sb);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    explicit basic_istream(basic_streambuf<char_type, traits_type>* __sb) : __gc_(0)
+    { this->init(__sb); }
     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);
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    void swap(basic_istream& __rhs) {
+      _VSTD::swap(__gc_, __rhs.__gc_);
+      basic_ios<char_type, traits_type>::swap(__rhs);
+    }
 
 #if _LIBCPP_STD_VER > 11
 #ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS
@@ -213,10 +220,19 @@
     class _LIBCPP_TYPE_VIS_ONLY sentry;
 
     // 27.7.1.2 Formatted input:
-    basic_istream& operator>>(basic_istream& (*__pf)(basic_istream&));
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_istream& operator>>(basic_istream& (*__pf)(basic_istream&))
+    { return __pf(*this); }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
     basic_istream& operator>>(basic_ios<char_type, traits_type>&
-                              (*__pf)(basic_ios<char_type, traits_type>&));
-    basic_istream& operator>>(ios_base& (*__pf)(ios_base&));
+                              (*__pf)(basic_ios<char_type, traits_type>&))
+    { __pf(*this); return *this; }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_istream& operator>>(ios_base& (*__pf)(ios_base&))
+    { __pf(*this); return *this; }
+
     basic_istream& operator>>(basic_streambuf<char_type, traits_type>* __sb);
     basic_istream& operator>>(bool& __n);
     basic_istream& operator>>(short& __n);
@@ -236,13 +252,31 @@
     _LIBCPP_INLINE_VISIBILITY
     streamsize gcount() const {return __gc_;}
     int_type get();
-    basic_istream& get(char_type& __c);
-    basic_istream& get(char_type* __s, streamsize __n);
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_istream& get(char_type& __c) {
+      int_type __ch = get();
+      if (__ch != traits_type::eof())
+        __c = traits_type::to_char_type(__ch);
+      return *this;
+    }
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_istream& get(char_type* __s, streamsize __n)
+    { return get(__s, __n, this->widen('\n')); }
+
     basic_istream& get(char_type* __s, streamsize __n, char_type __dlm);
-    basic_istream& get(basic_streambuf<char_type, traits_type>& __sb);
+
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_istream& get(basic_streambuf<char_type, traits_type>& __sb)
+    { return get(__sb, this->widen('\n')); }
+
     basic_istream& get(basic_streambuf<char_type, traits_type>& __sb, char_type __dlm);
 
-    basic_istream& getline(char_type* __s, streamsize __n);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    basic_istream& getline(char_type* __s, streamsize __n)
+    { return getline(__s, __n, this->widen('\n')); }
+
     basic_istream& getline(char_type* __s, streamsize __n, char_type __dlm);
 
     basic_istream& ignore(streamsize __n = 1, int_type __dlm = traits_type::eof());
@@ -303,27 +337,17 @@
         __is.setstate(ios_base::failbit);
 }
 
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-basic_istream<_CharT, _Traits>::basic_istream(basic_streambuf<char_type, traits_type>* __sb)
-    : __gc_(0)
-{
-    this->init(__sb);
-}
-
 #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,15 +363,6 @@
 }
 
 template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-void
-basic_istream<_CharT, _Traits>::swap(basic_istream& __rhs)
-{
-    _VSTD::swap(__gc_, __rhs.__gc_);
-    basic_ios<char_type, traits_type>::swap(__rhs);
-}
-
-template <class _CharT, class _Traits>
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::operator>>(unsigned short& __n)
 {
@@ -724,33 +739,6 @@
     return *this;
 }
 
-template <class _CharT, class _Traits>
-inline _LIBCPP_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
-basic_istream<_CharT, _Traits>&
-basic_istream<_CharT, _Traits>::operator>>(basic_ios<char_type, traits_type>&
-                                           (*__pf)(basic_ios<char_type, traits_type>&))
-{
-    __pf(*this);
-    return *this;
-}
-
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-basic_istream<_CharT, _Traits>&
-basic_istream<_CharT, _Traits>::operator>>(ios_base& (*__pf)(ios_base&))
-{
-    __pf(*this);
-    return *this;
-}
-
 template<class _CharT, class _Traits>
 basic_istream<_CharT, _Traits>&
 operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
@@ -947,17 +935,6 @@
 }
 
 template<class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-basic_istream<_CharT, _Traits>&
-basic_istream<_CharT, _Traits>::get(char_type& __c)
-{
-    int_type __ch = get();
-    if (__ch != traits_type::eof())
-        __c = traits_type::to_char_type(__ch);
-    return *this;
-}
-
-template<class _CharT, class _Traits>
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n, char_type __dlm)
 {
@@ -1006,14 +983,6 @@
 }
 
 template<class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-basic_istream<_CharT, _Traits>&
-basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n)
-{
-    return get(__s, __n, this->widen('\n'));
-}
-
-template<class _CharT, class _Traits>
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __sb,
                                     char_type __dlm)
@@ -1068,14 +1037,6 @@
 }
 
 template<class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-basic_istream<_CharT, _Traits>&
-basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __sb)
-{
-    return get(__sb, this->widen('\n'));
-}
-
-template<class _CharT, class _Traits>
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_type __dlm)
 {
@@ -1129,14 +1090,6 @@
 }
 
 template<class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-basic_istream<_CharT, _Traits>&
-basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n)
-{
-    return getline(__s, __n, this->widen('\n'));
-}
-
-template<class _CharT, class _Traits>
 basic_istream<_CharT, _Traits>&
 basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __dlm)
 {
@@ -1503,41 +1456,38 @@
     typedef typename traits_type::off_type off_type;
 
     // constructor/destructor
-    explicit basic_iostream(basic_streambuf<char_type, traits_type>* __sb);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    explicit basic_iostream(basic_streambuf<char_type, traits_type>* __sb)
+      : basic_istream<_CharT, _Traits>(__sb)
+    {}
+
     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);
+    inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
+    void swap(basic_iostream& __rhs)
+    { basic_istream<char_type, traits_type>::swap(__rhs); }
 public:
 };
 
-template <class _CharT, class _Traits>
-inline _LIBCPP_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)
 {
@@ -1552,14 +1502,6 @@
 {
 }
 
-template <class _CharT, class _Traits>
-inline _LIBCPP_INLINE_VISIBILITY
-void
-basic_iostream<_CharT, _Traits>::swap(basic_iostream& __rhs)
-{
-    basic_istream<char_type, traits_type>::swap(__rhs);
-}
-
 template<class _CharT, class _Traits, class _Allocator>
 basic_istream<_CharT, _Traits>&
 operator>>(basic_istream<_CharT, _Traits>& __is,
Index: include/__config
===================================================================
--- include/__config
+++ include/__config
@@ -562,6 +562,7 @@
 #define _LIBCPP_ENUM_VIS
 #define _LIBCPP_INLINE_VISIBILITY __forceinline
 #define _LIBCPP_ALWAYS_INLINE     __forceinline
+#define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __forceinline
 #endif // _WIN32
 
 #ifndef _LIBCPP_HIDDEN
@@ -616,6 +617,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
+
 #ifndef _LIBCPP_PREFERRED_OVERLOAD
 #  if __has_attribute(__enable_if__)
 #    define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, "")))
Index: docs/DesignDocs/VisibilityMacros.rst
===================================================================
--- docs/DesignDocs/VisibilityMacros.rst
+++ docs/DesignDocs/VisibilityMacros.rst
@@ -71,6 +71,16 @@
   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.
 
+**_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.
+
 **_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*.
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