diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index b94c9f510cab9d83de99cb6be8e4cf2ef12704bf..3f75f61715146505dfe16e80fe0920207b540831 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,22 @@
+2005-09-27  Steve Ellcey  <sje@cup.hp.com>
+
+	PR target/23552
+	* acinclude.m4 (LIBGFOR_CHECK_FOR_BROKEN_ISFINITE): New.
+	(LIBGFOR_CHECK_FOR_BROKEN_ISNAN): New.
+	(LIBGFOR_CHECK_FOR_BROKEN_FPCLASSIFY): New.
+	* configure.ac (LIBGFOR_CHECK_FOR_BROKEN_ISFINITE): Add use.
+	(LIBGFOR_CHECK_FOR_BROKEN_ISNAN): Add use.
+	(LIBGFOR_CHECK_FOR_BROKEN_FPCLASSIFY): Add use.
+	* configure: Regenerate.
+	* config.h.in: Regenerate.
+	* libgfortan.h (isfinite): undef if broken, set if needed.
+	(isnan): undef if broken, set if needed.
+        (fpclassify): undef if broken, set if needed.
+	* io/write.c: Remove TODO comment about working isfinite.
+	* intrinsics/c99_functions.c (round): Use isfinite instead
+	of fpclassify.
+	* intrinsics/c99_functions.c (roundf): Ditto.
+
 2005-09-24  Janne Blomqvist <jblomqvi@cc.hut.fi>
 
 	* io.h: Changed prototypes of list_formatted_{read|write}.
diff --git a/libgfortran/acinclude.m4 b/libgfortran/acinclude.m4
index f9fcca666598652be2df1647c89573b55ab65c02..dbf25f3c6362b3436629272d34ba1eaf3a98f2c4 100644
--- a/libgfortran/acinclude.m4
+++ b/libgfortran/acinclude.m4
@@ -230,3 +230,122 @@ esac])])
 if test x"$have_crlf" = xyes; then
   AC_DEFINE(HAVE_CRLF, 1, [Define if CRLF is line terminator.])
 fi])
+
+dnl Check whether isfinite is broken.
+dnl The most common problem is that it does not work on long doubles.
+AC_DEFUN([LIBGFOR_CHECK_FOR_BROKEN_ISFINITE], [
+  AC_CACHE_CHECK([whether isfinite is broken],
+                  have_broken_isfinite, [
+  libgfor_check_for_broken_isfinite_save_LIBS=$LIBS
+  LIBS="$LIBS -lm"
+  AC_TRY_RUN([
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#include <float.h>
+int main ()
+{
+#ifdef isfinite
+#ifdef LDBL_MAX
+  if (!isfinite(LDBL_MAX)) return 1;
+#endif
+#ifdef DBL_MAX
+  if (!isfinite(DBL_MAX)) return 1;
+#endif
+#endif
+return 0;
+}], have_broken_isfinite=no, have_broken_isfinite=yes, [
+case "${target}" in
+  hppa*-*-hpux*) have_broken_isfinite=yes ;;
+  *) have_broken_isfinite=no ;;
+esac])]
+  LIBS=$libgfor_check_for_broken_isfinite_save_LIBS)
+if test x"$have_broken_isfinite" = xyes; then
+  AC_DEFINE(HAVE_BROKEN_ISFINITE, 1, [Define if isfinite is broken.])
+fi])
+
+dnl Check whether isnan is broken.
+dnl The most common problem is that it does not work on long doubles.
+AC_DEFUN([LIBGFOR_CHECK_FOR_BROKEN_ISNAN], [
+  AC_CACHE_CHECK([whether isnan is broken],
+                  have_broken_isnan, [
+  libgfor_check_for_broken_isnan_save_LIBS=$LIBS
+  LIBS="$LIBS -lm"
+  AC_TRY_RUN([
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#include <float.h>
+int main ()
+{
+#ifdef isnan
+#ifdef LDBL_MAX
+  {
+    long double x;
+    x = __builtin_nanl ("");
+    if (!isnan(x)) return 1;
+    if (isnan(LDBL_MAX)) return 1;
+#ifdef NAN
+    x = (long double) NAN;
+    if (!isnan(x)) return 1;
+#endif
+  }
+#endif
+#ifdef DBL_MAX
+  {
+    double y;
+    y = __builtin_nan ("");
+    if (!isnan(y)) return 1;
+    if (isnan(DBL_MAX)) return 1;
+#ifdef NAN
+    y = (double) NAN;
+    if (!isnan(y)) return 1;
+#endif
+  }
+#endif
+#endif
+return 0;
+}], have_broken_isnan=no, have_broken_isnan=yes, [
+case "${target}" in
+  hppa*-*-hpux*) have_broken_isnan=yes ;;
+  *) have_broken_isnan=no ;;
+esac])]
+  LIBS=$libgfor_check_for_broken_isnan_save_LIBS)
+if test x"$have_broken_isnan" = xyes; then
+  AC_DEFINE(HAVE_BROKEN_ISNAN, 1, [Define if isnan is broken.])
+fi])
+
+dnl Check whether fpclassify is broken.
+dnl The most common problem is that it does not work on long doubles.
+AC_DEFUN([LIBGFOR_CHECK_FOR_BROKEN_FPCLASSIFY], [
+  AC_CACHE_CHECK([whether fpclassify is broken],
+                  have_broken_fpclassify, [
+  libgfor_check_for_broken_fpclassify_save_LIBS=$LIBS
+  LIBS="$LIBS -lm"
+  AC_TRY_RUN([
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#include <float.h>
+int main ()
+{
+#ifdef fpclassify
+#ifdef LDBL_MAX
+        if (fpclassify(LDBL_MAX) == FP_NAN
+            || fpclassify(LDBL_MAX) == FP_INFINITE) return 1;
+#endif
+#ifdef DBL_MAX
+        if (fpclassify(DBL_MAX) == FP_NAN
+            || fpclassify(DBL_MAX) == FP_INFINITE) return 1;
+#endif
+#endif
+return 0;
+}], have_broken_fpclassify=no, have_broken_fpclassify=yes, [
+case "${target}" in
+  hppa*-*-hpux*) have_broken_fpclassify=yes ;;
+  *) have_broken_fpclassify=no ;;
+esac])]
+  LIBS=$libgfor_check_for_broken_fpclassify_save_LIBS)
+if test x"$have_broken_fpclassify" = xyes; then
+  AC_DEFINE(HAVE_BROKEN_FPCLASSIFY, 1, [Define if fpclassify is broken.])
+fi])
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index 47f7c2f76c827daaa740937d8b8534a1bcbb36b2..44c45c7767bc126b3f10664504c143fd41f30c46 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -75,6 +75,15 @@
 /* Define to 1 if the target supports __attribute__((visibility(...))). */
 #undef HAVE_ATTRIBUTE_VISIBILITY
 
+/* Define if fpclassify is broken. */
+#undef HAVE_BROKEN_FPCLASSIFY
+
+/* Define if isfinite is broken. */
+#undef HAVE_BROKEN_ISFINITE
+
+/* Define if isnan is broken. */
+#undef HAVE_BROKEN_ISNAN
+
 /* libm includes cabs */
 #undef HAVE_CABS
 
diff --git a/libgfortran/configure b/libgfortran/configure
index 6ace2fb76b15640f5d408c0414b19565e0c49844..5b31d51a64772bd6b57bbf116f2979c9fbbb1319 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -19028,7 +19028,7 @@ _ACEOF
 fi
 
 
-# Hack for AIX
+# On AIX, clog is present in libm as __clog
 echo "$as_me:$LINENO: checking for __clog in -lm" >&5
 echo $ECHO_N "checking for __clog in -lm... $ECHO_C" >&6
 if test "${ac_cv_lib_m___clog+set}" = set; then
@@ -19107,6 +19107,251 @@ _ACEOF
 fi
 
 
+# Check for a isfinite macro that works on long doubles.
+
+  echo "$as_me:$LINENO: checking whether isfinite is broken" >&5
+echo $ECHO_N "checking whether isfinite is broken... $ECHO_C" >&6
+if test "${have_broken_isfinite+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+  libgfor_check_for_broken_isfinite_save_LIBS=$LIBS
+  LIBS="$LIBS -lm"
+  if test "$cross_compiling" = yes; then
+
+case "${target}" in
+  hppa*-*-hpux*) have_broken_isfinite=yes ;;
+  *) have_broken_isfinite=no ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#include <float.h>
+int main ()
+{
+#ifdef isfinite
+#ifdef LDBL_MAX
+  if (!isfinite(LDBL_MAX)) return 1;
+#endif
+#ifdef DBL_MAX
+  if (!isfinite(DBL_MAX)) return 1;
+#endif
+#endif
+return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  have_broken_isfinite=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+have_broken_isfinite=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+  LIBS=$libgfor_check_for_broken_isfinite_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $have_broken_isfinite" >&5
+echo "${ECHO_T}$have_broken_isfinite" >&6
+if test x"$have_broken_isfinite" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_BROKEN_ISFINITE 1
+_ACEOF
+
+fi
+
+# Check for a isnan macro that works on long doubles.
+
+  echo "$as_me:$LINENO: checking whether isnan is broken" >&5
+echo $ECHO_N "checking whether isnan is broken... $ECHO_C" >&6
+if test "${have_broken_isnan+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+  libgfor_check_for_broken_isnan_save_LIBS=$LIBS
+  LIBS="$LIBS -lm"
+  if test "$cross_compiling" = yes; then
+
+case "${target}" in
+  hppa*-*-hpux*) have_broken_isnan=yes ;;
+  *) have_broken_isnan=no ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#include <float.h>
+int main ()
+{
+#ifdef isnan
+#ifdef LDBL_MAX
+  {
+    long double x;
+    x = __builtin_nanl ("");
+    if (!isnan(x)) return 1;
+    if (isnan(LDBL_MAX)) return 1;
+#ifdef NAN
+    x = (long double) NAN;
+    if (!isnan(x)) return 1;
+#endif
+  }
+#endif
+#ifdef DBL_MAX
+  {
+    double y;
+    y = __builtin_nan ("");
+    if (!isnan(y)) return 1;
+    if (isnan(DBL_MAX)) return 1;
+#ifdef NAN
+    y = (double) NAN;
+    if (!isnan(y)) return 1;
+#endif
+  }
+#endif
+#endif
+return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  have_broken_isnan=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+have_broken_isnan=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+  LIBS=$libgfor_check_for_broken_isnan_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $have_broken_isnan" >&5
+echo "${ECHO_T}$have_broken_isnan" >&6
+if test x"$have_broken_isnan" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_BROKEN_ISNAN 1
+_ACEOF
+
+fi
+
+# Check for a fpclassify macro that works on long doubles.
+
+  echo "$as_me:$LINENO: checking whether fpclassify is broken" >&5
+echo $ECHO_N "checking whether fpclassify is broken... $ECHO_C" >&6
+if test "${have_broken_fpclassify+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+  libgfor_check_for_broken_fpclassify_save_LIBS=$LIBS
+  LIBS="$LIBS -lm"
+  if test "$cross_compiling" = yes; then
+
+case "${target}" in
+  hppa*-*-hpux*) have_broken_fpclassify=yes ;;
+  *) have_broken_fpclassify=no ;;
+esac
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#ifdef HAVE_MATH_H
+#include <math.h>
+#endif
+#include <float.h>
+int main ()
+{
+#ifdef fpclassify
+#ifdef LDBL_MAX
+        if (fpclassify(LDBL_MAX) == FP_NAN
+            || fpclassify(LDBL_MAX) == FP_INFINITE) return 1;
+#endif
+#ifdef DBL_MAX
+        if (fpclassify(DBL_MAX) == FP_NAN
+            || fpclassify(DBL_MAX) == FP_INFINITE) return 1;
+#endif
+#endif
+return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  have_broken_fpclassify=no
+else
+  echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+have_broken_fpclassify=yes
+fi
+rm -f core *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+  LIBS=$libgfor_check_for_broken_fpclassify_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $have_broken_fpclassify" >&5
+echo "${ECHO_T}$have_broken_fpclassify" >&6
+if test x"$have_broken_fpclassify" = xyes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_BROKEN_FPCLASSIFY 1
+_ACEOF
+
+fi
+
 # Fallback in case isfinite is not available.
 echo "$as_me:$LINENO: checking for finite in -lm" >&5
 echo $ECHO_N "checking for finite in -lm... $ECHO_C" >&6
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index ebd17b193b1882a3ceae72ce0ffcc74b12f2816c..65f6241637442fef0fcd36de291a8f9db60b77d5 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -328,6 +328,15 @@ AC_CHECK_LIB([m],[ynl],[AC_DEFINE([HAVE_YNL],[1],[libm includes ynl])])
 # On AIX, clog is present in libm as __clog
 AC_CHECK_LIB([m],[__clog],[AC_DEFINE([HAVE_CLOG],[1],[libm includes clog])])
 
+# Check for a isfinite macro that works on long doubles.
+LIBGFOR_CHECK_FOR_BROKEN_ISFINITE
+
+# Check for a isnan macro that works on long doubles.
+LIBGFOR_CHECK_FOR_BROKEN_ISNAN
+
+# Check for a fpclassify macro that works on long doubles.
+LIBGFOR_CHECK_FOR_BROKEN_FPCLASSIFY
+
 # Fallback in case isfinite is not available.
 AC_CHECK_LIB([m],[finite],[AC_DEFINE([HAVE_FINITE],[1],[libm includes finite])])
 
diff --git a/libgfortran/intrinsics/c99_functions.c b/libgfortran/intrinsics/c99_functions.c
index 8083f776df54d782ba9c4b4465996a2eac26790d..2417e69cbed5ab372a0600b534ec592a0ccd5290 100644
--- a/libgfortran/intrinsics/c99_functions.c
+++ b/libgfortran/intrinsics/c99_functions.c
@@ -344,12 +344,8 @@ double
 round(double x)
 {
    double t;
-#if defined(fpclassify)
-   int i;
-   i = fpclassify(x);
-   if (i == FP_INFINITE || i == FP_NAN)
+   if (!isfinite (x))
      return (x);
-#endif
 
    if (x >= 0.0) 
     {
@@ -377,13 +373,8 @@ float
 roundf(float x)
 {
    float t;
-#if defined(fpclassify)
-   int i;
-
-   i = fpclassify(x);
-   if (i == FP_INFINITE || i == FP_NAN)
+   if (!isfinite (x))
      return (x);
-#endif
 
    if (x >= 0.0) 
     {
diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c
index 04361345ffb757667ad3f31f831061d1fa0abafb..c1bf78eca3e39bd6817a0972da590842d359a9be 100644
--- a/libgfortran/io/write.c
+++ b/libgfortran/io/write.c
@@ -821,9 +821,6 @@ write_float (fnode *f, const char *source, int len)
 
   if (f->format != FMT_B && f->format != FMT_O && f->format != FMT_Z)
     {
-      /* TODO: there are some systems where isfinite is not able to work
-               with long double variables. We should detect this case and
-	       provide our own version for isfinite.  */
       res = isfinite (n); 
       if (res == 0)
 	{
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 54aca7e66bc86f3dd5f4d80467c780236d406fd5..191d8d4807065801124a20bca0c7e39c9fbbb2c4 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -177,13 +177,33 @@ typedef off_t gfc_offset;
 
    When isfinite is not available, try to use one of the
    alternatives, or bail out.  */
-#if (!defined(isfinite) || defined(__CYGWIN__))
+
+#if defined(HAVE_BROKEN_ISFINITE) || defined(__CYGWIN__)
 #undef isfinite
-#if defined(fpclassify)
+#endif
+
+#if defined(HAVE_BROKEN_ISNAN)
+#undef isnan
+#endif
+
+#if defined(HAVE_BROKEN_FPCLASSIFY)
+#undef fpclassify
+#endif
+
+#if !defined(isfinite)
+#if !defined(fpclassify)
+#define isfinite(x) ((x) - (x) == 0)
+#else
 #define isfinite(x) (fpclassify(x) != FP_NAN && fpclassify(x) != FP_INFINITE)
+#endif /* !defined(fpclassify) */
+#endif /* !defined(isfinite)  */
+
+#if !defined(isnan)
+#if !defined(fpclassify)
+#define isnan(x) ((x) != (x))
 #else
-#define isfinite(x) ((x) - (x) == 0)
-#endif
+#define isnan(x) (fpclassify(x) == FP_NAN)
+#endif /* !defined(fpclassify) */
 #endif /* !defined(isfinite)  */
 
 /* TODO: find the C99 version of these an move into above ifdef.  */