Portability of idiom

Loren James Rittle rittle@latour.rsch.comm.mot.com
Tue Jan 29 16:52:00 GMT 2002


On mainline, libstdc++-v3/config/locale/c_locale_generic.cc uses this
idiom (and it is clearly production-quality error checking):

  char* __sanity;
  errno = 0;
  double __d = strtod(__s, &__sanity);
  if (__sanity != __s && *__sanity == '\0' && errno == 0)
    [...]

3.0.X uses the same idiom in libstdc++-v3/include/bits/locale_facets.tcc.

Depending on exactly how one interprets this C99 standard passage:
``The value of errno may be set to nonzero by a library function call
whether or not there is an error, provided the use of errno is not
documented in the description of the function in this International
Standard.'', I could see it go either way.  strtod() is documented by
standard to use errno but it is only documented to ever set it to
ERANGE under some overflow/underflow conditions.  Thus, if it
magically sets errno, e.g. to EINVAL because of a nested library call,
did this implementation of strtod() violate the standard?

Either way, at some point, this line was added to the FreeBSD
implementation of strtod:

  char decimal_point = localeconv()->decimal_point[0];

In this environment, the call to localeconv() can set errno to EINVAL
and thus the behavior of this user-level code changed (4.4 returns 0,
CURRENT returns EINVAL):

#include <errno.h>
#include <stdlib.h>

int main() {
  char* __sanity;
  errno = 0;
  strtod("80.21", &__sanity);
  return errno;
}

I have passed this issue along to David O'Brien but in the interest of
general GCC portability, I wonder if we couldn't revise the error
checking idiom used to only look for the errno settings documented by
the standard.  FYI, this issue is why these tests started failing both
mainline and 3.0.X branch on FreeBSD 5.0 machines:

  FAIL: 26_numerics/complex_inserters_extractors.cc execution test
  FAIL: 27_io/istream_sentry.cc execution test

Regards,
Loren



More information about the Libstdc++ mailing list