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: 27_io/istream_extractor_arith.cc (take 2 or 3)


>>> test case.  It is still failing, at least HP and FreeBSD, due to
>>> undetected overflow on double to float cast in a non-C99 code path.

>> Huh. Bummer. Is there a way to fix this up?

> Yes and no.  There is no obvious fix portable to all failing machines.

This version should be even more portable.  Fixes
27_io/istream_extractor_arith.cc on alphaev67-dec-osf5.1 and
i386-unknown-freebsd4.4.  Still cores inside sscanf() whenever first
argument is over 1024 characters on sparc-sun-solaris2.7 but there is
little we can do about that (except observe yet another reason to
rewrite all these input routines from scratch).

First of all, we try harder to use strtof() or strtold() when
available even if all the machinery of C99 was not available
(alphaev67-dec-osf5.1 and hopefully modern HP-UX).  If we still have
to use the other code path, then we try harder to catch error
conditions related to casting strtod() result to float and similar
tightening in the case of handling a long double (helps Solaris 2.7
and FreeBSD).

This code could be further improved once we have a generic portable
way to test for infinity, etc.  I am still looking at how I can
improve errno handling in this file per Nathan's points.

David, does this fix HP-UX for you?  If not, willing to hack on it
further after I commit it?

	* acinclude.m4: Add C++ linkage check for strtof.
	* aclocal.m4: Rebuilt.
	* config.h.in: Rebuilt.
	* configure: Rebuilt.
	* config/locale/c_locale_generic.cc: Conditionally include
	<ieeefp.h>.  Improve handling and error checking of float
	and long double input for non-C99 configurations.

Index: acinclude.m4
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/acinclude.m4,v
retrieving revision 1.189
diff -c -r1.189 acinclude.m4
*** acinclude.m4	2002/01/24 20:46:23	1.189
--- acinclude.m4	2002/02/05 23:39:27
***************
*** 661,666 ****
--- 661,667 ----
    CXXFLAGS='-fno-builtins -D_GNU_SOURCE'
  
    GLIBCPP_CHECK_STDLIB_DECL_AND_LINKAGE_2(strtold)
+   GLIBCPP_CHECK_STDLIB_DECL_AND_LINKAGE_2(strtof)
    AC_CHECK_FUNCS(drand48)
  
    CXXFLAGS="$ac_save_CXXFLAGS"
Index: config/locale/c_locale_generic.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/locale/c_locale_generic.cc,v
retrieving revision 1.7
diff -c -r1.7 c_locale_generic.cc
*** c_locale_generic.cc	2002/01/31 00:47:05	1.7
--- c_locale_generic.cc	2002/01/31 23:01:10
***************
*** 35,40 ****
--- 35,44 ----
  
  #include <locale>
  
+ #ifdef _GLIBCPP_HAVE_IEEEFP_H
+ #include <ieeefp.h>
+ #endif
+ 
  namespace std 
  {
    // Specializations for all types used in num_get.
***************
*** 119,129 ****
  	  const char* __old = setlocale(LC_ALL, "C");
  	  char* __sanity;
  	  errno = 0;
! #ifdef _GLIBCPP_USE_C99
  	  float __f = strtof(__s, &__sanity);
  #else
! 	  float __f = static_cast<float>(strtod(__s, &__sanity));
  #endif
            if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
  	    __v = __f;
  	  else
--- 123,147 ----
  	  const char* __old = setlocale(LC_ALL, "C");
  	  char* __sanity;
  	  errno = 0;
! #if defined(_GLIBCPP_USE_C99) || defined(_GLIBCPP_HAVE_STRTOF)
  	  float __f = strtof(__s, &__sanity);
+ #else
+ 	  double __d = strtod(__s, &__sanity);
+ 	  float __f = static_cast<float>(__d);
+ #ifdef _GLIBCPP_HAVE_FINITEF
+ 	  if (!finitef (__f))
+ 	    errno = ERANGE;
+ #elif defined (_GLIBCPP_HAVE_FINITE)
+ 	  if (!finite (static_cast<double> (__f)))
+ 	    errno = ERANGE;
+ #elif defined (_GLIBCPP_HAVE_ISINF)
+ 	  if (isinf (static_cast<double> (__f)))
+ 	    errno = ERANGE;
  #else
! 	  if (fabs(__d) > numeric_limits<float>::max())
! 	    errno = ERANGE;
  #endif
+ #endif
            if (__sanity != __s && *__sanity == '\0' && errno != ERANGE)
  	    __v = __f;
  	  else
***************
*** 161,167 ****
  	{
  	  // Assumes __s formatted for "C" locale.
  	  const char* __old = setlocale(LC_ALL, "C");
! #if defined(_GLIBCPP_USE_C99) && !defined(__hpux)
  	  char* __sanity;
  	  errno = 0;
  	  long double __ld = strtold(__s, &__sanity);
--- 179,185 ----
  	{
  	  // Assumes __s formatted for "C" locale.
  	  const char* __old = setlocale(LC_ALL, "C");
! #if defined(_GLIBCPP_USE_C99) || defined(_GLIBCPP_HAVE_STRTOLD)
  	  char* __sanity;
  	  errno = 0;
  	  long double __ld = strtold(__s, &__sanity);
***************
*** 170,176 ****
--- 188,201 ----
  #else
  	  typedef char_traits<char>::int_type int_type;
  	  long double __ld;
+ 	  errno = 0;
  	  int __p = sscanf(__s, "%Lf", &__ld);
+ 	  if (errno == ERANGE)
+ 	    __p = 0;
+ #ifdef _GLIBCPP_HAVE_FINITEL
+ 	  if ((__p == 1) && !finitel (__ld))
+ 	    __p = 0;
+ #endif
  	  if (__p && static_cast<int_type>(__p) != char_traits<char>::eof())
  	    __v = __ld;
  #endif


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