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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits