diff --git a/libcxx/.clang-format b/libcxx/.clang-format index a6154c7c4a2bc..e25196a05c92c 100644 --- a/libcxx/.clang-format +++ b/libcxx/.clang-format @@ -37,7 +37,6 @@ AttributeMacros: [ '_LIBCPP_HIDDEN', '_LIBCPP_HIDE_FROM_ABI_AFTER_V1', '_LIBCPP_HIDE_FROM_ABI', - '_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS', '_LIBCPP_NO_SANITIZE', '_LIBCPP_NO_UNIQUE_ADDRESS', '_LIBCPP_NOALIAS', diff --git a/libcxx/docs/DesignDocs/VisibilityMacros.rst b/libcxx/docs/DesignDocs/VisibilityMacros.rst index 83a9a62942bc9..e37e712014c08 100644 --- a/libcxx/docs/DesignDocs/VisibilityMacros.rst +++ b/libcxx/docs/DesignDocs/VisibilityMacros.rst @@ -105,35 +105,6 @@ Visibility Macros the extern template declaration) as exported on Windows, as discussed above. On all other platforms, this macro has an empty definition. -**_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS** - Mark a symbol as hidden so it will not be exported from shared libraries. This - is intended specifically for method templates of either classes marked with - `_LIBCPP_TYPE_VIS` or classes with an extern template instantiation - declaration marked with `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS`. - - When building libc++ with hidden visibility, we want explicit template - instantiations to export members, which is consistent with existing Windows - behavior. We also want classes annotated with `_LIBCPP_TYPE_VIS` to export - their members, which is again consistent with existing Windows behavior. - Both these changes are necessary for clients to be able to link against a - libc++ DSO built with hidden visibility without encountering missing symbols. - - An unfortunate side effect, however, is that method templates of classes - either marked `_LIBCPP_TYPE_VIS` or with extern template instantiation - declarations marked with `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` also get default - visibility when instantiated. These methods are often implicitly instantiated - inside other libraries which use the libc++ headers, and will therefore end up - being exported from those libraries, since those implicit instantiations will - receive default visibility. This is not acceptable for libraries that wish to - control their visibility, and led to PR30642. - - Consequently, all such problematic method templates are explicitly marked - either hidden (via this macro) or inline, so that they don't leak into client - libraries. The problematic methods were found by running - `bad-visibility-finder `_ - against the libc++ headers after making `_LIBCPP_TYPE_VIS` and - `_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS` expand to default visibility. - Links ===== diff --git a/libcxx/include/__condition_variable/condition_variable.h b/libcxx/include/__condition_variable/condition_variable.h index 82ecb804669e6..1e8edd5dcb009 100644 --- a/libcxx/include/__condition_variable/condition_variable.h +++ b/libcxx/include/__condition_variable/condition_variable.h @@ -39,60 +39,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_DECLARE_STRONG_ENUM(cv_status){no_timeout, timeout}; _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status) -class _LIBCPP_EXPORTED_FROM_ABI condition_variable { - __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; - -public: - _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; - -# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION - ~condition_variable() = default; -# else - ~condition_variable(); -# endif - - condition_variable(const condition_variable&) = delete; - condition_variable& operator=(const condition_variable&) = delete; - - void notify_one() _NOEXCEPT; - void notify_all() _NOEXCEPT; - - void wait(unique_lock& __lk) _NOEXCEPT; - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(unique_lock& __lk, _Predicate __pred); - - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status - wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t); - - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool - wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred); - - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status - wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d); - - template - bool _LIBCPP_HIDE_FROM_ABI - wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); - - typedef __libcpp_condvar_t* native_handle_type; - _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; } - -private: - void - __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; -# if _LIBCPP_HAS_COND_CLOCKWAIT - _LIBCPP_HIDE_FROM_ABI void - __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; -# endif - template - _LIBCPP_HIDE_FROM_ABI void - __do_timed_wait(unique_lock& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; -}; -#endif // _LIBCPP_HAS_THREADS - template ::value, int> = 0> inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) { using namespace chrono; @@ -140,64 +86,106 @@ inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono:: return nanoseconds(__result); } -#if _LIBCPP_HAS_THREADS -template -void condition_variable::wait(unique_lock& __lk, _Predicate __pred) { - while (!__pred()) - wait(__lk); -} +class _LIBCPP_EXPORTED_FROM_ABI condition_variable { + __libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER; -template -cv_status condition_variable::wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t) { - using namespace chrono; - using __clock_tp_ns = time_point<_Clock, nanoseconds>; +public: + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default; - typename _Clock::time_point __now = _Clock::now(); - if (__t <= __now) - return cv_status::timeout; +# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION + ~condition_variable() = default; +# else + ~condition_variable(); +# endif - __clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch())); + condition_variable(const condition_variable&) = delete; + condition_variable& operator=(const condition_variable&) = delete; - __do_timed_wait(__lk, __t_ns); - return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; -} + void notify_one() _NOEXCEPT; + void notify_all() _NOEXCEPT; + + void wait(unique_lock& __lk) _NOEXCEPT; -template -bool condition_variable::wait_until( - unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) { - while (!__pred()) { - if (wait_until(__lk, __t) == cv_status::timeout) - return __pred(); + template + _LIBCPP_HIDE_FROM_ABI void wait(unique_lock& __lk, _Predicate __pred) { + while (!__pred()) + wait(__lk); } - return true; -} -template -cv_status condition_variable::wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d) { - using namespace chrono; - if (__d <= __d.zero()) - return cv_status::timeout; - using __ns_rep = nanoseconds::rep; - steady_clock::time_point __c_now = steady_clock::now(); + template + _LIBCPP_HIDE_FROM_ABI cv_status + wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t) { + using namespace chrono; + using __clock_tp_ns = time_point<_Clock, nanoseconds>; + + typename _Clock::time_point __now = _Clock::now(); + if (__t <= __now) + return cv_status::timeout; + + __clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch())); + + __do_timed_wait(__lk, __t_ns); + return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout; + } + + template + _LIBCPP_HIDE_FROM_ABI bool + wait_until(unique_lock& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) { + while (!__pred()) { + if (wait_until(__lk, __t) == cv_status::timeout) + return __pred(); + } + return true; + } + + template + _LIBCPP_HIDE_FROM_ABI cv_status wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d) { + using namespace chrono; + if (__d <= __d.zero()) + return cv_status::timeout; + using __ns_rep = nanoseconds::rep; + steady_clock::time_point __c_now = steady_clock::now(); # if _LIBCPP_HAS_COND_CLOCKWAIT - using __clock_tp_ns = time_point; - __ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); + using __clock_tp_ns = time_point; + __ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count(); # else - using __clock_tp_ns = time_point; - __ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); + using __clock_tp_ns = time_point; + __ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count(); # endif - __ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count(); + __ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count(); - if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { - __do_timed_wait(__lk, __clock_tp_ns::max()); - } else { - __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); + if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) { + __do_timed_wait(__lk, __clock_tp_ns::max()); + } else { + __do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count))); + } + + return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout; } - return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout; -} + template + bool _LIBCPP_HIDE_FROM_ABI + wait_for(unique_lock& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred); + + typedef __libcpp_condvar_t* native_handle_type; + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; } + +private: + void + __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; +# if _LIBCPP_HAS_COND_CLOCKWAIT + _LIBCPP_HIDE_FROM_ABI void + __do_timed_wait(unique_lock& __lk, chrono::time_point) _NOEXCEPT; +# endif + template + _LIBCPP_HIDE_FROM_ABI void + __do_timed_wait(unique_lock& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT; +}; +#endif // _LIBCPP_HAS_THREADS + +#if _LIBCPP_HAS_THREADS template inline bool diff --git a/libcxx/include/__config b/libcxx/include/__config index ce8bc38acfe3e..854746a157235 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -383,7 +383,6 @@ typedef __char32_t char32_t; # endif # define _LIBCPP_HIDDEN -# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS # define _LIBCPP_TEMPLATE_VIS # define _LIBCPP_TEMPLATE_DATA_VIS # define _LIBCPP_NAMESPACE_VISIBILITY @@ -407,13 +406,6 @@ typedef __char32_t char32_t; # define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_VISIBILITY("default") # endif -# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) -// The inline should be removed once PR32114 is resolved -# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS inline _LIBCPP_HIDDEN -# else -# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS -# endif - // This is kept to avoid a huge library-wide diff in the first step. // TODO: Remove this in a follow-up patch # define _LIBCPP_TEMPLATE_VIS diff --git a/libcxx/include/__locale b/libcxx/include/__locale index 47323046fab38..f01ab4e719ca8 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -45,6 +45,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD class _LIBCPP_EXPORTED_FROM_ABI locale; +template +class collate; + template _LIBCPP_HIDE_FROM_ABI bool has_facet(const locale&) _NOEXCEPT; @@ -84,7 +87,12 @@ public: const locale& operator=(const locale&) _NOEXCEPT; template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS locale combine(const locale&) const; + _LIBCPP_HIDE_FROM_ABI locale combine(const locale& __other) const { + if (!std::has_facet<_Facet>(__other)) + __throw_runtime_error("locale::combine: locale missing facet"); + + return locale(*this, std::addressof(const_cast<_Facet&>(std::use_facet<_Facet>(__other)))); + } // locale operations: string name() const; @@ -93,8 +101,11 @@ public: _LIBCPP_HIDE_FROM_ABI bool operator!=(const locale& __y) const { return !(*this == __y); } # endif template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool - operator()(const basic_string<_CharT, _Traits, _Allocator>&, const basic_string<_CharT, _Traits, _Allocator>&) const; + _LIBCPP_HIDE_FROM_ABI bool operator()(const basic_string<_CharT, _Traits, _Allocator>& __x, + const basic_string<_CharT, _Traits, _Allocator>& __y) const { + return std::use_facet >(*this).compare( + __x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size()) < 0; + } // global locale objects: static locale global(const locale&); @@ -155,14 +166,6 @@ inline _LIBCPP_HIDE_FROM_ABI locale::locale(const locale& __other, _Facet* __f) __install_ctor(__other, __f, __f ? __f->id.__get() : 0); } -template -locale locale::combine(const locale& __other) const { - if (!std::has_facet<_Facet>(__other)) - std::__throw_runtime_error("locale::combine: locale missing facet"); - - return locale(*this, std::addressof(const_cast<_Facet&>(std::use_facet<_Facet>(__other)))); -} - template inline _LIBCPP_HIDE_FROM_ABI bool has_facet(const locale& __l) _NOEXCEPT { return __l.has_facet(_Facet::id); @@ -289,13 +292,6 @@ protected: }; # endif -template -bool locale::operator()(const basic_string<_CharT, _Traits, _Allocator>& __x, - const basic_string<_CharT, _Traits, _Allocator>& __y) const { - return std::use_facet >(*this).compare( - __x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size()) < 0; -} - // template class ctype class _LIBCPP_EXPORTED_FROM_ABI ctype_base { diff --git a/libcxx/include/__thread/thread.h b/libcxx/include/__thread/thread.h index 5e22013dec49f..5aae50710bbfc 100644 --- a/libcxx/include/__thread/thread.h +++ b/libcxx/include/__thread/thread.h @@ -152,47 +152,6 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) { } # endif // _LIBCPP_HAS_LOCALIZATION -class _LIBCPP_EXPORTED_FROM_ABI thread { - __libcpp_thread_t __t_; - - thread(const thread&); - thread& operator=(const thread&); - -public: - typedef __thread_id id; - typedef __libcpp_thread_t native_handle_type; - - _LIBCPP_HIDE_FROM_ABI thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} -# ifndef _LIBCPP_CXX03_LANG - template , thread>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp&& __f, _Args&&... __args); -# else // _LIBCPP_CXX03_LANG - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS explicit thread(_Fp __f); -# endif - ~thread(); - - _LIBCPP_HIDE_FROM_ABI thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { __t.__t_ = _LIBCPP_NULL_THREAD; } - - _LIBCPP_HIDE_FROM_ABI thread& operator=(thread&& __t) _NOEXCEPT { - if (!__libcpp_thread_isnull(&__t_)) - terminate(); - __t_ = __t.__t_; - __t.__t_ = _LIBCPP_NULL_THREAD; - return *this; - } - - _LIBCPP_HIDE_FROM_ABI void swap(thread& __t) _NOEXCEPT { std::swap(__t_, __t.__t_); } - - _LIBCPP_HIDE_FROM_ABI bool joinable() const _NOEXCEPT { return !__libcpp_thread_isnull(&__t_); } - void join(); - void detach(); - _LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); } - _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; } - - static unsigned hardware_concurrency() _NOEXCEPT; -}; - # ifndef _LIBCPP_CXX03_LANG template @@ -210,19 +169,6 @@ _LIBCPP_HIDE_FROM_ABI void* __thread_proxy(void* __vp) { return nullptr; } -template , thread>::value, int> > -thread::thread(_Fp&& __f, _Args&&... __args) { - typedef unique_ptr<__thread_struct> _TSPtr; - _TSPtr __tsp(new __thread_struct); - typedef tuple<_TSPtr, __decay_t<_Fp>, __decay_t<_Args>...> _Gp; - unique_ptr<_Gp> __p(new _Gp(std::move(__tsp), std::forward<_Fp>(__f), std::forward<_Args>(__args)...)); - int __ec = std::__libcpp_thread_create(&__t_, std::addressof(__thread_proxy<_Gp>), __p.get()); - if (__ec == 0) - __p.release(); - else - std::__throw_system_error(__ec, "thread constructor failed"); -} - # else // _LIBCPP_CXX03_LANG template @@ -243,20 +189,69 @@ _LIBCPP_HIDE_FROM_ABI void* __thread_proxy_cxx03(void* __vp) { return nullptr; } -template -thread::thread(_Fp __f) { - typedef __thread_invoke_pair<_Fp> _InvokePair; - typedef unique_ptr<_InvokePair> _PairPtr; - _PairPtr __pp(new _InvokePair(__f)); - int __ec = std::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); - if (__ec == 0) - __pp.release(); - else - std::__throw_system_error(__ec, "thread constructor failed"); -} - # endif // _LIBCPP_CXX03_LANG +class _LIBCPP_EXPORTED_FROM_ABI thread { + __libcpp_thread_t __t_; + + thread(const thread&); + thread& operator=(const thread&); + +public: + typedef __thread_id id; + typedef __libcpp_thread_t native_handle_type; + + _LIBCPP_HIDE_FROM_ABI thread() _NOEXCEPT : __t_(_LIBCPP_NULL_THREAD) {} + +# ifndef _LIBCPP_CXX03_LANG + template , thread>::value, int> = 0> + _LIBCPP_HIDE_FROM_ABI explicit thread(_Fp&& __f, _Args&&... __args) { + typedef unique_ptr<__thread_struct> _TSPtr; + _TSPtr __tsp(new __thread_struct); + typedef tuple<_TSPtr, __decay_t<_Fp>, __decay_t<_Args>...> _Gp; + unique_ptr<_Gp> __p(new _Gp(std::move(__tsp), std::forward<_Fp>(__f), std::forward<_Args>(__args)...)); + int __ec = std::__libcpp_thread_create(&__t_, std::addressof(__thread_proxy<_Gp>), __p.get()); + if (__ec == 0) + __p.release(); + else + __throw_system_error(__ec, "thread constructor failed"); + } +# else // _LIBCPP_CXX03_LANG + template + _LIBCPP_HIDE_FROM_ABI explicit thread(_Fp __f) { + typedef __thread_invoke_pair<_Fp> _InvokePair; + typedef unique_ptr<_InvokePair> _PairPtr; + _PairPtr __pp(new _InvokePair(__f)); + int __ec = std::__libcpp_thread_create(&__t_, &__thread_proxy_cxx03<_InvokePair>, __pp.get()); + if (__ec == 0) + __pp.release(); + else + __throw_system_error(__ec, "thread constructor failed"); + } +# endif + ~thread(); + + _LIBCPP_HIDE_FROM_ABI thread(thread&& __t) _NOEXCEPT : __t_(__t.__t_) { __t.__t_ = _LIBCPP_NULL_THREAD; } + + _LIBCPP_HIDE_FROM_ABI thread& operator=(thread&& __t) _NOEXCEPT { + if (!__libcpp_thread_isnull(&__t_)) + terminate(); + __t_ = __t.__t_; + __t.__t_ = _LIBCPP_NULL_THREAD; + return *this; + } + + _LIBCPP_HIDE_FROM_ABI void swap(thread& __t) _NOEXCEPT { std::swap(__t_, __t.__t_); } + + _LIBCPP_HIDE_FROM_ABI bool joinable() const _NOEXCEPT { return !__libcpp_thread_isnull(&__t_); } + void join(); + void detach(); + _LIBCPP_HIDE_FROM_ABI id get_id() const _NOEXCEPT { return __libcpp_thread_get_id(&__t_); } + _LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() _NOEXCEPT { return __t_; } + + static unsigned hardware_concurrency() _NOEXCEPT; +}; + inline _LIBCPP_HIDE_FROM_ABI void swap(thread& __x, thread& __y) _NOEXCEPT { __x.swap(__y); } #endif // _LIBCPP_HAS_THREADS diff --git a/libcxx/include/condition_variable b/libcxx/include/condition_variable index 81699bf6adbf7..7f44990547f55 100644 --- a/libcxx/include/condition_variable +++ b/libcxx/include/condition_variable @@ -147,6 +147,21 @@ _LIBCPP_PUSH_MACROS _LIBCPP_BEGIN_NAMESPACE_STD +template +struct __unlock_guard { + _Lock& __lock_; + + _LIBCPP_HIDE_FROM_ABI __unlock_guard(_Lock& __lock) : __lock_(__lock) { __lock_.unlock(); } + + _LIBCPP_HIDE_FROM_ABI ~__unlock_guard() _NOEXCEPT // turns exception to std::terminate + { + __lock_.lock(); + } + + __unlock_guard(const __unlock_guard&) = delete; + __unlock_guard& operator=(const __unlock_guard&) = delete; +}; + class _LIBCPP_EXPORTED_FROM_ABI condition_variable_any { condition_variable __cv_; shared_ptr __mut_; @@ -158,13 +173,25 @@ public: _LIBCPP_HIDE_FROM_ABI void notify_all() _NOEXCEPT; template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(_Lock& __lock); + _LIBCPP_HIDE_FROM_ABI void wait(_Lock& __lock) { + shared_ptr __mut = __mut_; + unique_lock __lk(*__mut); + __unlock_guard<_Lock> __unlock(__lock); + lock_guard > __lx(__lk, adopt_lock_t()); + __cv_.wait(__lk); + } // __mut_.unlock(), __lock.lock() + template _LIBCPP_HIDE_FROM_ABI void wait(_Lock& __lock, _Predicate __pred); template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status - wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t); + _LIBCPP_HIDE_FROM_ABI cv_status wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t) { + shared_ptr __mut = __mut_; + unique_lock __lk(*__mut); + __unlock_guard<_Lock> __unlock(__lock); + lock_guard > __lx(__lk, adopt_lock_t()); + return __cv_.wait_until(__lk, __t); + } // __mut_.unlock(), __lock.lock() template bool _LIBCPP_HIDE_FROM_ABI @@ -204,45 +231,12 @@ inline void condition_variable_any::notify_all() _NOEXCEPT { __cv_.notify_all(); } -template -struct __unlock_guard { - _Lock& __lock_; - - _LIBCPP_HIDE_FROM_ABI __unlock_guard(_Lock& __lock) : __lock_(__lock) { __lock_.unlock(); } - - _LIBCPP_HIDE_FROM_ABI ~__unlock_guard() _NOEXCEPT // turns exception to std::terminate - { - __lock_.lock(); - } - - __unlock_guard(const __unlock_guard&) = delete; - __unlock_guard& operator=(const __unlock_guard&) = delete; -}; - -template -void condition_variable_any::wait(_Lock& __lock) { - shared_ptr __mut = __mut_; - unique_lock __lk(*__mut); - __unlock_guard<_Lock> __unlock(__lock); - lock_guard > __lx(__lk, adopt_lock_t()); - __cv_.wait(__lk); -} // __mut_.unlock(), __lock.lock() - template inline void condition_variable_any::wait(_Lock& __lock, _Predicate __pred) { while (!__pred()) wait(__lock); } -template -cv_status condition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t) { - shared_ptr __mut = __mut_; - unique_lock __lk(*__mut); - __unlock_guard<_Lock> __unlock(__lock); - lock_guard > __lx(__lk, adopt_lock_t()); - return __cv_.wait_until(__lk, __t); -} // __mut_.unlock(), __lock.lock() - template inline bool condition_variable_any::wait_until(_Lock& __lock, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) { diff --git a/libcxx/include/future b/libcxx/include/future index a08687485bd99..ea1eb65e332f7 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -563,24 +563,20 @@ public: template future_status _LIBCPP_HIDE_FROM_ABI wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const; template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS future_status - wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const; + _LIBCPP_HIDE_FROM_ABI future_status wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { + unique_lock __lk(__mut_); + if (__state_ & deferred) + return future_status::deferred; + while (!(__state_ & ready) && _Clock::now() < __abs_time) + __cv_.wait_until(__lk, __abs_time); + if (__state_ & ready) + return future_status::ready; + return future_status::timeout; + } virtual void __execute(); }; -template -future_status __assoc_sub_state::wait_until(const chrono::time_point<_Clock, _Duration>& __abs_time) const { - unique_lock __lk(__mut_); - if (__state_ & deferred) - return future_status::deferred; - while (!(__state_ & ready) && _Clock::now() < __abs_time) - __cv_.wait_until(__lk, __abs_time); - if (__state_ & ready) - return future_status::ready; - return future_status::timeout; -} - template inline future_status __assoc_sub_state::wait_for(const chrono::duration<_Rep, _Period>& __rel_time) const { return wait_until(chrono::steady_clock::now() + __rel_time); @@ -1347,8 +1343,17 @@ class _LIBCPP_EXPORTED_FROM_ABI promise { public: promise(); - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS promise(allocator_arg_t, const _Allocator& __a); + template + _LIBCPP_HIDE_FROM_ABI promise(allocator_arg_t, const _Alloc& __a0) { + typedef __assoc_sub_state_alloc<_Alloc> _State; + typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; + typedef __allocator_destructor<_A2> _D2; + _A2 __a(__a0); + unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); + ::new ((void*)std::addressof(*__hold.get())) _State(__a0); + __state_ = std::addressof(*__hold.release()); + } + _LIBCPP_HIDE_FROM_ABI promise(promise&& __rhs) _NOEXCEPT : __state_(__rhs.__state_) { __rhs.__state_ = nullptr; } promise(const promise& __rhs) = delete; ~promise(); @@ -1374,17 +1379,6 @@ public: void set_exception_at_thread_exit(exception_ptr __p); }; -template -promise::promise(allocator_arg_t, const _Alloc& __a0) { - typedef __assoc_sub_state_alloc<_Alloc> _State; - typedef typename __allocator_traits_rebind<_Alloc, _State>::type _A2; - typedef __allocator_destructor<_A2> _D2; - _A2 __a(__a0); - unique_ptr<_State, _D2> __hold(__a.allocate(1), _D2(__a, 1)); - ::new ((void*)std::addressof(*__hold.get())) _State(__a0); - __state_ = std::addressof(*__hold.release()); -} - template inline _LIBCPP_HIDE_FROM_ABI void swap(promise<_Rp>& __x, promise<_Rp>& __y) _NOEXCEPT { __x.swap(__y); diff --git a/libcxx/include/locale b/libcxx/include/locale index fa15302223202..3afdef856ede7 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -566,6 +566,104 @@ extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; extern template struct _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __num_get; # endif +template +_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2); + +template <> +inline _LIBCPP_HIDE_FROM_ABI float __do_strtod(const char* __a, char** __p2) { + return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_HIDE_FROM_ABI double __do_strtod(const char* __a, char** __p2) { + return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod(const char* __a, char** __p2) { + return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) { + if (__a != __a_end) { + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + _Tp __ld = std::__do_strtod<_Tp>(__a, &__p2); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE) + __err = ios_base::failbit; + return __ld; + } + __err = ios_base::failbit; + return 0; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { + if (__a != __a_end) { + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) { + __err = ios_base::failbit; + if (__ll > 0) + return numeric_limits<_Tp>::max(); + else + return numeric_limits<_Tp>::min(); + } + return static_cast<_Tp>(__ll); + } + __err = ios_base::failbit; + return 0; +} + +template +_LIBCPP_HIDE_FROM_ABI _Tp +__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { + if (__a != __a_end) { + const bool __negate = *__a == '-'; + if (__negate && ++__a == __a_end) { + __err = ios_base::failbit; + return 0; + } + __libcpp_remove_reference_t __save_errno = errno; + errno = 0; + char* __p2; + unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); + __libcpp_remove_reference_t __current_errno = errno; + if (__current_errno == 0) + errno = __save_errno; + if (__p2 != __a_end) { + __err = ios_base::failbit; + return 0; + } else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) { + __err = ios_base::failbit; + return numeric_limits<_Tp>::max(); + } + _Tp __res = static_cast<_Tp>(__ll); + if (__negate) + __res = -__res; + return __res; + } + __err = ios_base::failbit; + return 0; +} + template > class _LIBCPP_TEMPLATE_VIS num_get : public locale::facet, private __num_get<_CharT> { public: @@ -635,16 +733,175 @@ protected: _LIBCPP_HIDE_FROM_ABI_VIRTUAL ~num_get() override {} template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type - __do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const; + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_floating_point(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const { + // Stage 1, nothing to do + // Stage 2 + char_type __atoms[__num_get_base::__fp_chr_cnt]; + char_type __decimal_point; + char_type __thousands_sep; + string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + bool __in_units = true; + char __exp = 'E'; + bool __is_leading_parsed = false; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_float_loop( + *__b, + __in_units, + __exp, + __a, + __a_end, + __decimal_point, + __thousands_sep, + __grouping, + __g, + __g_end, + __dc, + __atoms)) + break; + + // the leading character excluding the sign must be a decimal digit + if (!__is_leading_parsed) { + if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') { + if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.') + __is_leading_parsed = true; + else + break; + } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) { + if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.') + __is_leading_parsed = true; + else + break; + } + } + } + if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_float<_Fp>(__a, __a_end, __err); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type - __do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const; + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_signed(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const { + // Stage 1 + int __base = this->__get_base(__iob); + // Stage 2 + char_type __thousands_sep; + const int __atoms_size = __num_get_base::__int_chr_cnt; + char_type __atoms1[__atoms_size]; + const char_type* __atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) + break; + } + if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS iter_type - __do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const; + _LIBCPP_HIDE_FROM_ABI iter_type + __do_get_unsigned(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const { + // Stage 1 + int __base = this->__get_base(__iob); + // Stage 2 + char_type __thousands_sep; + const int __atoms_size = __num_get_base::__int_chr_cnt; + char_type __atoms1[__atoms_size]; + const char_type* __atoms = this->__do_widen(__iob, __atoms1); + string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); + string __buf; + __buf.resize(__buf.capacity()); + char* __a = &__buf[0]; + char* __a_end = __a; + unsigned __g[__num_get_base::__num_get_buf_sz]; + unsigned* __g_end = __g; + unsigned __dc = 0; + for (; __b != __e; ++__b) { + if (__a_end == __a + __buf.size()) { + size_t __tmp = __buf.size(); + __buf.resize(2 * __buf.size()); + __buf.resize(__buf.capacity()); + __a = &__buf[0]; + __a_end = __a + __tmp; + } + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) + break; + } + if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) + *__g_end++ = __dc; + // Stage 3 + __v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); + // Digit grouping checked + __check_grouping(__grouping, __g, __g_end, __err); + // EOF checked + if (__b == __e) + __err |= ios_base::eofbit; + return __b; + } virtual iter_type do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const; @@ -696,104 +953,6 @@ protected: template locale::id num_get<_CharT, _InputIterator>::id; -template -_LIBCPP_HIDE_FROM_ABI _Tp -__num_get_signed_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { - if (__a != __a_end) { - __libcpp_remove_reference_t __save_errno = errno; - errno = 0; - char* __p2; - long long __ll = __locale::__strtoll(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); - __libcpp_remove_reference_t __current_errno = errno; - if (__current_errno == 0) - errno = __save_errno; - if (__p2 != __a_end) { - __err = ios_base::failbit; - return 0; - } else if (__current_errno == ERANGE || __ll < numeric_limits<_Tp>::min() || numeric_limits<_Tp>::max() < __ll) { - __err = ios_base::failbit; - if (__ll > 0) - return numeric_limits<_Tp>::max(); - else - return numeric_limits<_Tp>::min(); - } - return static_cast<_Tp>(__ll); - } - __err = ios_base::failbit; - return 0; -} - -template -_LIBCPP_HIDE_FROM_ABI _Tp -__num_get_unsigned_integral(const char* __a, const char* __a_end, ios_base::iostate& __err, int __base) { - if (__a != __a_end) { - const bool __negate = *__a == '-'; - if (__negate && ++__a == __a_end) { - __err = ios_base::failbit; - return 0; - } - __libcpp_remove_reference_t __save_errno = errno; - errno = 0; - char* __p2; - unsigned long long __ll = __locale::__strtoull(__a, &__p2, __base, _LIBCPP_GET_C_LOCALE); - __libcpp_remove_reference_t __current_errno = errno; - if (__current_errno == 0) - errno = __save_errno; - if (__p2 != __a_end) { - __err = ios_base::failbit; - return 0; - } else if (__current_errno == ERANGE || numeric_limits<_Tp>::max() < __ll) { - __err = ios_base::failbit; - return numeric_limits<_Tp>::max(); - } - _Tp __res = static_cast<_Tp>(__ll); - if (__negate) - __res = -__res; - return __res; - } - __err = ios_base::failbit; - return 0; -} - -template -_LIBCPP_HIDE_FROM_ABI _Tp __do_strtod(const char* __a, char** __p2); - -template <> -inline _LIBCPP_HIDE_FROM_ABI float __do_strtod(const char* __a, char** __p2) { - return __locale::__strtof(__a, __p2, _LIBCPP_GET_C_LOCALE); -} - -template <> -inline _LIBCPP_HIDE_FROM_ABI double __do_strtod(const char* __a, char** __p2) { - return __locale::__strtod(__a, __p2, _LIBCPP_GET_C_LOCALE); -} - -template <> -inline _LIBCPP_HIDE_FROM_ABI long double __do_strtod(const char* __a, char** __p2) { - return __locale::__strtold(__a, __p2, _LIBCPP_GET_C_LOCALE); -} - -template -_LIBCPP_HIDE_FROM_ABI _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) { - if (__a != __a_end) { - __libcpp_remove_reference_t __save_errno = errno; - errno = 0; - char* __p2; - _Tp __ld = std::__do_strtod<_Tp>(__a, &__p2); - __libcpp_remove_reference_t __current_errno = errno; - if (__current_errno == 0) - errno = __save_errno; - if (__p2 != __a_end) { - __err = ios_base::failbit; - return 0; - } else if (__current_errno == ERANGE) - __err = ios_base::failbit; - return __ld; - } - __err = ios_base::failbit; - return 0; -} - template _InputIterator num_get<_CharT, _InputIterator>::do_get( iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, bool& __v) const { @@ -823,186 +982,6 @@ _InputIterator num_get<_CharT, _InputIterator>::do_get( return __b; } -// signed - -template -template -_InputIterator num_get<_CharT, _InputIterator>::__do_get_signed( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Signed& __v) const { - // Stage 1 - int __base = this->__get_base(__iob); - // Stage 2 - char_type __thousands_sep; - const int __atoms_size = __num_get_base::__int_chr_cnt; - char_type __atoms1[__atoms_size]; - const char_type* __atoms = this->__do_widen(__iob, __atoms1); - string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); - string __buf; - __buf.resize(__buf.capacity()); - char* __a = &__buf[0]; - char* __a_end = __a; - unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - for (; __b != __e; ++__b) { - if (__a_end == __a + __buf.size()) { - size_t __tmp = __buf.size(); - __buf.resize(2 * __buf.size()); - __buf.resize(__buf.capacity()); - __a = &__buf[0]; - __a_end = __a + __tmp; - } - if (this->__stage2_int_loop( - *__b, - __base, - __a, - __a_end, - __dc, - __thousands_sep, - __grouping, - __g, - __g_end, - const_cast(__atoms))) - break; - } - if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) - *__g_end++ = __dc; - // Stage 3 - __v = std::__num_get_signed_integral<_Signed>(__a, __a_end, __err, __base); - // Digit grouping checked - __check_grouping(__grouping, __g, __g_end, __err); - // EOF checked - if (__b == __e) - __err |= ios_base::eofbit; - return __b; -} - -// unsigned - -template -template -_InputIterator num_get<_CharT, _InputIterator>::__do_get_unsigned( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Unsigned& __v) const { - // Stage 1 - int __base = this->__get_base(__iob); - // Stage 2 - char_type __thousands_sep; - const int __atoms_size = __num_get_base::__int_chr_cnt; - char_type __atoms1[__atoms_size]; - const char_type* __atoms = this->__do_widen(__iob, __atoms1); - string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); - string __buf; - __buf.resize(__buf.capacity()); - char* __a = &__buf[0]; - char* __a_end = __a; - unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - for (; __b != __e; ++__b) { - if (__a_end == __a + __buf.size()) { - size_t __tmp = __buf.size(); - __buf.resize(2 * __buf.size()); - __buf.resize(__buf.capacity()); - __a = &__buf[0]; - __a_end = __a + __tmp; - } - if (this->__stage2_int_loop( - *__b, - __base, - __a, - __a_end, - __dc, - __thousands_sep, - __grouping, - __g, - __g_end, - const_cast(__atoms))) - break; - } - if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) - *__g_end++ = __dc; - // Stage 3 - __v = std::__num_get_unsigned_integral<_Unsigned>(__a, __a_end, __err, __base); - // Digit grouping checked - __check_grouping(__grouping, __g, __g_end, __err); - // EOF checked - if (__b == __e) - __err |= ios_base::eofbit; - return __b; -} - -// floating point - -template -template -_InputIterator num_get<_CharT, _InputIterator>::__do_get_floating_point( - iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, _Fp& __v) const { - // Stage 1, nothing to do - // Stage 2 - char_type __atoms[__num_get_base::__fp_chr_cnt]; - char_type __decimal_point; - char_type __thousands_sep; - string __grouping = this->__stage2_float_prep(__iob, __atoms, __decimal_point, __thousands_sep); - string __buf; - __buf.resize(__buf.capacity()); - char* __a = &__buf[0]; - char* __a_end = __a; - unsigned __g[__num_get_base::__num_get_buf_sz]; - unsigned* __g_end = __g; - unsigned __dc = 0; - bool __in_units = true; - char __exp = 'E'; - bool __is_leading_parsed = false; - for (; __b != __e; ++__b) { - if (__a_end == __a + __buf.size()) { - size_t __tmp = __buf.size(); - __buf.resize(2 * __buf.size()); - __buf.resize(__buf.capacity()); - __a = &__buf[0]; - __a_end = __a + __tmp; - } - if (this->__stage2_float_loop( - *__b, - __in_units, - __exp, - __a, - __a_end, - __decimal_point, - __thousands_sep, - __grouping, - __g, - __g_end, - __dc, - __atoms)) - break; - - // the leading character excluding the sign must be a decimal digit - if (!__is_leading_parsed) { - if (__a_end - __a >= 1 && __a[0] != '-' && __a[0] != '+') { - if (('0' <= __a[0] && __a[0] <= '9') || __a[0] == '.') - __is_leading_parsed = true; - else - break; - } else if (__a_end - __a >= 2 && (__a[0] == '-' || __a[0] == '+')) { - if (('0' <= __a[1] && __a[1] <= '9') || __a[1] == '.') - __is_leading_parsed = true; - else - break; - } - } - } - if (__grouping.size() != 0 && __in_units && __g_end - __g < __num_get_base::__num_get_buf_sz) - *__g_end++ = __dc; - // Stage 3 - __v = std::__num_get_float<_Fp>(__a, __a_end, __err); - // Digit grouping checked - __check_grouping(__grouping, __g, __g_end, __err); - // EOF checked - if (__b == __e) - __err |= ios_base::eofbit; - return __b; -} - template _InputIterator num_get<_CharT, _InputIterator>::do_get( iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { diff --git a/libcxx/include/mutex b/libcxx/include/mutex index 9b128e8710aae..b072bc38f3486 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -256,26 +256,24 @@ public: _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) { return try_lock_until(chrono::steady_clock::now() + __d); } + template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); + _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { + using namespace chrono; + unique_lock __lk(__m_); + bool __no_timeout = _Clock::now() < __t; + while (__no_timeout && __locked_) + __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; + if (!__locked_) { + __locked_ = true; + return true; + } + return false; + } + void unlock() _NOEXCEPT; }; -template -bool timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { - using namespace chrono; - unique_lock __lk(__m_); - bool __no_timeout = _Clock::now() < __t; - while (__no_timeout && __locked_) - __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; - if (!__locked_) { - __locked_ = true; - return true; - } - return false; -} - class _LIBCPP_EXPORTED_FROM_ABI recursive_timed_mutex { mutex __m_; condition_variable __cv_; @@ -295,34 +293,32 @@ public: _LIBCPP_HIDE_FROM_ABI bool try_lock_for(const chrono::duration<_Rep, _Period>& __d) { return try_lock_until(chrono::steady_clock::now() + __d); } + template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __t); + _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { + using namespace chrono; + __thread_id __id = this_thread::get_id(); + unique_lock __lk(__m_); + if (__id == __id_) { + if (__count_ == numeric_limits::max()) + return false; + ++__count_; + return true; + } + bool __no_timeout = _Clock::now() < __t; + while (__no_timeout && __count_ != 0) + __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; + if (__count_ == 0) { + __count_ = 1; + __id_ = __id; + return true; + } + return false; + } + void unlock() _NOEXCEPT; }; -template -bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { - using namespace chrono; - __thread_id __id = this_thread::get_id(); - unique_lock __lk(__m_); - if (__id == __id_) { - if (__count_ == numeric_limits::max()) - return false; - ++__count_; - return true; - } - bool __no_timeout = _Clock::now() < __t; - while (__no_timeout && __count_ != 0) - __no_timeout = __cv_.wait_until(__lk, __t) == cv_status::no_timeout; - if (__count_ == 0) { - __count_ = 1; - __id_ = __id; - return true; - } - return false; -} - template _LIBCPP_HIDE_FROM_ABI int try_lock(_L0& __l0, _L1& __l1) { unique_lock<_L0> __u0(__l0, try_to_lock_t()); diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex index b1e2a5d434400..7821f62f53032 100644 --- a/libcxx/include/shared_mutex +++ b/libcxx/include/shared_mutex @@ -240,10 +240,36 @@ public: _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) { return try_lock_until(chrono::steady_clock::now() + __rel_time); } + template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) - _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)); + _LIBCPP_HIDE_FROM_ABI bool try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_capability__(true)) { + unique_lock __lk(__base_.__mut_); + if (__base_.__state_ & __base_.__write_entered_) { + while (true) { + cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); + if ((__base_.__state_ & __base_.__write_entered_) == 0) + break; + if (__status == cv_status::timeout) + return false; + } + } + __base_.__state_ |= __base_.__write_entered_; + if (__base_.__state_ & __base_.__n_readers_) { + while (true) { + cv_status __status = __base_.__gate2_.wait_until(__lk, __abs_time); + if ((__base_.__state_ & __base_.__n_readers_) == 0) + break; + if (__status == cv_status::timeout) { + __base_.__state_ &= ~__base_.__write_entered_; + __base_.__gate1_.notify_all(); + return false; + } + } + } + return true; + } + void unlock() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_capability__()); // Shared ownership @@ -254,60 +280,30 @@ public: _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) { return try_lock_shared_until(chrono::steady_clock::now() + __rel_time); } - template - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool - try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) - _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)); - void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__()); -}; -template -bool shared_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) { - unique_lock __lk(__base_.__mut_); - if (__base_.__state_ & __base_.__write_entered_) { - while (true) { - cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); - if ((__base_.__state_ & __base_.__write_entered_) == 0) - break; - if (__status == cv_status::timeout) - return false; - } - } - __base_.__state_ |= __base_.__write_entered_; - if (__base_.__state_ & __base_.__n_readers_) { - while (true) { - cv_status __status = __base_.__gate2_.wait_until(__lk, __abs_time); - if ((__base_.__state_ & __base_.__n_readers_) == 0) - break; - if (__status == cv_status::timeout) { - __base_.__state_ &= ~__base_.__write_entered_; - __base_.__gate1_.notify_all(); - return false; + template + _LIBCPP_HIDE_FROM_ABI bool try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + _LIBCPP_THREAD_SAFETY_ANNOTATION(__try_acquire_shared_capability__(true)) { + unique_lock __lk(__base_.__mut_); + if ((__base_.__state_ & __base_.__write_entered_) || + (__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) { + while (true) { + cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); + if ((__base_.__state_ & __base_.__write_entered_) == 0 && + (__base_.__state_ & __base_.__n_readers_) < __base_.__n_readers_) + break; + if (__status == cv_status::timeout) + return false; } } + unsigned __num_readers = (__base_.__state_ & __base_.__n_readers_) + 1; + __base_.__state_ &= ~__base_.__n_readers_; + __base_.__state_ |= __num_readers; + return true; } - return true; -} -template -bool shared_timed_mutex::try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& __abs_time) { - unique_lock __lk(__base_.__mut_); - if ((__base_.__state_ & __base_.__write_entered_) || - (__base_.__state_ & __base_.__n_readers_) == __base_.__n_readers_) { - while (true) { - cv_status __status = __base_.__gate1_.wait_until(__lk, __abs_time); - if ((__base_.__state_ & __base_.__write_entered_) == 0 && - (__base_.__state_ & __base_.__n_readers_) < __base_.__n_readers_) - break; - if (__status == cv_status::timeout) - return false; - } - } - unsigned __num_readers = (__base_.__state_ & __base_.__n_readers_) + 1; - __base_.__state_ &= ~__base_.__n_readers_; - __base_.__state_ |= __num_readers; - return true; -} + void unlock_shared() _LIBCPP_THREAD_SAFETY_ANNOTATION(__release_shared_capability__()); +}; template class shared_lock { diff --git a/libcxx/include/string b/libcxx/include/string index fa87dc2fddb59..3d182cbc26892 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1117,7 +1117,7 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string(const _Tp& __t, size_type __pos, size_type __n, const allocator_type& __a = allocator_type()) : __alloc_(__a) { __self_view __sv0 = __t; @@ -1129,8 +1129,7 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t) { __self_view __sv = __t; __init(__sv.data(), __sv.size()); } @@ -1139,8 +1138,7 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS - _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t, const allocator_type& __a) + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t, const allocator_type& __a) : __alloc_(__a) { __self_view __sv = __t; __init(__sv.data(), __sv.size()); @@ -1336,8 +1334,7 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string >::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - operator+=(const _Tp& __t) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& operator+=(const _Tp& __t) { __self_view __sv = __t; return append(__sv); } @@ -1366,8 +1363,7 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - append(const _Tp& __t) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const _Tp& __t) { __self_view __sv = __t; return append(__sv.data(), __sv.size()); } @@ -1378,10 +1374,14 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 - - basic_string& - append(const _Tp& __t, size_type __pos, size_type __n = npos); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + append(const _Tp& __t, size_type __pos, size_type __n = npos) { + __self_view __sv = __t; + size_type __sz = __sv.size(); + if (__pos > __sz) + __throw_out_of_range(); + return append(__sv.data() + __pos, std::min(__n, __sz - __pos)); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* _LIBCPP_DIAGNOSE_NULLPTR __s); @@ -1390,7 +1390,7 @@ public: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __append_default_init(size_type __n); template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + _LIBCPP_HIDE_FROM_ABI _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(_InputIterator __first, _InputIterator __last) { const basic_string __temp(__first, __last, __alloc_); append(__temp.data(), __temp.size()); @@ -1398,8 +1398,26 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - append(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + append(_ForwardIterator __first, _ForwardIterator __last) { + size_type __sz = size(); + size_type __cap = capacity(); + size_type __n = static_cast(std::distance(__first, __last)); + if (__n) { + if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) { + if (__cap - __sz < __n) + __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); + __annotate_increase(__n); + auto __end = __copy_non_overlapping_range(__first, __last, std::__to_address(__get_pointer() + __sz)); + traits_type::assign(*__end, value_type()); + __set_size(__sz + __n); + } else { + const basic_string __temp(__first, __last, __alloc_); + append(__temp.data(), __temp.size()); + } + } + return *this; + } # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> @@ -1439,8 +1457,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - assign(const _Tp& __t) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const _Tp& __t) { __self_view __sv = __t; return assign(__sv.data(), __sv.size()); } @@ -1484,19 +1501,38 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - assign(const _Tp& __t, size_type __pos, size_type __n = npos); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + assign(const _Tp& __t, size_type __pos, size_type __n = npos) { + __self_view __sv = __t; + size_type __sz = __sv.size(); + if (__pos > __sz) + __throw_out_of_range(); + return assign(__sv.data() + __pos, std::min(__n, __sz - __pos)); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s, size_type __n); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(const value_type* __s); _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& assign(size_type __n, value_type __c); + template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - assign(_InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + assign(_InputIterator __first, _InputIterator __last) { + __assign_with_sentinel(__first, __last); + return *this; + } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - assign(_ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + assign(_ForwardIterator __first, _ForwardIterator __last) { + if (__string_is_trivial_iterator<_ForwardIterator>::value) { + size_type __n = static_cast(std::distance(__first, __last)); + __assign_trivial(__first, __last, __n); + } else { + __assign_with_sentinel(__first, __last); + } + + return *this; + } # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> @@ -1526,8 +1562,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - insert(size_type __pos1, const _Tp& __t) { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const _Tp& __t) { __self_view __sv = __t; return insert(__pos1, __sv.data(), __sv.size()); } @@ -1536,8 +1571,14 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n = npos) { + __self_view __sv = __t; + size_type __str_sz = __sv.size(); + if (__pos2 > __str_sz) + __throw_out_of_range(); + return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2)); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos); @@ -1568,12 +1609,18 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator - insert(const_iterator __pos, _InputIterator __first, _InputIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator + insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) { + const basic_string __temp(__first, __last, __alloc_); + return insert(__pos, __temp.data(), __temp.data() + __temp.size()); + } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator - insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator + insert(const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) { + auto __n = static_cast(std::distance(__first, __last)); + return __insert_with_size(__pos, __first, __last, __n); + } # ifndef _LIBCPP_CXX03_LANG _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 iterator @@ -1592,7 +1639,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos1, size_type __n1, const _Tp& __t) { __self_view __sv = __t; return replace(__pos1, __n1, __sv.data(), __sv.size()); @@ -1605,8 +1652,14 @@ public: __enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value && !__is_same_uncvref<_Tp, basic_string>::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + replace(size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2 = npos) { + __self_view __sv = __t; + size_type __str_sz = __sv.size(); + if (__pos2 > __str_sz) + __throw_out_of_range(); + return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2)); + } _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(size_type __pos, size_type __n1, const value_type* __s, size_type __n2); @@ -1620,7 +1673,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& replace(const_iterator __i1, const_iterator __i2, const _Tp& __t) { __self_view __sv = __t; return replace(__i1 - begin(), __i2 - __i1, __sv); @@ -1642,8 +1695,11 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& - replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2); + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& + replace(const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) { + const basic_string __temp(__j1, __j2, __alloc_); + return replace(__i1, __i2, __temp); + } # if _LIBCPP_STD_VER >= 23 template <_ContainerCompatibleRange<_CharT> _Range> @@ -1710,7 +1766,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find(data(), size(), __sv.data(), __pos, __sv.size()); @@ -1741,7 +1797,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type rfind(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_rfind(data(), size(), __sv.data(), __pos, __sv.size()); @@ -1772,7 +1828,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_first_of( @@ -1806,7 +1862,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_last_of( @@ -1840,7 +1896,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_first_not_of(const _Tp& __t, size_type __pos = 0) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_first_not_of( @@ -1874,7 +1930,7 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type find_last_not_of(const _Tp& __t, size_type __pos = npos) const _NOEXCEPT { __self_view __sv = __t; return std::__str_find_last_not_of( @@ -1906,11 +1962,22 @@ public: } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int - compare(const _Tp& __t) const _NOEXCEPT; + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(const _Tp& __t) const _NOEXCEPT { + __self_view __sv = __t; + size_t __lhs_sz = size(); + size_t __rhs_sz = __sv.size(); + int __result = traits_type::compare(data(), __sv.data(), std::min(__lhs_sz, __rhs_sz)); + if (__result != 0) + return __result; + if (__lhs_sz < __rhs_sz) + return -1; + if (__lhs_sz > __rhs_sz) + return 1; + return 0; + } template ::value, int> = 0> - _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 int + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 int compare(size_type __pos1, size_type __n1, const _Tp& __t) const { __self_view __sv = __t; return compare(__pos1, __n1, __sv.data(), __sv.size()); @@ -2877,14 +2944,6 @@ basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, tr # endif -template -template ::value, int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::assign(_InputIterator __first, _InputIterator __last) { - __assign_with_sentinel(__first, __last); - return *this; -} - template template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void @@ -2893,20 +2952,6 @@ basic_string<_CharT, _Traits, _Allocator>::__assign_with_sentinel(_InputIterator assign(__temp.data(), __temp.size()); } -template -template ::value, int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::assign(_ForwardIterator __first, _ForwardIterator __last) { - if (__string_is_trivial_iterator<_ForwardIterator>::value) { - size_type __n = static_cast(std::distance(__first, __last)); - __assign_trivial(__first, __last, __n); - } else { - __assign_with_sentinel(__first, __last); - } - - return *this; -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void @@ -2946,20 +2991,6 @@ basic_string<_CharT, _Traits, _Allocator>::assign(const basic_string& __str, siz return assign(__str.data() + __pos, std::min(__n, __sz - __pos)); } -template -template ::value && - !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::assign(const _Tp& __t, size_type __pos, size_type __n) { - __self_view __sv = __t; - size_type __sz = __sv.size(); - if (__pos > __sz) - this->__throw_out_of_range(); - return assign(__sv.data() + __pos, std::min(__n, __sz - __pos)); -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_NOINLINE basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::__assign_external(const value_type* __s) { @@ -3059,29 +3090,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::pu traits_type::assign(*++__p, value_type()); } -template -template ::value, int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::append(_ForwardIterator __first, _ForwardIterator __last) { - size_type __sz = size(); - size_type __cap = capacity(); - size_type __n = static_cast(std::distance(__first, __last)); - if (__n) { - if (__string_is_trivial_iterator<_ForwardIterator>::value && !__addr_in_range(*__first)) { - if (__cap - __sz < __n) - __grow_by_without_replace(__cap, __sz + __n - __cap, __sz, __sz, 0); - __annotate_increase(__n); - auto __end = __copy_non_overlapping_range(__first, __last, std::__to_address(__get_pointer() + __sz)); - traits_type::assign(*__end, value_type()); - __set_size(__sz + __n); - } else { - const basic_string __temp(__first, __last, __alloc_); - append(__temp.data(), __temp.size()); - } - } - return *this; -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, size_type __pos, size_type __n) { @@ -3091,20 +3099,6 @@ basic_string<_CharT, _Traits, _Allocator>::append(const basic_string& __str, siz return append(__str.data() + __pos, std::min(__n, __sz - __pos)); } -template -template ::value && - !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::append(const _Tp& __t, size_type __pos, size_type __n) { - __self_view __sv = __t; - size_type __sz = __sv.size(); - if (__pos > __sz) - this->__throw_out_of_range(); - return append(__sv.data() + __pos, std::min(__n, __sz - __pos)); -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::append(const value_type* __s) { @@ -3169,23 +3163,6 @@ basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, size_type __n return *this; } -template -template ::value, int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator -basic_string<_CharT, _Traits, _Allocator>::insert(const_iterator __pos, _InputIterator __first, _InputIterator __last) { - const basic_string __temp(__first, __last, __alloc_); - return insert(__pos, __temp.data(), __temp.data() + __temp.size()); -} - -template -template ::value, int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator -basic_string<_CharT, _Traits, _Allocator>::insert( - const_iterator __pos, _ForwardIterator __first, _ForwardIterator __last) { - auto __n = static_cast(std::distance(__first, __last)); - return __insert_with_size(__pos, __first, __last, __n); -} - template template _LIBCPP_CONSTEXPR_SINCE_CXX20 typename basic_string<_CharT, _Traits, _Allocator>::iterator @@ -3213,20 +3190,6 @@ basic_string<_CharT, _Traits, _Allocator>::insert( return insert(__pos1, __str.data() + __pos2, std::min(__n, __str_sz - __pos2)); } -template -template ::value && - !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos1, const _Tp& __t, size_type __pos2, size_type __n) { - __self_view __sv = __t; - size_type __str_sz = __sv.size(); - if (__pos2 > __str_sz) - this->__throw_out_of_range(); - return insert(__pos1, __sv.data() + __pos2, std::min(__n, __str_sz - __pos2)); -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::insert(size_type __pos, const value_type* __s) { @@ -3330,15 +3293,6 @@ basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __ return __null_terminate_at(__p, __sz - (__n1 - __n2)); } -template -template ::value, int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::replace( - const_iterator __i1, const_iterator __i2, _InputIterator __j1, _InputIterator __j2) { - const basic_string __temp(__j1, __j2, __alloc_); - return replace(__i1, __i2, __temp); -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace( @@ -3349,21 +3303,6 @@ basic_string<_CharT, _Traits, _Allocator>::replace( return replace(__pos1, __n1, __str.data() + __pos2, std::min(__n2, __str_sz - __pos2)); } -template -template ::value && - !__is_same_uncvref<_Tp, basic_string<_CharT, _Traits, _Allocator> >::value, - int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& -basic_string<_CharT, _Traits, _Allocator>::replace( - size_type __pos1, size_type __n1, const _Tp& __t, size_type __pos2, size_type __n2) { - __self_view __sv = __t; - size_type __str_sz = __sv.size(); - if (__pos2 > __str_sz) - this->__throw_out_of_range(); - return replace(__pos1, __n1, __sv.data() + __pos2, std::min(__n2, __str_sz - __pos2)); -} - template _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>& basic_string<_CharT, _Traits, _Allocator>::replace(size_type __pos, size_type __n1, const value_type* __s) { @@ -3586,22 +3525,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocat // compare -template -template ::value, int> > -_LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare(const _Tp& __t) const _NOEXCEPT { - __self_view __sv = __t; - size_t __lhs_sz = size(); - size_t __rhs_sz = __sv.size(); - int __result = traits_type::compare(data(), __sv.data(), std::min(__lhs_sz, __rhs_sz)); - if (__result != 0) - return __result; - if (__lhs_sz < __rhs_sz) - return -1; - if (__lhs_sz > __rhs_sz) - return 1; - return 0; -} - template inline _LIBCPP_CONSTEXPR_SINCE_CXX20 int basic_string<_CharT, _Traits, _Allocator>::compare( size_type __pos1, size_type __n1, const value_type* __s, size_type __n2) const {