Skip to content

Commit f8f31c4

Browse files
committedSep 16, 2016
[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
1 parent 6efbc73 commit f8f31c4

File tree

8 files changed

+211
-370
lines changed

8 files changed

+211
-370
lines changed
 

Diff for: ‎libcxx/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ endif()
330330
# headers
331331
add_compile_flags_if_supported(-nostdinc++)
332332

333+
add_definitions(-D_LIBCPP_BUILDING_LIBRARY)
334+
333335
# Warning flags ===============================================================
334336
add_definitions(-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
335337
add_compile_flags_if_supported(

Diff for: ‎libcxx/docs/DesignDocs/VisibilityMacros.rst

+10
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ Visibility Macros
7171
However since `_LIBCPP_TYPE_VIS_ONLY` is the same as `_LIBCPP_TYPE_VIS` the
7272
visibility is already correct. The macro has an empty definition with GCC.
7373

74+
**_LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY**
75+
Mark a member function of a class template as hidden and inline except when
76+
building the libc++ library where it marks the symbol as being exported by
77+
the library.
78+
79+
This macro is used to maintain ABI compatibility for symbols that have been
80+
historically exported by the libc++ library but are now marked inline. It
81+
should only be applied to member functions of class templates that are
82+
externally instantiated.
83+
7484
**_LIBCPP_EXCEPTION_ABI**
7585
Mark the member functions, typeinfo, and vtable of the type as being exported
7686
by the libc++ library. This macro must be applied to all *exception types*.

Diff for: ‎libcxx/include/__config

+9
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,7 @@ namespace std {
562562
#define _LIBCPP_ENUM_VIS
563563
#define _LIBCPP_INLINE_VISIBILITY __forceinline
564564
#define _LIBCPP_ALWAYS_INLINE __forceinline
565+
#define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __forceinline
565566
#endif // _WIN32
566567

567568
#ifndef _LIBCPP_HIDDEN
@@ -616,6 +617,14 @@ namespace std {
616617
#define _LIBCPP_ALWAYS_INLINE __attribute__ ((__visibility__("hidden"), __always_inline__))
617618
#endif
618619

620+
#ifndef _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
621+
# ifdef _LIBCPP_BUILDING_LIBRARY
622+
# define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY __attribute__((__visibility__("default"), __always_inline__))
623+
# else
624+
# define _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
625+
# endif
626+
#endif
627+
619628
#ifndef _LIBCPP_PREFERRED_OVERLOAD
620629
# if __has_attribute(__enable_if__)
621630
# define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, "")))

Diff for: ‎libcxx/include/istream

+55-113
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,26 @@ public:
184184
typedef typename traits_type::off_type off_type;
185185

186186
// 27.7.1.1.1 Constructor/destructor:
187-
explicit basic_istream(basic_streambuf<char_type, traits_type>* __sb);
187+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
188+
explicit basic_istream(basic_streambuf<char_type, traits_type>* __sb) : __gc_(0)
189+
{ this->init(__sb); }
188190
virtual ~basic_istream();
189191
protected:
190192
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
191-
_LIBCPP_INLINE_VISIBILITY
193+
inline _LIBCPP_INLINE_VISIBILITY
192194
basic_istream(basic_istream&& __rhs);
193195
#endif
194196
// 27.7.1.1.2 Assign/swap:
195197
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
196-
_LIBCPP_INLINE_VISIBILITY
198+
inline _LIBCPP_INLINE_VISIBILITY
197199
basic_istream& operator=(basic_istream&& __rhs);
198200
#endif
199-
void swap(basic_istream& __rhs);
201+
202+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
203+
void swap(basic_istream& __rhs) {
204+
_VSTD::swap(__gc_, __rhs.__gc_);
205+
basic_ios<char_type, traits_type>::swap(__rhs);
206+
}
200207

201208
#if _LIBCPP_STD_VER > 11
202209
#ifndef _LIBCPP_HAS_NO_DELETED_FUNCTIONS
@@ -213,10 +220,19 @@ public:
213220
class _LIBCPP_TYPE_VIS_ONLY sentry;
214221

215222
// 27.7.1.2 Formatted input:
216-
basic_istream& operator>>(basic_istream& (*__pf)(basic_istream&));
223+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
224+
basic_istream& operator>>(basic_istream& (*__pf)(basic_istream&))
225+
{ return __pf(*this); }
226+
227+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
217228
basic_istream& operator>>(basic_ios<char_type, traits_type>&
218-
(*__pf)(basic_ios<char_type, traits_type>&));
219-
basic_istream& operator>>(ios_base& (*__pf)(ios_base&));
229+
(*__pf)(basic_ios<char_type, traits_type>&))
230+
{ __pf(*this); return *this; }
231+
232+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
233+
basic_istream& operator>>(ios_base& (*__pf)(ios_base&))
234+
{ __pf(*this); return *this; }
235+
220236
basic_istream& operator>>(basic_streambuf<char_type, traits_type>* __sb);
221237
basic_istream& operator>>(bool& __n);
222238
basic_istream& operator>>(short& __n);
@@ -236,13 +252,31 @@ public:
236252
_LIBCPP_INLINE_VISIBILITY
237253
streamsize gcount() const {return __gc_;}
238254
int_type get();
239-
basic_istream& get(char_type& __c);
240-
basic_istream& get(char_type* __s, streamsize __n);
255+
256+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
257+
basic_istream& get(char_type& __c) {
258+
int_type __ch = get();
259+
if (__ch != traits_type::eof())
260+
__c = traits_type::to_char_type(__ch);
261+
return *this;
262+
}
263+
264+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
265+
basic_istream& get(char_type* __s, streamsize __n)
266+
{ return get(__s, __n, this->widen('\n')); }
267+
241268
basic_istream& get(char_type* __s, streamsize __n, char_type __dlm);
242-
basic_istream& get(basic_streambuf<char_type, traits_type>& __sb);
269+
270+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
271+
basic_istream& get(basic_streambuf<char_type, traits_type>& __sb)
272+
{ return get(__sb, this->widen('\n')); }
273+
243274
basic_istream& get(basic_streambuf<char_type, traits_type>& __sb, char_type __dlm);
244275

245-
basic_istream& getline(char_type* __s, streamsize __n);
276+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
277+
basic_istream& getline(char_type* __s, streamsize __n)
278+
{ return getline(__s, __n, this->widen('\n')); }
279+
246280
basic_istream& getline(char_type* __s, streamsize __n, char_type __dlm);
247281

248282
basic_istream& ignore(streamsize __n = 1, int_type __dlm = traits_type::eof());
@@ -303,18 +337,9 @@ basic_istream<_CharT, _Traits>::sentry::sentry(basic_istream<_CharT, _Traits>& _
303337
__is.setstate(ios_base::failbit);
304338
}
305339

306-
template <class _CharT, class _Traits>
307-
inline _LIBCPP_INLINE_VISIBILITY
308-
basic_istream<_CharT, _Traits>::basic_istream(basic_streambuf<char_type, traits_type>* __sb)
309-
: __gc_(0)
310-
{
311-
this->init(__sb);
312-
}
313-
314340
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
315341

316342
template <class _CharT, class _Traits>
317-
inline _LIBCPP_INLINE_VISIBILITY
318343
basic_istream<_CharT, _Traits>::basic_istream(basic_istream&& __rhs)
319344
: __gc_(__rhs.__gc_)
320345
{
@@ -323,7 +348,6 @@ basic_istream<_CharT, _Traits>::basic_istream(basic_istream&& __rhs)
323348
}
324349

325350
template <class _CharT, class _Traits>
326-
inline _LIBCPP_INLINE_VISIBILITY
327351
basic_istream<_CharT, _Traits>&
328352
basic_istream<_CharT, _Traits>::operator=(basic_istream&& __rhs)
329353
{
@@ -338,15 +362,6 @@ basic_istream<_CharT, _Traits>::~basic_istream()
338362
{
339363
}
340364

341-
template <class _CharT, class _Traits>
342-
inline _LIBCPP_INLINE_VISIBILITY
343-
void
344-
basic_istream<_CharT, _Traits>::swap(basic_istream& __rhs)
345-
{
346-
_VSTD::swap(__gc_, __rhs.__gc_);
347-
basic_ios<char_type, traits_type>::swap(__rhs);
348-
}
349-
350365
template <class _CharT, class _Traits>
351366
basic_istream<_CharT, _Traits>&
352367
basic_istream<_CharT, _Traits>::operator>>(unsigned short& __n)
@@ -724,33 +739,6 @@ basic_istream<_CharT, _Traits>::operator>>(int& __n)
724739
return *this;
725740
}
726741

727-
template <class _CharT, class _Traits>
728-
inline _LIBCPP_INLINE_VISIBILITY
729-
basic_istream<_CharT, _Traits>&
730-
basic_istream<_CharT, _Traits>::operator>>(basic_istream& (*__pf)(basic_istream&))
731-
{
732-
return __pf(*this);
733-
}
734-
735-
template <class _CharT, class _Traits>
736-
inline _LIBCPP_INLINE_VISIBILITY
737-
basic_istream<_CharT, _Traits>&
738-
basic_istream<_CharT, _Traits>::operator>>(basic_ios<char_type, traits_type>&
739-
(*__pf)(basic_ios<char_type, traits_type>&))
740-
{
741-
__pf(*this);
742-
return *this;
743-
}
744-
745-
template <class _CharT, class _Traits>
746-
inline _LIBCPP_INLINE_VISIBILITY
747-
basic_istream<_CharT, _Traits>&
748-
basic_istream<_CharT, _Traits>::operator>>(ios_base& (*__pf)(ios_base&))
749-
{
750-
__pf(*this);
751-
return *this;
752-
}
753-
754742
template<class _CharT, class _Traits>
755743
basic_istream<_CharT, _Traits>&
756744
operator>>(basic_istream<_CharT, _Traits>& __is, _CharT* __s)
@@ -946,17 +934,6 @@ basic_istream<_CharT, _Traits>::get()
946934
return __r;
947935
}
948936

949-
template<class _CharT, class _Traits>
950-
inline _LIBCPP_INLINE_VISIBILITY
951-
basic_istream<_CharT, _Traits>&
952-
basic_istream<_CharT, _Traits>::get(char_type& __c)
953-
{
954-
int_type __ch = get();
955-
if (__ch != traits_type::eof())
956-
__c = traits_type::to_char_type(__ch);
957-
return *this;
958-
}
959-
960937
template<class _CharT, class _Traits>
961938
basic_istream<_CharT, _Traits>&
962939
basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n, char_type __dlm)
@@ -1005,14 +982,6 @@ basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n, char_type __
1005982
return *this;
1006983
}
1007984

1008-
template<class _CharT, class _Traits>
1009-
inline _LIBCPP_INLINE_VISIBILITY
1010-
basic_istream<_CharT, _Traits>&
1011-
basic_istream<_CharT, _Traits>::get(char_type* __s, streamsize __n)
1012-
{
1013-
return get(__s, __n, this->widen('\n'));
1014-
}
1015-
1016985
template<class _CharT, class _Traits>
1017986
basic_istream<_CharT, _Traits>&
1018987
basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __sb,
@@ -1067,14 +1036,6 @@ basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __s
10671036
return *this;
10681037
}
10691038

1070-
template<class _CharT, class _Traits>
1071-
inline _LIBCPP_INLINE_VISIBILITY
1072-
basic_istream<_CharT, _Traits>&
1073-
basic_istream<_CharT, _Traits>::get(basic_streambuf<char_type, traits_type>& __sb)
1074-
{
1075-
return get(__sb, this->widen('\n'));
1076-
}
1077-
10781039
template<class _CharT, class _Traits>
10791040
basic_istream<_CharT, _Traits>&
10801041
basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_type __dlm)
@@ -1128,14 +1089,6 @@ basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n, char_typ
11281089
return *this;
11291090
}
11301091

1131-
template<class _CharT, class _Traits>
1132-
inline _LIBCPP_INLINE_VISIBILITY
1133-
basic_istream<_CharT, _Traits>&
1134-
basic_istream<_CharT, _Traits>::getline(char_type* __s, streamsize __n)
1135-
{
1136-
return getline(__s, __n, this->widen('\n'));
1137-
}
1138-
11391092
template<class _CharT, class _Traits>
11401093
basic_istream<_CharT, _Traits>&
11411094
basic_istream<_CharT, _Traits>::ignore(streamsize __n, int_type __dlm)
@@ -1503,41 +1456,38 @@ public:
15031456
typedef typename traits_type::off_type off_type;
15041457

15051458
// constructor/destructor
1506-
explicit basic_iostream(basic_streambuf<char_type, traits_type>* __sb);
1459+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
1460+
explicit basic_iostream(basic_streambuf<char_type, traits_type>* __sb)
1461+
: basic_istream<_CharT, _Traits>(__sb)
1462+
{}
1463+
15071464
virtual ~basic_iostream();
15081465
protected:
15091466
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1510-
_LIBCPP_INLINE_VISIBILITY
1467+
inline _LIBCPP_INLINE_VISIBILITY
15111468
basic_iostream(basic_iostream&& __rhs);
15121469
#endif
15131470

15141471
// assign/swap
15151472
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1516-
_LIBCPP_INLINE_VISIBILITY
1473+
inline _LIBCPP_INLINE_VISIBILITY
15171474
basic_iostream& operator=(basic_iostream&& __rhs);
15181475
#endif
1519-
void swap(basic_iostream& __rhs);
1476+
inline _LIBCPP_EXTERN_TEMPLATE_INLINE_VISIBILITY
1477+
void swap(basic_iostream& __rhs)
1478+
{ basic_istream<char_type, traits_type>::swap(__rhs); }
15201479
public:
15211480
};
15221481

1523-
template <class _CharT, class _Traits>
1524-
inline _LIBCPP_INLINE_VISIBILITY
1525-
basic_iostream<_CharT, _Traits>::basic_iostream(basic_streambuf<char_type, traits_type>* __sb)
1526-
: basic_istream<_CharT, _Traits>(__sb)
1527-
{
1528-
}
1529-
15301482
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
15311483

15321484
template <class _CharT, class _Traits>
1533-
inline _LIBCPP_INLINE_VISIBILITY
15341485
basic_iostream<_CharT, _Traits>::basic_iostream(basic_iostream&& __rhs)
15351486
: basic_istream<_CharT, _Traits>(_VSTD::move(__rhs))
15361487
{
15371488
}
15381489

15391490
template <class _CharT, class _Traits>
1540-
inline _LIBCPP_INLINE_VISIBILITY
15411491
basic_iostream<_CharT, _Traits>&
15421492
basic_iostream<_CharT, _Traits>::operator=(basic_iostream&& __rhs)
15431493
{
@@ -1552,14 +1502,6 @@ basic_iostream<_CharT, _Traits>::~basic_iostream()
15521502
{
15531503
}
15541504

1555-
template <class _CharT, class _Traits>
1556-
inline _LIBCPP_INLINE_VISIBILITY
1557-
void
1558-
basic_iostream<_CharT, _Traits>::swap(basic_iostream& __rhs)
1559-
{
1560-
basic_istream<char_type, traits_type>::swap(__rhs);
1561-
}
1562-
15631505
template<class _CharT, class _Traits, class _Allocator>
15641506
basic_istream<_CharT, _Traits>&
15651507
operator>>(basic_istream<_CharT, _Traits>& __is,

0 commit comments

Comments
 (0)
Please sign in to comment.