This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] Fix libstdc++/9548 on the 3_3 branch
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: "libstdc++ at gcc dot gnu dot org" <libstdc++ at gcc dot gnu dot org>
- Cc: bkoz <bkoz at redhat dot com>
- Date: Fri, 07 Feb 2003 14:55:26 +0100
- Subject: [Patch] Fix libstdc++/9548 on the 3_3 branch
Hi,
the below is the version for the branch, regtested and
abi checked on x86-linux.
Ok?
Paolo.
//////////
2003-02-07 Paolo Carlini <pcarlini@unitus.it>
PR libstdc++/9548
Implement resolution of DR 231 (Ready)
* include/bits/locale_facets.h (__num_base::_S_format_float):
Return void.
* src/locale.cc (__num_base::_S_format_float): Implement
resolution of DR 231.
* include/bits/locale_facets.tcc (num_put::_M_convert_float):
Tweak uses. Check for negative precision.
* testsuite/22_locale/num_put_members_char.cc (test06): Add
* testsuite/22_locale/num_put_members_wchar_t.cc (test06): Ditto.
diff -urN libstdc++-v3-orig/include/bits/locale_facets.h libstdc++-v3/include/bits/locale_facets.h
--- libstdc++-v3-orig/include/bits/locale_facets.h 2003-02-06 09:33:03.000000000 +0100
+++ libstdc++-v3/include/bits/locale_facets.h 2003-02-07 13:25:58.000000000 +0100
@@ -546,8 +546,8 @@
// num_put
// Construct and return valid scanf format for floating point types.
- static bool
- _S_format_float(const ios_base& __io, char* __fptr, char __mod,
+ static void
+ _S_format_float(const ios_base& __io, char* __fptr, char __mod,
streamsize __prec);
// Construct and return valid scanf format for integer types.
diff -urN libstdc++-v3-orig/include/bits/locale_facets.tcc libstdc++-v3/include/bits/locale_facets.tcc
--- libstdc++-v3-orig/include/bits/locale_facets.tcc 2003-02-06 09:33:03.000000000 +0100
+++ libstdc++-v3/include/bits/locale_facets.tcc 2003-02-07 13:27:01.000000000 +0100
@@ -634,6 +634,9 @@
if (__prec > static_cast<streamsize>(__max_digits))
__prec = static_cast<streamsize>(__max_digits);
+ else if (__prec < static_cast<streamsize>(0))
+ // Default precision.
+ __prec = static_cast<streamsize>(6);
// Long enough for the max format spec.
char __fbuf[16];
@@ -646,24 +649,17 @@
int __cs_size = __max_digits * 3;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
- const bool __fp = _S_format_float(__io, __fbuf, __mod, __prec);
- if (__fp)
- __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_c_locale, __prec);
- else
- __len = __convert_from_v(__cs, __cs_size, __fbuf, __v, _S_c_locale);
+ _S_format_float(__io, __fbuf, __mod, __prec);
+ __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
+ _S_c_locale, __prec);
// If the buffer was not large enough, try again with the correct size.
if (__len >= __cs_size)
{
__cs_size = __len + 1;
__cs = static_cast<char*>(__builtin_alloca(__cs_size));
- if (__fp)
- __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_c_locale, __prec);
- else
- __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
- _S_c_locale);
+ __len = __convert_from_v(__cs, __cs_size, __fbuf, __v,
+ _S_c_locale, __prec);
}
#else
// Consider the possibility of long ios_base::fixed outputs
@@ -678,10 +674,8 @@
: __max_digits * 3;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
- if (_S_format_float(__io, __fbuf, __mod, __prec))
- __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
- else
- __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale);
+ _S_format_float(__io, __fbuf, __mod, __prec);
+ __len = __convert_from_v(__cs, 0, __fbuf, __v, _S_c_locale, __prec);
#endif
return _M_widen_float(__s, __io, __fill, __cs, __len);
}
diff -urN libstdc++-v3-orig/src/locale.cc libstdc++-v3/src/locale.cc
--- libstdc++-v3-orig/src/locale.cc 2003-01-06 23:20:07.000000000 +0100
+++ libstdc++-v3/src/locale.cc 2003-02-07 13:25:08.000000000 +0100
@@ -504,11 +504,13 @@
const char __num_base::_S_atoms[] = "0123456789eEabcdfABCDF";
- bool
- __num_base::_S_format_float(const ios_base& __io, char* __fptr, char __mod,
- streamsize __prec)
+ // _GLIBCPP_RESOLVE_LIB_DEFECTS
+ // According to the resolution of DR 231, about 22.2.2.2.2, p11,
+ // "str.precision() is specified in the conversion specification".
+ void
+ __num_base::_S_format_float(const ios_base& __io, char* __fptr,
+ char __mod, streamsize /* unused post DR 231 */)
{
- bool __incl_prec = false;
ios_base::fmtflags __flags = __io.flags();
*__fptr++ = '%';
// [22.2.2.2.2] Table 60
@@ -516,13 +518,12 @@
*__fptr++ = '+';
if (__flags & ios_base::showpoint)
*__fptr++ = '#';
- // As per [22.2.2.2.2.11]
- if (__flags & ios_base::fixed || __prec > 0)
- {
- *__fptr++ = '.';
- *__fptr++ = '*';
- __incl_prec = true;
- }
+
+ // As per DR 231: _always_, not only when
+ // __flags & ios_base::fixed || __prec > 0
+ *__fptr++ = '.';
+ *__fptr++ = '*';
+
if (__mod)
*__fptr++ = __mod;
ios_base::fmtflags __fltfield = __flags & ios_base::floatfield;
@@ -534,7 +535,6 @@
else
*__fptr++ = (__flags & ios_base::uppercase) ? 'G' : 'g';
*__fptr = '\0';
- return __incl_prec;
}
void
diff -urN libstdc++-v3-orig/testsuite/22_locale/num_put_members_char.cc libstdc++-v3/testsuite/22_locale/num_put_members_char.cc
--- libstdc++-v3-orig/testsuite/22_locale/num_put_members_char.cc 2002-10-23 17:45:50.000000000 +0200
+++ libstdc++-v3/testsuite/22_locale/num_put_members_char.cc 2003-02-07 14:00:14.000000000 +0100
@@ -1,6 +1,6 @@
// 2001-11-19 Benjamin Kosnik <bkoz@redhat.com>
-// Copyright (C) 2001, 2002 Free Software Foundation
+// Copyright (C) 2001, 2002, 2003 Free Software Foundation
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -363,6 +363,35 @@
VERIFY( result == "0" );
}
+// libstdc++/9548 and DR 231
+void test06()
+{
+ using namespace std;
+ bool test = true;
+
+ const locale loc_c = locale::classic();
+
+ ostringstream oss1, oss2;
+ oss1.imbue(loc_c);
+ oss2.imbue(loc_c);
+ const num_put<char>& np1 = use_facet<num_put<char> >(oss1.getloc());
+ const num_put<char>& np2 = use_facet<num_put<char> >(oss2.getloc());
+
+ string result1, result2;
+
+ oss1.precision(-1);
+ oss1.setf(ios_base::fixed, ios_base::floatfield);
+ np1.put(oss1.rdbuf(), oss1, '+', 30.5);
+ result1 = oss1.str();
+ VERIFY( result1 == "30.500000" );
+
+ oss2.precision(0);
+ oss2.setf(ios_base::scientific, ios_base::floatfield);
+ np2.put(oss2.rdbuf(), oss2, '+', 1.0);
+ result2 = oss2.str();
+ VERIFY( result2 == "1e+00" );
+}
+
int main()
{
test01();
@@ -370,6 +399,7 @@
test03();
test04();
test05();
+ test06();
return 0;
}
diff -urN libstdc++-v3-orig/testsuite/22_locale/num_put_members_wchar_t.cc libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc
--- libstdc++-v3-orig/testsuite/22_locale/num_put_members_wchar_t.cc 2002-10-23 17:45:50.000000000 +0200
+++ libstdc++-v3/testsuite/22_locale/num_put_members_wchar_t.cc 2003-02-07 14:01:09.000000000 +0100
@@ -1,6 +1,6 @@
// 2001-11-19 Benjamin Kosnik <bkoz@redhat.com>
-// Copyright (C) 2001, 2002 Free Software Foundation
+// Copyright (C) 2001, 2002, 2003 Free Software Foundation
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
@@ -362,6 +362,35 @@
result = oss.str();
VERIFY( result == L"0" );
}
+
+// libstdc++/9548 and DR 231
+void test06()
+{
+ using namespace std;
+ bool test = true;
+
+ const locale loc_c = locale::classic();
+
+ wostringstream woss1, woss2;
+ woss1.imbue(loc_c);
+ woss2.imbue(loc_c);
+ const num_put<wchar_t>& np1 = use_facet<num_put<wchar_t> >(woss1.getloc());
+ const num_put<wchar_t>& np2 = use_facet<num_put<wchar_t> >(woss2.getloc());
+
+ wstring result1, result2;
+
+ woss1.precision(-1);
+ woss1.setf(ios_base::fixed, ios_base::floatfield);
+ np1.put(woss1.rdbuf(), woss1, '+', 30.5);
+ result1 = woss1.str();
+ VERIFY( result1 == L"30.500000" );
+
+ woss2.precision(0);
+ woss2.setf(ios_base::scientific, ios_base::floatfield);
+ np2.put(woss2.rdbuf(), woss2, '+', 1.0);
+ result2 = woss2.str();
+ VERIFY( result2 == L"1e+00" );
+}
#endif
int main()
@@ -372,6 +401,7 @@
test03();
test04();
test05();
+ test06();
#endif
return 0;
}