summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-06-19 06:58:22 +0000
committerEric Fiselier <eric@efcs.ca>2016-06-19 06:58:22 +0000
commitfe6d50fcaac37051057467a29eb99f817d5a4dc7 (patch)
tree22d1bac32f5c694aa1739a346fdb93b94322f58e /include
parent57254f448f82195c76ad97ccca1fba4a618306df (diff)
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
Diffstat (limited to 'include')
-rw-r--r--include/locale31
-rw-r--r--include/support/solaris/xlocale.h20
-rw-r--r--include/support/xlocale/__strtonum_fallback.h11
3 files changed, 54 insertions, 8 deletions
diff --git a/include/locale b/include/locale
index b1cac28fb..f999cd984 100644
--- a/include/locale
+++ b/include/locale
@@ -180,6 +180,7 @@ template <class charT> class messages_byname;
#include <__config>
#include <__locale>
+#include <__debug>
#include <algorithm>
#include <memory>
#include <ios>
@@ -756,6 +757,28 @@ __num_get_unsigned_integral(const char* __a, const char* __a_end,
}
template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY
+_Tp __do_strtod(const char* __a, char** __p2);
+
+template <>
+inline _LIBCPP_INLINE_VISIBILITY
+float __do_strtod<float>(const char* __a, char** __p2) {
+ return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
+}
+
+template <>
+inline _LIBCPP_INLINE_VISIBILITY
+double __do_strtod<double>(const char* __a, char** __p2) {
+ return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
+}
+
+template <>
+inline _LIBCPP_INLINE_VISIBILITY
+long double __do_strtod<long double>(const char* __a, char** __p2) {
+ return strtold_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
+}
+
+template <class _Tp>
_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<decltype(errno)>::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<decltype(errno)>::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<streamsize>(this->egptr() - this->eback() - __unget_sz),
diff --git a/include/support/solaris/xlocale.h b/include/support/solaris/xlocale.h
index 62b0d74a6..e20ef7a6e 100644
--- a/include/support/solaris/xlocale.h
+++ b/include/support/solaris/xlocale.h
@@ -44,11 +44,6 @@ long strtol_l(const char *__nptr, char **__endptr,
return strtol(__nptr, __endptr, __base);
}
static inline
-long double strtold_l(const char *__nptr, char **__endptr,
- locale_t __loc) {
- return strtold(__nptr, __endptr);
-}
-static inline
unsigned long long strtoull_l(const char *__nptr, char **__endptr,
int __base, locale_t __loc) {
return strtoull(__nptr, __endptr, __base);
@@ -58,6 +53,21 @@ unsigned long strtoul_l(const char *__nptr, char **__endptr,
int __base, locale_t __loc) {
return strtoul(__nptr, __endptr, __base);
}
+static inline
+float strtof_l(const char *__nptr, char **__endptr,
+ locale_t __loc) {
+ return strtof(__nptr, __endptr);
+}
+static inline
+double strtod_l(const char *__nptr, char **__endptr,
+ locale_t __loc) {
+ return strtod(__nptr, __endptr);
+}
+static inline
+long double strtold_l(const char *__nptr, char **__endptr,
+ locale_t __loc) {
+ return strtold(__nptr, __endptr);
+}
#ifdef __cplusplus
diff --git a/include/support/xlocale/__strtonum_fallback.h b/include/support/xlocale/__strtonum_fallback.h
index b060f7568..4ae3918b3 100644
--- a/include/support/xlocale/__strtonum_fallback.h
+++ b/include/support/xlocale/__strtonum_fallback.h
@@ -19,6 +19,17 @@
#ifdef __cplusplus
extern "C" {
#endif
+
+inline _LIBCPP_ALWAYS_INLINE float strtof_l(const char *nptr,
+ char **endptr, locale_t) {
+ return ::strtof(nptr, endptr);
+}
+
+inline _LIBCPP_ALWAYS_INLINE double strtod_l(const char *nptr,
+ char **endptr, locale_t) {
+ return ::strtod(nptr, endptr);
+}
+
inline _LIBCPP_ALWAYS_INLINE long double strtold_l(const char *nptr,
char **endptr, locale_t) {
return ::strtold(nptr, endptr);