Parsing floating point numbers with very long precision was broken, and this patch fixes it. This fixes http://llvm.org/bugs/show_bug.cgi?id=15445.
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@176711 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
23fb972520
commit
6319f1462d
@ -646,6 +646,8 @@ __num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __ex
|
|||||||
_CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
|
_CharT __decimal_point, _CharT __thousands_sep, const string& __grouping,
|
||||||
unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
|
unsigned* __g, unsigned*& __g_end, unsigned& __dc, _CharT* __atoms)
|
||||||
{
|
{
|
||||||
|
if (__a_end-__a >= __num_get_buf_sz - 1)
|
||||||
|
return -1;
|
||||||
if (__ct == __decimal_point)
|
if (__ct == __decimal_point)
|
||||||
{
|
{
|
||||||
if (!__in_units)
|
if (!__in_units)
|
||||||
@ -673,23 +675,27 @@ __num_get<_CharT>::__stage2_float_loop(_CharT __ct, bool& __in_units, char& __ex
|
|||||||
char __x = __src[__f];
|
char __x = __src[__f];
|
||||||
if (__x == '-' || __x == '+')
|
if (__x == '-' || __x == '+')
|
||||||
{
|
{
|
||||||
if (__a_end == __a || (__a_end[-1] & 0xDF) == __exp)
|
if (__a_end == __a || (__a_end[-1] & 0x5F) == (__exp & 0x7F))
|
||||||
{
|
{
|
||||||
*__a_end++ = __x;
|
*__a_end++ = __x;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (__a_end-__a < __num_get_buf_sz - 1)
|
|
||||||
*__a_end++ = __x;
|
|
||||||
if (__x == 'x' || __x == 'X')
|
if (__x == 'x' || __x == 'X')
|
||||||
__exp = 'P';
|
__exp = 'P';
|
||||||
else if ((__x & 0xDF) == __exp)
|
else if ((__x & 0x5F) == __exp)
|
||||||
{
|
{
|
||||||
__in_units = false;
|
__exp |= 0x80;
|
||||||
if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
|
if (__in_units)
|
||||||
*__g_end++ = __dc;
|
{
|
||||||
|
__in_units = false;
|
||||||
|
if (__grouping.size() != 0 && __g_end-__g < __num_get_buf_sz)
|
||||||
|
*__g_end++ = __dc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (__a_end-__a < __num_get_buf_sz - ((__exp & 0x80) ? 1 : 11))
|
||||||
|
*__a_end++ = __x;
|
||||||
if (__f >= 22)
|
if (__f >= 22)
|
||||||
return 0;
|
return 0;
|
||||||
++__dc;
|
++__dc;
|
||||||
|
@ -240,4 +240,16 @@ int main()
|
|||||||
assert(iter.base() == str+sizeof(str)-1);
|
assert(iter.base() == str+sizeof(str)-1);
|
||||||
assert(err == ios.failbit);
|
assert(err == ios.failbit);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
v = -1;
|
||||||
|
const char str[] = "3;14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651e+10";
|
||||||
|
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.goodbit);
|
||||||
|
assert(std::abs(v - 3.14159265358979e+10)/3.14159265358979e+10 < 1.e-8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user