This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, RFA] Reworked fix for PR4402


Hi all, hi Benjamin,

I have reworked my original fix for PR4402, adapting it to the new framework, using
_M_convert_float and _M_widen_float. The present version is much smaller, thanks to your
clean ups, but I had to add a parameter to _M_widen_float. Following the current practice,
I used __builtin_alloca in _M_convert_float.

As is, the code in _M_widen_float does not consider the possibility of exotic groupings
(leading to many more separators than 1 every 3 figures). Probably, we can leave this for
another time...

Tested on i686-pc-linux-gnu, as usual.

Cheers,

Paolo Carlini <pcarlini@unitus.it>

        libstdc++/4402
        * testsuite/27_io/ostream_inserter_arith.cc (test02): add testcase from the PR.
        * include/bits/locale_facets.tcc (num_put::_M_widen_float): Add parameter.
        * include/bits/locale_facets.h: Update declaration.
        * include/bits/locale_facets.tcc (num_put::_M_convert_float):
        Deal with long ios_base::fixed floats, update call of _M_widen_float.


diff -urN gcc-vanilla/libstdc++-v3/include/bits/locale_facets.h
gcc/libstdc++-v3/include/bits/locale_facets.h
--- gcc-vanilla/libstdc++-v3/include/bits/locale_facets.h Wed Nov 28 12:57:16 2001
+++ gcc/libstdc++-v3/include/bits/locale_facets.h Sat Dec  1 12:34:53 2001
@@ -752,7 +752,7 @@

       iter_type
       _M_widen_float(iter_type, ios_base& __io, char_type __fill, char* __cs,
-       int __len) const;
+       int __len, int __cs_size) const;

       iter_type
       _M_widen_int(iter_type, ios_base& __io, char_type __fill, char* __cs,
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 Sat Dec  1 13:14:01 2001
@@ -716,17 +716,24 @@
  // 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))
    __len = sprintf(__cs, __fbuf, __prec, __v);
  else
    __len = sprintf(__cs, __fbuf, __v);
- return _M_widen_float(__s, __io, __fill, __cs, __len);
+ return _M_widen_float(__s, __io, __fill, __cs, __len, __cs_size);
       }

   template<typename _CharT, typename _OutIter>
@@ -751,15 +758,19 @@
     _OutIter
     num_put<_CharT, _OutIter>::
     _M_widen_float(_OutIter __s, ios_base& __io, _CharT __fill, char* __cs,
-     int __len) const
+     int __len, int __cs_size) const
     {
       // [22.2.2.2.2] Stage 2, convert to char_type, using correct
       // numpunct.decimal_point() values for '.' and adding grouping.
       const locale __loc = __io.getloc();
       const ctype<_CharT>& __ctype = use_facet<ctype<_CharT> >(__loc);
-      _CharT* __ws = static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * 64));
+      // Grouping needs typically ~1/3 additional chars, but this is
+      // only a first approximation, and more work is needed here to
+      // accurately estimate the optimal size for __ws...
+      _CharT* __ws =
+        static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __cs_size * 4/3));
       __ctype.widen(__cs, __cs + __len, __ws);
-
+
       const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
       // Replace decimal point.
       const _CharT* __p;
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;
 }






Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]