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]

RFC PATCH: 27_io/istream_extractor_arith.cc for !_GLIBCPP_USE_C99


This patch is the best "portable" effort I could do to properly fix
the current assertion failure in 27_io/istream_extractor_arith.cc on
sparc-sun-solaris2.7 and i386-unknown-freebsd4.4 without seeing how it
still fails in various other environments (this patch was basically
done and tested before I read Dave's first input; I did add
speculative support for isinf since I guessed he didn't have finite).

We can debate the merits of leaving a commented abort() in an
configuration path that I don't know how to properly handle.  I have
to think that a controlled crash at the exact point of a problem that
will FAIL a test case is better than forcing others to reverse
engineer the test case.  Something like the pseudo code I offer and/or
Dave's suggestions might work there but I have almost exhausted my
time quota on this problem.  I will work on it more only if this
solution fails for Dave's hpux environment.  We can entirely remove
the abort(), if people find it too distasteful.

More importantly, we can debate the new requirement of including
<ieeefp.h> [of course, only on those hosts found to have it since,
e.g., Solaris doesn't really have finite() unless this file is
included no matter what config.h claims].  The upshot is that we can't
even use _GLIBCPP_HAVE_FINITEF or _GLIBCPP_HAVE_FINITE unless we
include ieeefp.h when _GLIBCPP_HAVE_IEEEFP_H is defined (I would like
to know where that dependency is documented in autoconf).  Perhaps
some indirection through libmath would be useful?  A little help, if
that is indeed the correct path to enlightenment for this issue.  I
only noted this based on the fact that it already includes ieeefp.h,
when possible, and sets up to remap and provide various math functions. ;-)

In fact, we might debate if *all* these inline macro checks within
code seen by the application should be moved into libmath in some
manner... (I think Gaby's comments led me to think this.)

Oh yes, we might also debate on how one really is suppose to test
whether a long double is indeed finite when sscanf("<huge number>",
"%Lf", &__ld) happily writes Inf into __ld and returns 1 and the
platform does not itself provide finitel(). (According to FreeBSD 4
man pages and library source code comments, a long double merely has
more precision not additional range, so this is probably portable as
long as other ports generally mean the same thing which is doubtful. ;-)

For the record, in the float case, FreeBSD 4.4 uses the
_GLIBCPP_HAVE_FINITEF configuration path and Solaris 2.7 uses the
_GLIBCPP_HAVE_FINITE configuration path.  The _GLIBCPP_HAVE_ISINF has
not been tested, but it mirrors the other constructs so I have some
faith (although FreeBSD has isinf and a man page for it, autoconf
doesn't define HAVE_ISINF for reasons I haven't fully debugged).

In the long double case, neither Solaris or FreeBSD checks the
_GLIBCPP_HAVE_FINITEL or HAVE_ISINF configuration paths but they
mirror the other constructs so I have some faith.

Solaris now core dumps inside a sscanf("<huge number>", "%Lf", &__ld)
system library routine while processing the later
``VERIFY(test12_aux<long double>(false))'' test case.  Since I don't
have library source code, I must refuse to bother since the crashing
call site looks legit to me and in accordance with usage allowed by
the local man page of the system (i.e. %Lf is supposed to be supported).

FreeBSD now passes the test with no other regressions tested
against a fully rebuilt libstdc++-v3.  Yea!

I expect comments from the usual suspects.  I wouldn't even dream of
installing this patch without some feedback on the many issues
raised. ;-)

	* include/bits/locale_facets.tcc (ieeefp.h): Include it when
	_GLIBCPP_HAVE_IEEEFP_H is defined.
	(do_get<>(..., float&)): Explicitly check double return for
	overflow from strtod casted to float.  Explicitly abort() when
	we don't know how to check for the FP model of the port.
	(num_get<>(..., long double&): Explicitly check long double
	result for overflow since sscanf will infinity.

Index: libstdc++-v3/include/bits/locale_facets.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/locale_facets.tcc,v
retrieving revision 1.52
diff -c -r1.52 locale_facets.tcc
*** locale_facets.tcc	2002/01/15 04:23:44	1.52
--- locale_facets.tcc	2002/01/17 09:42:39
***************
*** 43,48 ****
--- 43,52 ----
  #include <typeinfo> 		// For bad_cast
  #include <vector>	
  
+ #ifdef _GLIBCPP_HAVE_IEEEFP_H
+ #include <ieeefp.h>
+ #endif
+ 
  namespace std
  {
    template<typename _Facet>
***************
*** 632,638 ****
--- 636,661 ----
        float __f = strtof(__xtrc.c_str(), &__sanity);
  #else
        float __f = static_cast<float>(strtod(__xtrc.c_str(), &__sanity));
+ #ifdef _GLIBCPP_HAVE_FINITEF
+       if (!finitef (__f))
+         __err |= ios_base::failbit;
+ #elif defined (_GLIBCPP_HAVE_FINITE)
+       if (!finite (static_cast<double> (__f)))
+         __err |= ios_base::failbit;
+ #elif defined (_GLIBCPP_HAVE_ISINF)
+       if (isinf (static_cast<double> (__f)))
+         __err |= ios_base::failbit;
+ #else
+       abort (); // Unresolved portability issue.
+       // To whom it may concern, it is possible that the abort can be
+       // replaced with code that implements this pseudo code:
+       // capture double __d1 from strtod(), convert to float __f,
+       // covert __f back to double __d2, compare __d1
+       // against __d2 for equality allowing up to FLT_EPSILON difference;
+       // untested since for all I know it only really would work on IEEE FP
+       // platforms that already support the more elegant mechanisms.
  #endif
+ #endif
        if (!(__err & ios_base::failbit)
            && __sanity != __xtrc.c_str() && *__sanity == '\0' && errno == 0)
          __v = __f;
***************
*** 700,705 ****
--- 723,740 ----
        typedef typename char_traits<_CharT>::int_type int_type;
        long double __ld;
        int __p = sscanf(__xtrc.c_str(), __conv, &__ld);
+ #ifdef _GLIBCPP_HAVE_FINITEL
+       if ((__p == 1) && !finitel (__ld))
+ 	__err |= ios_base::failbit;
+ #elif defined (_GLIBCPP_HAVE_FINITE)
+       if ((__p == 1) && !finite (static_cast<double> (__ld)))
+ 	__err |= ios_base::failbit;
+ #elif defined (_GLIBCPP_HAVE_ISINF)
+       if ((__p == 1) && isinf (static_cast<double> (__ld)))
+         __err |= ios_base::failbit;
+ #else
+       abort ();
+ #endif
        if (!(__err & ios_base::failbit) && __p 
  	  && static_cast<int_type>(__p) != char_traits<_CharT>::eof())
          __v = __ld;


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