This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Poor me... (was: Re: [PATCH, RFA] Reworked fix for PR4402)
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: Paolo Carlini <pcarlini at unitus dot it>, libstdc++ at gcc dot gnu dot org
- Cc: bkoz at rehdat dot com
- Date: Sun, 02 Dec 2001 01:26:40 +0100
- Subject: Poor me... (was: Re: [PATCH, RFA] Reworked fix for PR4402)
- References: <3C095064.94AA8B4F@unitus.it>
Well...
of course there is *no* grouping at all for float types... (see, f.i., Langer/Kreft 571-572).
May I say that I have been a little bit sidetracked by the comment at the beginning of
_M_widen_float?
So my previous patches were conceptually wrong :( Pragmatically, there was a factor of 4/3
(2), completely unmotivated in the __builtin_alloca call in _M_widen_float.
Anyway, the present proposal, which seems ok to me, shows also an hunk for _M_insert, which
in fact also had (as _M_widen_float and _M_convert_float did) an hardwired 64 in the
__builtin_alloca call (why testing did'nt reveal that?).
This time too, tested i686-pc-linux-gnu.
Yours sleepy,
Paolo Carlini <pcarlini@unitus.it>
libstdc++/4402
* testsuite/27_io/ostream_inserter_arith.cc (test02): add testcase.
* include/bits/locale_facets.tcc (num_put::_M_convert_float): deal
properly with long ios_base::fixed floats.
* include/bits/locale_facets.tcc (num_put::_M_widen_float): use __len in
__builtin_alloca call, correct comment.
* include/bits/locale_facets.tcc (num_put::_M_insert): fix conditional,
use __w in __builtin_alloca call.
diff -urN gcc-vanilla/libstdc++-v3/include/bits/locale_facets.tcc
gcc/libstdc++-v3/include/bits/locale_facets.tcc
--- gcc-vanilla/libstdc++-v3/include/bits/locale_facets.tcc Thu Nov 29 23:59:37 2001
+++ gcc/libstdc++-v3/include/bits/locale_facets.tcc Sun Dec 2 01:07:04 2001
@@ -716,10 +716,18 @@
// Protect against sprintf() buffer overflows.
if (__prec > __max_prec)
__prec = __max_prec;
-
// Long enough for the max format spec.
char __fbuf[16];
- char __cs[64];
+
+ // Consider the possibility of long ios_base::fixed outputs
+ const bool __long_fixed =
+ ((__io.flags() & ios_base::fixed) && (__v < -1e35 || __v > 1e35));
+ const int __cs_size = __long_fixed ?
+ numeric_limits<_ValueT>::max_exponent10 + __max_prec + 4
+ : __max_prec*4;
+ char* __cs =
+ static_cast<char*>(__builtin_alloca(sizeof(char) * __cs_size));
+
int __len;
// [22.2.2.2.2] Stage 1, numeric conversion to character.
if (_S_format_float(__io, __fbuf, __mod, __prec))
@@ -754,12 +762,14 @@
int __len) const
{
// [22.2.2.2.2] Stage 2, convert to char_type, using correct
- // numpunct.decimal_point() values for '.' and adding grouping.
+ // numpunct.decimal_point() values for '.'.
const locale __loc = __io.getloc();
const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
- _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
+
+ _CharT* __ws =
+ static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __len));
__ctype.widen(__cs, __cs + __len, __ws);
-
+
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
// Replace decimal point.
const _CharT* __p;
@@ -810,10 +820,11 @@
int __len) const
{
// [22.2.2.2.2] Stage 3.
- _CharT* __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
streamsize __w = __io.width();
+ _CharT* __ws2;
if (__w > static_cast<streamsize>(__len))
{
+ __ws2 = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __w));
__pad(__io, __fill, __ws2, __ws, __w, __len, true);
__len = static_cast<int>(__w);
// Switch strings.
diff -urN gcc-vanilla/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc
gcc/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc
--- gcc-vanilla/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc Thu Nov 29 23:59:38
2001
+++ gcc/libstdc++-v3/testsuite/27_io/ostream_inserter_arith.cc Sat Dec 1 11:25:07 2001
@@ -272,6 +272,22 @@
#endif
VERIFY(os && os.str() == largebuf);
+ // make sure we can output a long float in fixed format
+ // without seg-faulting (libstdc++/4402)
+ double val2 = 3.5e230;
+
+ ostringstream os2;
+ os2.precision(3);
+ os2.setf(ios::fixed);
+ os2 << val2;
+
+ sprintf(largebuf, "%.*f", 3, val2);
+#ifdef TEST_NUMPUT_VERBOSE
+ cout << "expect: " << largebuf << endl;
+ cout << "result: " << os2.str() << endl;
+#endif
+ VERIFY(os2 && os2.str() == largebuf);
+
return 0;
}