forked from OSchip/llvm-project
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). llvm-svn: 273106
This commit is contained in:
parent
3119599475
commit
be13be47ba
|
@ -180,6 +180,7 @@ template <class charT> class messages_byname;
|
||||||
|
|
||||||
#include <__config>
|
#include <__config>
|
||||||
#include <__locale>
|
#include <__locale>
|
||||||
|
#include <__debug>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ios>
|
#include <ios>
|
||||||
|
@ -755,6 +756,28 @@ __num_get_unsigned_integral(const char* __a, const char* __a_end,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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>
|
template <class _Tp>
|
||||||
_Tp
|
_Tp
|
||||||
__num_get_float(const char* __a, const char* __a_end, ios_base::iostate& __err)
|
__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;
|
typename remove_reference<decltype(errno)>::type __save_errno = errno;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
char *__p2;
|
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;
|
typename remove_reference<decltype(errno)>::type __current_errno = errno;
|
||||||
if (__current_errno == 0)
|
if (__current_errno == 0)
|
||||||
errno = __save_errno;
|
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)
|
else if (__current_errno == ERANGE)
|
||||||
__err = ios_base::failbit;
|
__err = ios_base::failbit;
|
||||||
return static_cast<_Tp>(__ld);
|
return __ld;
|
||||||
}
|
}
|
||||||
__err = ios_base::failbit;
|
__err = ios_base::failbit;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3901,7 +3924,9 @@ wbuffer_convert<_Codecvt, _Elem, _Tr>::underflow()
|
||||||
}
|
}
|
||||||
else
|
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_);
|
__extbufnext_ = __extbuf_ + (__extbufend_ - __extbufnext_);
|
||||||
__extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
|
__extbufend_ = __extbuf_ + (__extbuf_ == __extbuf_min_ ? sizeof(__extbuf_min_) : __ebs_);
|
||||||
streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
|
streamsize __nmemb = _VSTD::min(static_cast<streamsize>(this->egptr() - this->eback() - __unget_sz),
|
||||||
|
|
|
@ -44,11 +44,6 @@ long strtol_l(const char *__nptr, char **__endptr,
|
||||||
return strtol(__nptr, __endptr, __base);
|
return strtol(__nptr, __endptr, __base);
|
||||||
}
|
}
|
||||||
static inline
|
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,
|
unsigned long long strtoull_l(const char *__nptr, char **__endptr,
|
||||||
int __base, locale_t __loc) {
|
int __base, locale_t __loc) {
|
||||||
return strtoull(__nptr, __endptr, __base);
|
return strtoull(__nptr, __endptr, __base);
|
||||||
|
@ -58,6 +53,21 @@ unsigned long strtoul_l(const char *__nptr, char **__endptr,
|
||||||
int __base, locale_t __loc) {
|
int __base, locale_t __loc) {
|
||||||
return strtoul(__nptr, __endptr, __base);
|
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
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -19,6 +19,17 @@
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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,
|
inline _LIBCPP_ALWAYS_INLINE long double strtold_l(const char *nptr,
|
||||||
char **endptr, locale_t) {
|
char **endptr, locale_t) {
|
||||||
return ::strtold(nptr, endptr);
|
return ::strtold(nptr, endptr);
|
||||||
|
|
|
@ -207,6 +207,30 @@ int main()
|
||||||
assert(err == ios.goodbit);
|
assert(err == ios.goodbit);
|
||||||
assert(v == 2);
|
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));
|
ios.imbue(std::locale(std::locale(), new my_numpunct));
|
||||||
{
|
{
|
||||||
v = -1;
|
v = -1;
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
: F(refs) {}
|
: F(refs) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
const my_facet f(1);
|
const my_facet f(1);
|
||||||
|
@ -168,4 +169,29 @@ int main()
|
||||||
assert(err == ios.goodbit);
|
assert(err == ios.goodbit);
|
||||||
assert(std::isnan(v));
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
: F(refs) {}
|
: F(refs) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
const my_facet f(1);
|
const my_facet f(1);
|
||||||
|
@ -228,4 +229,28 @@ int main()
|
||||||
assert(err != ios.failbit);
|
assert(err != ios.failbit);
|
||||||
assert(v == 304888344611713860501504000000.0L);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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#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><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></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#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#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>
|
<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>
|
||||||
|
|
Loading…
Reference in New Issue