[libcxx] r273106 - Implement LWG issue 1169. num_get not fully compatible with strto*

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Sat Jun 18 23:58:23 PDT 2016


Author: ericwf
Date: Sun Jun 19 01:58:22 2016
New Revision: 273106

URL: http://llvm.org/viewvc/llvm-project?rev=273106&view=rev
Log:
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).

Modified:
    libcxx/trunk/include/locale
    libcxx/trunk/include/support/solaris/xlocale.h
    libcxx/trunk/include/support/xlocale/__strtonum_fallback.h
    libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp
    libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp
    libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp
    libcxx/trunk/www/cxx1z_status.html

Modified: libcxx/trunk/include/locale
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/locale?rev=273106&r1=273105&r2=273106&view=diff
==============================================================================
--- libcxx/trunk/include/locale (original)
+++ libcxx/trunk/include/locale Sun Jun 19 01:58:22 2016
@@ -180,6 +180,7 @@ template <class charT> class messages_by
 
 #include <__config>
 #include <__locale>
+#include <__debug>
 #include <algorithm>
 #include <memory>
 #include <ios>
@@ -756,6 +757,28 @@ __num_get_unsigned_integral(const char*
 }
 
 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 c
         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 c
         }
         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>::u
         }
         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),

Modified: libcxx/trunk/include/support/solaris/xlocale.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/support/solaris/xlocale.h?rev=273106&r1=273105&r2=273106&view=diff
==============================================================================
--- libcxx/trunk/include/support/solaris/xlocale.h (original)
+++ libcxx/trunk/include/support/solaris/xlocale.h Sun Jun 19 01:58:22 2016
@@ -44,11 +44,6 @@ long strtol_l(const char *__nptr, char *
   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 *__np
     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

Modified: libcxx/trunk/include/support/xlocale/__strtonum_fallback.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/support/xlocale/__strtonum_fallback.h?rev=273106&r1=273105&r2=273106&view=diff
==============================================================================
--- libcxx/trunk/include/support/xlocale/__strtonum_fallback.h (original)
+++ libcxx/trunk/include/support/xlocale/__strtonum_fallback.h Sun Jun 19 01:58:22 2016
@@ -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);

Modified: libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp?rev=273106&r1=273105&r2=273106&view=diff
==============================================================================
--- libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp (original)
+++ libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_double.pass.cpp Sun Jun 19 01:58:22 2016
@@ -207,6 +207,30 @@ int main()
         assert(err == ios.goodbit);
         assert(v == 2);
     }
+    {
+        v = -1;
+        const char str[] = "1.79779e+309"; // unrepresentable
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.failbit);
+        assert(v == HUGE_VAL);
+    }
+    {
+        v = -1;
+        const char str[] = "-1.79779e+308"; // unrepresentable
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.failbit);
+        assert(v == -HUGE_VAL);
+    }
     ios.imbue(std::locale(std::locale(), new my_numpunct));
     {
         v = -1;

Modified: libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp?rev=273106&r1=273105&r2=273106&view=diff
==============================================================================
--- libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp (original)
+++ libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_float.pass.cpp Sun Jun 19 01:58:22 2016
@@ -32,6 +32,7 @@ public:
         : F(refs) {}
 };
 
+
 int main()
 {
     const my_facet f(1);
@@ -168,4 +169,29 @@ int main()
         assert(err == ios.goodbit);
         assert(std::isnan(v));
     }
+    {
+        v = -1;
+        const char str[] = "3.40283e+39"; // unrepresentable
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.failbit);
+        assert(v == HUGE_VALF);
+    }
+    {
+        v = -1;
+        const char str[] = "-3.40283e+38"; // unrepresentable
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.failbit);
+        assert(v == -HUGE_VALF);
+
+    }
 }

Modified: libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp?rev=273106&r1=273105&r2=273106&view=diff
==============================================================================
--- libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp (original)
+++ libcxx/trunk/test/std/localization/locale.categories/category.numeric/locale.num.get/facet.num.get.members/get_long_double.pass.cpp Sun Jun 19 01:58:22 2016
@@ -32,6 +32,7 @@ public:
         : F(refs) {}
 };
 
+
 int main()
 {
     const my_facet f(1);
@@ -228,4 +229,28 @@ int main()
         assert(err != ios.failbit);
         assert(v == 304888344611713860501504000000.0L);
     }
+    {
+        v = -1;
+        const char str[] = "1.19973e+4933"; // unrepresentable
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.failbit);
+        assert(v == HUGE_VALL);
+    }
+    {
+        v = -1;
+        const char str[] = "-1.18974e+4932"; // unrepresentable
+        std::ios_base::iostate err = ios.goodbit;
+        input_iterator<const char*> iter =
+            f.get(input_iterator<const char*>(str),
+                  input_iterator<const char*>(str+sizeof(str)),
+                  ios, err, v);
+        assert(iter.base() == str+sizeof(str)-1);
+        assert(err == ios.failbit);
+        assert(v == -HUGE_VALL);
+    }
 }

Modified: libcxx/trunk/www/cxx1z_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1z_status.html?rev=273106&r1=273105&r2=273106&view=diff
==============================================================================
--- libcxx/trunk/www/cxx1z_status.html (original)
+++ libcxx/trunk/www/cxx1z_status.html Sun Jun 19 01:58:22 2016
@@ -163,7 +163,7 @@
 	<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2482">2482</td><td>[c.strings] Table 73 mentions nonexistent functions</td><td>Lenexa</td><td>Complete</td></tr>
 	<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2488">2488</td><td>Placeholders should be allowed and encouraged to be constexpr</td><td>Lenexa</td><td></td></tr>
  	<tr><td></td><td></td><td></td><td></td></tr>
-	<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#1169">1169</a></td><td><tt>num_get</tt> not fully compatible with <tt>strto*</tt></td><td>Kona</td><td></td></tr>
+	<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#1169">1169</a></td><td><tt>num_get</tt> not fully compatible with <tt>strto*</tt></td><td>Kona</td><td>Complete</td></tr>
 	<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2072">2072</a></td><td>Unclear wording about capacity of temporary buffers</td><td>Kona</td><td>Complete</td></tr>
 	<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2101">2101</a></td><td>Some transformation types can produce impossible types</td><td>Kona</td><td>Complete</td></tr>
 	<tr><td><a href="http://cplusplus.github.io/LWG/lwg-defects.html#2111">2111</a></td><td>Which <tt>unexpected</tt>/<tt>terminate</tt> handler is called from the exception handling runtime?</td><td>Kona</td><td>Complete</td></tr>




More information about the cfe-commits mailing list