From fe6d50fcaac37051057467a29eb99f817d5a4dc7 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Sun, 19 Jun 2016 06:58:22 +0000 Subject: Implement LWG issue 1169. num_get not fully compatible with strto* Use strtof and strtod for floats and doubles respectively instead of always using strtold. The other parts of the change are already implemented in libc++. This patch also has a drive by fix to wbuffer_convert::underflow() which prevents it from calling memmove(buff, null, 0). git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@273106 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/locale | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'include/locale') diff --git a/include/locale b/include/locale index b1cac28fb..f999cd984 100644 --- a/include/locale +++ b/include/locale @@ -180,6 +180,7 @@ template class messages_byname; #include <__config> #include <__locale> +#include <__debug> #include #include #include @@ -755,6 +756,28 @@ __num_get_unsigned_integral(const char* __a, const char* __a_end, return 0; } +template +_LIBCPP_INLINE_VISIBILITY +_Tp __do_strtod(const char* __a, char** __p2); + +template <> +inline _LIBCPP_INLINE_VISIBILITY +float __do_strtod(const char* __a, char** __p2) { + return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_INLINE_VISIBILITY +double __do_strtod(const char* __a, char** __p2) { + return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + +template <> +inline _LIBCPP_INLINE_VISIBILITY +long double __do_strtod(const char* __a, char** __p2) { + return strtold_l(__a, __p2, _LIBCPP_GET_C_LOCALE); +} + template _Tp __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) @@ -764,7 +787,7 @@ __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) typename remove_reference::type __save_errno = errno; errno = 0; char *__p2; - long double __ld = strtold_l(__a, &__p2, _LIBCPP_GET_C_LOCALE); + _Tp __ld = __do_strtod<_Tp>(__a, &__p2); typename remove_reference::type __current_errno = errno; if (__current_errno == 0) errno = __save_errno; @@ -775,7 +798,7 @@ __num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err) } else if (__current_errno == ERANGE) __err = ios_base::failbit; - return static_cast<_Tp>(__ld); + return __ld; } __err = ios_base::failbit; return 0; @@ -3901,7 +3924,9 @@ wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow() } else { - memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); + _LIBCPP_ASSERT(!(__extbufnext_ == NULL && (__extbufend_ != __extbufnext_)), "underflow moving from NULL" ); + if (__extbufend_ != __extbufnext_) + memmove(__extbuf_, __extbufnext_, __extbufend_ - __extbufnext_); __extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_); __extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_); streamsize __nmemb = _VSTD::min(static_cast(this->egptr() - this->eback() - __unget_sz), -- cgit v1.2.3