summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/builtin-types.def4
-rw-r--r--gcc/builtins.c33
-rw-r--r--gcc/builtins.def26
-rw-r--r--gcc/doc/extend.texi38
-rw-r--r--gcc/real.c101
-rw-r--r--gcc/real.h2
-rw-r--r--libstdc++-v3/ChangeLog36
-rw-r--r--libstdc++-v3/include/std/std_limits.h210
-rw-r--r--libstdc++-v3/src/limits.cc11
-rw-r--r--libstdc++-v3/testsuite/18_support/numeric_limits.cc99
11 files changed, 359 insertions, 214 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 10ff912287d..85a32f95b38 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2002-09-16 Richard Henderson <rth@redhat.com>
+
+ * builtin-types.def (BT_FN_FLOAT_CONST_STRING): New.
+ (BT_FN_DOUBLE_CONST_STRING, BT_FN_LONG_DOUBLE_CONST_STRING): New.
+ * builtins.def (__builtin_nan, __builtin_nanf, __builtin_nanl): New.
+ (__builtin_nans, __builtin_nansf, __builtin_nansl): New.
+ * builtins.c (fold_builtin_nan): New.
+ (fold_builtin): Call it.
+ * real.c (real_nan): Parse a non-empty string.
+ (round_for_format): Fix NaN significand truncation.
+ * real.h (real_nan): Return bool.
+ * doc/extend.texi: Document new builtins.
+
2002-09-16 Jason Merrill <jason@redhat.com>
Danny Smith <dannysmith@users.sourceforge.net>
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 89bd500b84c..be52392b49b 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -117,6 +117,10 @@ DEF_FUNCTION_TYPE_1 (BT_FN_INT_CONST_STRING, BT_INT, BT_CONST_STRING)
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_PTR, BT_PTR, BT_PTR)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VALIST_REF, BT_VOID, BT_VALIST_REF)
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_INT, BT_VOID, BT_INT)
+DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_CONST_STRING, BT_FLOAT, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_STRING, BT_DOUBLE, BT_CONST_STRING)
+DEF_FUNCTION_TYPE_1 (BT_FN_LONG_DOUBLE_CONST_STRING,
+ BT_LONG_DOUBLE, BT_CONST_STRING)
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_INT, BT_VOID, BT_PTR, BT_INT)
DEF_FUNCTION_TYPE_2 (BT_FN_STRING_STRING_CONST_STRING,
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 2e7cd53323b..25fadab0e21 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -149,6 +149,7 @@ static rtx expand_builtin_expect PARAMS ((tree, rtx));
static tree fold_builtin_constant_p PARAMS ((tree));
static tree fold_builtin_classify_type PARAMS ((tree));
static tree fold_builtin_inf PARAMS ((tree, int));
+static tree fold_builtin_nan PARAMS ((tree, tree, int));
static tree build_function_call_expr PARAMS ((tree, tree));
static int validate_arglist PARAMS ((tree, ...));
@@ -4149,6 +4150,28 @@ fold_builtin_inf (type, warn)
return build_real (type, real);
}
+/* Fold a call to __builtin_nan or __builtin_nans. */
+
+static tree
+fold_builtin_nan (arglist, type, quiet)
+ tree arglist, type;
+ int quiet;
+{
+ REAL_VALUE_TYPE real;
+ const char *str;
+
+ if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE))
+ return 0;
+ str = c_getstr (TREE_VALUE (arglist));
+ if (!str)
+ return 0;
+
+ if (!real_nan (&real, str, quiet, TYPE_MODE (type)))
+ return 0;
+
+ return build_real (type, real);
+}
+
/* Used by constant folding to eliminate some builtin calls early. EXP is
the CALL_EXPR of a call to a builtin function. */
@@ -4190,6 +4213,16 @@ fold_builtin (exp)
case BUILT_IN_HUGE_VALL:
return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), false);
+ case BUILT_IN_NAN:
+ case BUILT_IN_NANF:
+ case BUILT_IN_NANL:
+ return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), true);
+
+ case BUILT_IN_NANS:
+ case BUILT_IN_NANSF:
+ case BUILT_IN_NANSL:
+ return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false);
+
default:
break;
}
diff --git a/gcc/builtins.def b/gcc/builtins.def
index 60acc101fbc..8a3dac33236 100644
--- a/gcc/builtins.def
+++ b/gcc/builtins.def
@@ -427,6 +427,32 @@ DEF_GCC_BUILTIN(BUILT_IN_HUGE_VALL,
BT_FN_LONG_DOUBLE,
ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NAN,
+ "__builtin_nan",
+ BT_FN_DOUBLE_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NANF,
+ "__builtin_nanf",
+ BT_FN_FLOAT_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NANL,
+ "__builtin_nanl",
+ BT_FN_LONG_DOUBLE_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+
+DEF_LIB_BUILTIN(BUILT_IN_NANS,
+ "__builtin_nans",
+ BT_FN_DOUBLE_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NANSF,
+ "__builtin_nansf",
+ BT_FN_FLOAT_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+DEF_LIB_BUILTIN(BUILT_IN_NANSL,
+ "__builtin_nansl",
+ BT_FN_LONG_DOUBLE_CONST_STRING,
+ ATTR_CONST_NOTHROW_LIST)
+
DEF_GCC_BUILTIN(BUILT_IN_SAVEREGS,
"__builtin_saveregs",
BT_FN_PTR_VAR,
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index e9fef2548f4..d3e3eceff89 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -4863,6 +4863,44 @@ Similar to @code{__builtin_inf}, except the return
type is @code{long double}.
@end deftypefn
+@deftypefn {Built-in Function} double __builtin_nan (const char *str)
+This is an implementation of the ISO C99 function @code{nan}.
+
+Since ISO C99 defines this function in terms of @code{strtod}, which we
+do not implement, a desription of the parsing is in order. The string
+is parsed as by @code{strtol}; that is, the base is recognized by
+leading @samp{0} or @samp{0x} prefixes. The number parsed is placed
+in the significand such that the least significant bit of the number
+is at the least significant bit of the significand. The number is
+truncated to fit the significand field provided. The significand is
+forced to be a quiet NaN.
+
+This function, if given a string literal, is evaluated early enough
+that it is considered a compile-time constant.
+@end deftypefn
+
+@deftypefn {Built-in Function} float __builtin_nanf (const char *str)
+Similar to @code{__builtin_nan}, except the return type is @code{float}.
+@end deftypefn
+
+@deftypefn {Built-in Function} long double __builtin_nanl (const char *str)
+Similar to @code{__builtin_nan}, except the return type is @code{long double}.
+@end deftypefn
+
+@deftypefn {Built-in Function} double __builtin_nans (const char *str)
+Similar to @code{__builtin_nan}, except the significand is forced
+to be a signaling NaN. The @code{nans} function is proposed by
+@uref{http://std.dkuug.dk/JTC1/SC22/WG14/www/docs/n965.htm,,WG14 N956}.
+@end deftypefn
+
+@deftypefn {Built-in Function} float __builtin_nansf (const char *str)
+Similar to @code{__builtin_nans}, except the return type is @code{float}.
+@end deftypefn
+
+@deftypefn {Built-in Function} long double __builtin_nansl (const char *str)
+Similar to @code{__builtin_nans}, except the return type is @code{long double}.
+@end deftypefn
+
@node Target Builtins
@section Built-in Functions Specific to Particular Target Machines
diff --git a/gcc/real.c b/gcc/real.c
index 61ab02ce6a9..5859f0ff878 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -1946,16 +1946,22 @@ real_inf (tr)
/* Fills R with a NaN whose significand is described by STR. If QUIET,
we force a QNaN, else we force an SNaN. The string, if not empty,
- is parsed as a number and placed in the significand. */
+ is parsed as a number and placed in the significand. Return true
+ if the string was successfully parsed. */
-void
+bool
real_nan (tr, str, quiet, mode)
REAL_VALUE_TYPE *tr;
const char *str;
int quiet;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+ enum machine_mode mode;
{
struct real_value *r = (struct real_value *) tr;
+ const struct real_format *fmt;
+
+ fmt = fmt_for_mode[mode - QFmode];
+ if (fmt == NULL)
+ abort ();
if (*str == 0)
{
@@ -1965,8 +1971,89 @@ real_nan (tr, str, quiet, mode)
get_canonical_snan (r, 0);
}
else
- /* FIXME */
- abort ();
+ {
+ int base = 10, d;
+ bool neg = false;
+
+ memset (r, 0, sizeof (*r));
+ r->class = rvc_nan;
+
+ /* Parse akin to strtol into the significand of R. */
+
+ while (ISSPACE (*str))
+ str++;
+ if (*str == '-')
+ str++, neg = true;
+ else if (*str == '+')
+ str++;
+ if (*str == '0')
+ {
+ if (*++str == 'x')
+ str++, base = 16;
+ else
+ base = 8;
+ }
+
+ while ((d = hex_value (*str)) < base)
+ {
+ struct real_value u;
+
+ switch (base)
+ {
+ case 8:
+ lshift_significand (r, r, 3);
+ break;
+ case 16:
+ lshift_significand (r, r, 4);
+ break;
+ case 10:
+ lshift_significand_1 (&u, r);
+ lshift_significand (r, r, 3);
+ add_significands (r, r, &u);
+ break;
+ default:
+ abort ();
+ }
+
+ get_zero (&u, 0);
+ u.sig[0] = d;
+ add_significands (r, r, &u);
+
+ str++;
+ }
+
+ /* Must have consumed the entire string for success. */
+ if (*str != 0)
+ return false;
+
+ /* Shift the significand into place such that the bits
+ are in the most significant bits for the format. */
+ lshift_significand (r, r, SIGNIFICAND_BITS - fmt->p);
+
+ /* Our MSB is always unset for NaNs. */
+ r->sig[SIGSZ-1] &= ~SIG_MSB;
+
+ /* Force quiet or signalling NaN. */
+ if (quiet)
+ r->sig[SIGSZ-1] |= SIG_MSB >> 1;
+ else
+ r->sig[SIGSZ-1] &= ~(SIG_MSB >> 1);
+
+ /* Force at least one bit of the significand set. */
+ for (d = 0; d < SIGSZ; ++d)
+ if (r->sig[d])
+ break;
+ if (d == SIGSZ)
+ r->sig[SIGSZ-1] |= SIG_MSB >> 2;
+
+ /* Our intermediate format forces QNaNs to have MSB-1 set.
+ If the target format has QNaNs with the top bit unset,
+ mirror the output routines and invert the top two bits. */
+ if (!fmt->qnan_msb_set)
+ r->sig[SIGSZ-1] ^= (SIG_MSB >> 1) | (SIG_MSB >> 2);
+ }
+
+ return true;
}
/* Fills R with 2**N. */
@@ -2023,7 +2110,7 @@ round_for_format (fmt, r)
return;
case rvc_nan:
- clear_significand_below (r, np2 + 1);
+ clear_significand_below (r, np2);
/* If we've cleared the entire significand, we need one bit
set for this to continue to be a NaN. */
@@ -2031,7 +2118,7 @@ round_for_format (fmt, r)
if (r->sig[i])
break;
if (i == SIGSZ)
- r->sig[SIGSZ-1] = SIG_MSB >> 1;
+ r->sig[SIGSZ-1] = SIG_MSB >> 2;
return;
case rvc_normal:
diff --git a/gcc/real.h b/gcc/real.h
index 31fa56140a9..24df216ec53 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -143,7 +143,7 @@ extern void real_from_target PARAMS ((REAL_VALUE_TYPE *, const long *,
extern void real_inf PARAMS ((REAL_VALUE_TYPE *));
-extern void real_nan PARAMS ((REAL_VALUE_TYPE *, const char *,
+extern bool real_nan PARAMS ((REAL_VALUE_TYPE *, const char *,
int, enum machine_mode));
extern void real_2expN PARAMS ((REAL_VALUE_TYPE *, int));
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 0d8f5c35f3e..ac58d513809 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,39 @@
+2002-09-16 Richard Henderson <rth@redhat.com>
+
+ * include/std/std_limits.h (__glibcpp_f32_QNaN_bytes,
+ __glibcpp_f32_has_QNaN, __glibcpp_f32_SNaN_bytes,
+ __glibcpp_f32_has_SNaN, __glibcpp_f64_QNaN_bytes,
+ __glibcpp_f64_has_QNaN, __glibcpp_f64_SNaN_bytes,
+ __glibcpp_f64_has_SNaN, __glibcpp_f80_QNaN_bytes,
+ __glibcpp_f80_has_QNaN, __glibcpp_f80_SNaN_bytes,
+ __glibcpp_f80_has_SNaN, __glibcpp_f96_QNaN_bytes,
+ __glibcpp_f96_has_QNaN, __glibcpp_f96_SNaN_bytes,
+ __glibcpp_f96_has_SNaN, __glibcpp_f128_QNaN_bytes,
+ __glibcpp_f128_has_QNaN, __glibcpp_f128_SNaN_bytes,
+ __glibcpp_f128_has_SNaN, __glibcpp_float_QNaN_bytes,
+ __glibcpp_float_has_QNaN, __glibcpp_float_SNaN_bytes,
+ __glibcpp_float_has_SNaN, __glibcpp_double_QNaN_bytes,
+ __glibcpp_double_has_QNaN, __glibcpp_double_SNaN_bytes,
+ __glibcpp_double_has_SNaN, __glibcpp_long_double_QNaN_bytes,
+ __glibcpp_long_double_has_QNaN, __glibcpp_long_double_SNaN_bytes,
+ __glibcpp_long_double_has_SNaN): Remove.
+ (__glibcpp_f128_is_iec559): True if IEEE.
+ (__glibcpp_float_QNaN, __glibcpp_float_SNaN): Remove.
+ (__glibcpp_double_QNaN, __glibcpp_double_SNaN): Remove.
+ (__glibcpp_long_double_QNaN, __glibcpp_long_double_SNaN): Remove.
+ (std::numeric_limits<float>::has_quiet_NaN): Use __builtin_nanf.
+ (std::numeric_limits<float>::has_signaling_NaN): Mirror has_quiet_NaN.
+ (std::numeric_limits<float>::quiet_NaN): Use __builtin_nanf.
+ (std::numeric_limits<float>::signaling_NaN): Use __builtin_nansf.
+ (std::numeric_limits<double>): Similarly.
+ (std::numeric_limits<long double>): Similarly.
+ * src/limits.cc (__glibcpp_float_QNaN, __glibcpp_float_SNaN): Remove.
+ (__glibcpp_double_QNaN, __glibcpp_double_SNaN): Remove.
+ (__glibcpp_long_double_QNaN, __glibcpp_long_double_SNaN): Remove.
+
+ * testsuite/18_support/numeric_limits.cc (test_infinity): New.
+ (test_denorm_min, test_qnan, test_is_iec559): New.
+
2002-09-16 Phil Edwards <pme@gcc.gnu.org>
* testsuite/abi_check.cc: Pull shell fragments out into...
diff --git a/libstdc++-v3/include/std/std_limits.h b/libstdc++-v3/include/std/std_limits.h
index 34a3f761387..a1d42244bf8 100644
--- a/libstdc++-v3/include/std/std_limits.h
+++ b/libstdc++-v3/include/std/std_limits.h
@@ -152,115 +152,32 @@
#define __glibcpp_f32_round_error 1.0F
#if __GCC_FLOAT_FORMAT__ == __IEEE_FORMAT__
-# define __glibcpp_f32_QNaN_bytes { 0x7fc00000 }
-# define __glibcpp_f32_has_QNaN true
-# define __glibcpp_f32_SNaN_bytes { 0x7f800001 }
-# define __glibcpp_f32_has_SNaN true
# define __glibcpp_f32_is_iec559 true
#endif
-#ifndef __glibcpp_f32_QNaN_bytes
-# define __glibcpp_f32_QNaN_bytes { }
-# define __glibcpp_f32_has_QNaN false
-#endif
-#ifndef __glibcpp_f32_SNaN_bytes
-# define __glibcpp_f32_SNaN_bytes { }
-# define __glibcpp_f32_has_SNaN false
-#endif
#ifndef __glibcpp_f32_is_iec559
# define __glibcpp_f32_is_iec559 false
#endif
#define __glibcpp_f64_round_error 1.0
#if __GCC_FLOAT_FORMAT__ == __IEEE_FORMAT__
-# if __TARGET_FLOAT_WORDS_ORDER__ == __GCC_BIG_ENDIAN__
-# define __glibcpp_f64_QNaN_bytes { 0x7ff80000, 0x0 }
-# define __glibcpp_f64_SNaN_bytes { 0x7ff00000, 0x1 }
-# else
-# define __glibcpp_f64_QNaN_bytes { 0x0, 0x7ff80000 }
-# define __glibcpp_f64_SNaN_bytes { 0x1, 0x7ff00000 }
-# endif
-# define __glibcpp_f64_has_QNaN true
-# define __glibcpp_f64_has_SNaN true
# define __glibcpp_f64_is_iec559 true
#endif
-#ifndef __glibcpp_f64_QNaN_bytes
-# define __glibcpp_f64_QNaN_bytes { }
-# define __glibcpp_f64_has_QNaN false
-#endif
-#ifndef __glibcpp_f64_SNaN_bytes
-# define __glibcpp_f64_SNaN_bytes { }
-# define __glibcpp_f64_has_SNaN false
-#endif
#ifndef __glibcpp_f64_is_iec559
# define __glibcpp_f64_is_iec559 false
#endif
#define __glibcpp_f80_round_error 1.0L
#if __GCC_FLOAT_FORMAT__ == __IEEE_FORMAT__
-# if __TARGET_BYTES_ORDER__ == __GCC_BIG_ENDIAN__
-# define __glibcpp_f80_QNaN_bytes \
- { 0x7f, 0xff, 0xC0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
-# define __glibcpp_f80_SNaN_bytes \
- { 0x7f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 }
-# else
-# define __glibcpp_f80_QNaN_bytes \
- { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xC0, 0xff, 0x7f }
-# define __glibcpp_f80_SNaN_bytes \
- { 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0xff, 0x7f }
-# endif
-# define __glibcpp_f80_has_QNaN true
-# define __glibcpp_f80_has_SNaN true
# define __glibcpp_f80_is_iec559 true
#endif
-#ifndef __glibcpp_f80_QNaN_bytes
-# define __glibcpp_f80_QNaN_bytes { }
-# define __glibcpp_f80_has_QNaN false
-#endif
-#ifndef __glibcpp_f80_SNaN_bytes
-# define __glibcpp_f80_SNaN_bytes { }
-# define __glibcpp_f80_has_SNaN false
-#endif
#ifndef __glibcpp_f80_is_iec559
# define __glibcpp_f80_is_iec559 false
#endif
#define __glibcpp_f96_round_error 1.0L
#if __GCC_FLOAT_FORMAT__ == __IEEE_FORMAT__
-# if __TARGET_BYTES_ORDER__ == __GCC_BIG_ENDIAN__
-# define __glibcpp_f96_QNaN_bytes { 0x7ff80000, 0x0, 0x0 }
-# define __glibcpp_f96_SNaN_bytes { 0x7ff00000, 0x0, 0x1 }
-# else
-# define __glibcpp_f96_QNaN_bytes { 0x0, 0x0, 0x7ff80000 }
-# define __glibcpp_f96_SNaN_bytes { 0x1, 0x0, 0x7ff00000 }
-# endif
-# define __glibcpp_f96_has_QNaN true
-# define __glibcpp_f96_has_SNaN true
# define __glibcpp_f96_is_iec559 true
#endif
-#ifndef __glibcpp_f96_QNaN_bytes
-# define __glibcpp_f96_QNaN_bytes { }
-# define __glibcpp_f96_has_QNaN false
-#endif
-#ifndef __glibcpp_f96_SNaN_bytes
-# define __glibcpp_f96_SNaN_bytes { }
-# define __glibcpp_f96_has_SNaN false
-#endif
#define __glibcpp_f128_round_error 1.0L
#if __GCC_FLOAT_FORMAT__ == __IEEE_FORMAT__
-# if __TARGET_FLOAT_WORDS_ORDER__ == __GCC_BIG_ENDIAN__
-# define __glibcpp_f128_QNaN_bytes { 0x7fff0800, 0x0, 0x0, 0x0 }
-# define __glibcpp_f128_SNaN_bytes { 0x7fff0000, 0x0, 0x0, 0x1 }
-# else
-# define __glibcpp_f128_QNaN_bytes { 0x0, 0x0, 0x0, 0x7fff0800 }
-# define __glibcpp_f128_SNaN_bytes { 0x1, 0x0, 0x0, 0x7fff0000 }
-# endif
-# define __glibcpp_f128_has_QNaN true
-# define __glibcpp_f128_has_SNaN true
-#endif
-#ifndef __glibcpp_f128_QNaN_bytes
-# define __glibcpp_f128_QNaN_bytes { }
-# define __glibcpp_f128_has_QNaN false
-#endif
-#ifndef __glibcpp_f128_SNaN_bytes
-# define __glibcpp_f128_SNaN_bytes { }
-# define __glibcpp_f128_has_SNaN false
+# define __glibcpp_f128_is_iec559 true
#endif
#ifndef __glibcpp_f128_is_iec559
# define __glibcpp_f128_is_iec559 false
@@ -587,24 +504,12 @@
#if __FLOAT_BIT__ == 32
# define __glibcpp_float_round_error __glibcpp_f32_round_error
-# define __glibcpp_float_QNaN_bytes __glibcpp_f32_QNaN_bytes
-# define __glibcpp_float_SNaN_bytes __glibcpp_f32_SNaN_bytes
-# define __glibcpp_float_has_QNaN __glibcpp_f32_has_QNaN
-# define __glibcpp_float_has_SNaN __glibcpp_f32_has_SNaN
# define __glibcpp_float_is_iec559 __glibcpp_f32_is_iec559
#elif __FLOAT_BIT__ == 64
# define __glibcpp_float_round_error __glibcpp_f64_round_error
-# define __glibcpp_float_QNaN_bytes __glibcpp_f64_QNaN_bytes
-# define __glibcpp_float_SNaN_bytes __glibcpp_f64_SNaN_bytes
-# define __glibcpp_float_has_QNaN __glibcpp_f64_has_QNaN
-# define __glibcpp_float_has_SNaN __glibcpp_f64_has_SNaN
# define __glibcpp_float_is_iec559 __glibcpp_f64_is_iec559
#elif __FLOAT_BIT__ == 80
# define __glibcpp_float_round_error __glibcpp_f80_round_error
-# define __glibcpp_float_QNaN_bytes __glibcpp_f80_QNaN_bytes
-# define __glibcpp_float_SNaN_bytes __glibcpp_f80_SNaN_bytes
-# define __glibcpp_float_has_QNaN __glibcpp_f80_has_QNaN
-# define __glibcpp_float_has_SNaN __glibcpp_f80_has_SNaN
# define __glibcpp_float_is_iec559 __glibcpp_f80_is_iec559
#else
// You must define these macros in the configuration file.
@@ -612,16 +517,6 @@
// Default values. Should be overriden in configuration files if necessary.
-#ifndef __glibcpp_float_QNaN_bytes
-# define __glibcpp_float_QNaN_bytes { }
-# define __glibcpp_float_has_QNaN false
-#endif
-
-#ifndef __glibcpp_float_SNaN_bytes
-# define __glibcpp_float_SNaN_bytes { }
-# define __glibcpp_float_has_SNaN false
-#endif
-
#ifndef __glibcpp_float_has_denorm_loss
# define __glibcpp_float_has_denorm_loss false
#endif
@@ -654,24 +549,12 @@
#if __DOUBLE_BIT__ == 32
# define __glibcpp_double_round_error __glibcpp_f32_round_error
-# define __glibcpp_double_QNaN_bytes __glibcpp_f32_QNaN_bytes
-# define __glibcpp_double_SNaN_bytes __glibcpp_f32_SNaN_bytes
-# define __glibcpp_double_has_QNaN __glibcpp_f32_has_QNaN
-# define __glibcpp_double_has_SNaN __glibcpp_f32_has_SNaN
# define __glibcpp_double_is_iec559 __glibcpp_f32_is_iec559
#elif __DOUBLE_BIT__ == 64
# define __glibcpp_double_round_error __glibcpp_f64_round_error
-# define __glibcpp_double_QNaN_bytes __glibcpp_f64_QNaN_bytes
-# define __glibcpp_double_SNaN_bytes __glibcpp_f64_SNaN_bytes
-# define __glibcpp_double_has_QNaN __glibcpp_f64_has_QNaN
-# define __glibcpp_double_has_SNaN __glibcpp_f64_has_SNaN
# define __glibcpp_double_is_iec559 __glibcpp_f64_is_iec559
#elif __DOUBLE_BIT__ == 80
# define __glibcpp_double_round_error __glibcpp_f80_round_error
-# define __glibcpp_double_QNaN_bytes __glibcpp_f80_QNaN_bytes
-# define __glibcpp_double_SNaN_bytes __glibcpp_f80_SNaN_bytes
-# define __glibcpp_double_has_QNaN __glibcpp_f80_has_QNaN
-# define __glibcpp_double_has_SNaN __glibcpp_f80_has_SNaN
# define __glibcpp_double_is_iec559 __glibcpp_f80_is_iec559
#else
// You must define these macros in the configuration file.
@@ -679,16 +562,6 @@
// Default values. Should be overriden in configuration files if necessary.
-#ifndef __glibcpp_double_QNaN_bytes
-# define __glibcpp_double_QNaN_bytes { }
-# define __glibcpp_double_has_QNaN false
-#endif
-
-#ifndef __glibcpp_double_SNaN_bytes
-# define __glibcpp_double_SNaN_bytes { }
-# define __glibcpp_double_has_SNaN false
-#endif
-
#ifndef __glibcpp_double_has_denorm_loss
# define __glibcpp_double_has_denorm_loss false
#endif
@@ -721,38 +594,18 @@
#if __LONG_DOUBLE_BIT__ == 32
# define __glibcpp_long_double_round_error __glibcpp_f32_round_error
-# define __glibcpp_long_double_QNaN_bytes __glibcpp_f32_QNaN_bytes
-# define __glibcpp_long_double_SNaN_bytes __glibcpp_f32_SNaN_bytes
-# define __glibcpp_long_double_has_QNaN __glibcpp_f32_has_QNaN
-# define __glibcpp_long_double_has_SNaN __glibcpp_f32_has_SNaN
# define __glibcpp_long_double_is_iec559 __glibcpp_f32_is_iec559
#elif __LONG_DOUBLE_BIT__ == 64
# define __glibcpp_long_double_round_error __glibcpp_f64_round_error
-# define __glibcpp_long_double_QNaN_bytes __glibcpp_f64_QNaN_bytes
-# define __glibcpp_long_double_SNaN_bytes __glibcpp_f64_SNaN_bytes
-# define __glibcpp_long_double_has_QNaN __glibcpp_f64_has_QNaN
-# define __glibcpp_long_double_has_SNaN __glibcpp_f64_has_SNaN
# define __glibcpp_long_double_is_iec559 __glibcpp_f64_is_iec559
#elif __LONG_DOUBLE_BIT__ == 80
# define __glibcpp_long_double_round_error __glibcpp_f80_round_error
-# define __glibcpp_long_double_QNaN_bytes __glibcpp_f80_QNaN_bytes
-# define __glibcpp_long_double_SNaN_bytes __glibcpp_f80_SNaN_bytes
-# define __glibcpp_long_double_has_QNaN __glibcpp_f80_has_QNaN
-# define __glibcpp_long_double_has_SNaN __glibcpp_f80_has_SNaN
# define __glibcpp_long_double_is_iec559 __glibcpp_f80_is_iec559
#elif __LONG_DOUBLE_BIT__ == 96
# define __glibcpp_long_double_round_error __glibcpp_f96_round_error
-# define __glibcpp_long_double_QNaN_bytes __glibcpp_f96_QNaN_bytes
-# define __glibcpp_long_double_SNaN_bytes __glibcpp_f96_SNaN_bytes
-# define __glibcpp_long_double_has_QNaN __glibcpp_f96_has_QNaN
-# define __glibcpp_long_double_has_SNaN __glibcpp_f96_has_SNaN
# define __glibcpp_long_double_is_iec559 __glibcpp_f96_is_iec559
#elif __LONG_DOUBLE_BIT__ == 128
# define __glibcpp_long_double_round_error __glibcpp_f128_round_error
-# define __glibcpp_long_double_QNaN_bytes __glibcpp_f128_QNaN_bytes
-# define __glibcpp_long_double_SNaN_bytes __glibcpp_f128_SNaN_bytes
-# define __glibcpp_long_double_has_QNaN __glibcpp_f128_has_QNaN
-# define __glibcpp_long_double_has_SNaN __glibcpp_f128_has_SNaN
# define __glibcpp_long_double_is_iec559 __glibcpp_f128_is_iec559
#else
// You must define these macros in the configuration file.
@@ -760,16 +613,6 @@
// Default values. Should be overriden in configuration files if necessary.
-#ifndef __glibcpp_long_double_QNaN_bytes
-# define __glibcpp_long_double_QNaN_bytes { }
-# define __glibcpp_long_double_has_QNaN false
-#endif
-
-#ifndef __glibcpp_long_double_SNaN_bytes
-# define __glibcpp_long_double_SNaN_bytes { }
-# define __glibcpp_long_double_has_SNaN false
-#endif
-
#ifndef __glibcpp_long_double_has_denorm_loss
# define __glibcpp_long_double_has_denorm_loss false
#endif
@@ -843,15 +686,6 @@ namespace std
#endif
__attribute__((__aligned__(__alignof__(long double))));
- extern const __float_storage __glibcpp_float_QNaN;
- extern const __float_storage __glibcpp_float_SNaN;
-
- extern const __double_storage __glibcpp_double_QNaN;
- extern const __double_storage __glibcpp_double_SNaN;
-
- extern const __long_double_storage __glibcpp_long_double_QNaN;
- extern const __long_double_storage __glibcpp_long_double_SNaN;
-
enum float_round_style
{
round_indeterminate = -1,
@@ -1680,8 +1514,9 @@ namespace std
static const bool has_infinity
= __builtin_huge_valf () / 2 == __builtin_huge_valf ();
- static const bool has_quiet_NaN = __glibcpp_float_has_QNaN;
- static const bool has_signaling_NaN = __glibcpp_float_has_SNaN;
+ static const bool has_quiet_NaN
+ = __builtin_nanf ("") != __builtin_nanf ("");
+ static const bool has_signaling_NaN = has_quiet_NaN;
static const float_denorm_style has_denorm
= __FLT_DENORM_MIN__ ? denorm_present : denorm_absent;
static const bool has_denorm_loss = __glibcpp_float_has_denorm_loss;
@@ -1689,9 +1524,9 @@ namespace std
static float infinity() throw()
{ return __builtin_huge_valf (); }
static float quiet_NaN() throw()
- { return *reinterpret_cast<const float*>(__glibcpp_float_QNaN); }
+ { return __builtin_nanf (""); }
static float signaling_NaN() throw()
- { return *reinterpret_cast<const float*>(__glibcpp_float_SNaN); }
+ { return __builtin_nansf (""); }
static float denorm_min() throw()
{ return __FLT_DENORM_MIN__; }
@@ -1705,8 +1540,6 @@ namespace std
};
#undef __glibcpp_float_round_error
-#undef __glibcpp_float_has_QNaN
-#undef __glibcpp_float_has_SNaN
#undef __glibcpp_float_has_denorm_loss
#undef __glibcpp_float_is_iec559
#undef __glibcpp_float_is_bounded
@@ -1743,8 +1576,9 @@ namespace std
static const bool has_infinity
= __builtin_huge_val () / 2 == __builtin_huge_val ();
- static const bool has_quiet_NaN = __glibcpp_double_has_QNaN;
- static const bool has_signaling_NaN = __glibcpp_double_has_SNaN;
+ static const bool has_quiet_NaN
+ = __builtin_nan ("") != __builtin_nan ("");
+ static const bool has_signaling_NaN = has_quiet_NaN;
static const float_denorm_style has_denorm
= __DBL_DENORM_MIN__ ? denorm_present : denorm_absent;
static const bool has_denorm_loss = __glibcpp_double_has_denorm_loss;
@@ -1752,9 +1586,9 @@ namespace std
static double infinity() throw()
{ return __builtin_huge_val(); }
static double quiet_NaN() throw()
- { return *reinterpret_cast<const double*>(__glibcpp_double_QNaN); }
+ { return __builtin_nan (""); }
static double signaling_NaN() throw()
- { return *reinterpret_cast<const double*>(__glibcpp_double_SNaN); }
+ { return __builtin_nans (""); }
static double denorm_min() throw()
{ return __DBL_DENORM_MIN__; }
@@ -1769,8 +1603,6 @@ namespace std
};
#undef __glibcpp_double_round_error
-#undef __glibcpp_double_has_QNaN
-#undef __glibcpp_double_has_SNaN
#undef __glibcpp_double_has_denorm_loss
#undef __glibcpp_double_is_iec559
#undef __glibcpp_double_is_bounded
@@ -1808,8 +1640,9 @@ namespace std
static const bool has_infinity
= __builtin_huge_vall () / 2 == __builtin_huge_vall ();
- static const bool has_quiet_NaN = __glibcpp_long_double_has_SNaN;
- static const bool has_signaling_NaN = __glibcpp_long_double_has_SNaN;
+ static const bool has_quiet_NaN
+ = __builtin_nanl ("") != __builtin_nanl ("");
+ static const bool has_signaling_NaN = has_quiet_NaN;
static const float_denorm_style has_denorm
= __LDBL_DENORM_MIN__ ? denorm_present : denorm_absent;
static const bool has_denorm_loss
@@ -1817,19 +1650,10 @@ namespace std
static long double infinity() throw()
{ return __builtin_huge_vall (); }
-
static long double quiet_NaN() throw()
- {
- return *reinterpret_cast<const long double*>
- (__glibcpp_long_double_QNaN);
- }
-
+ { return __builtin_nanl (""); }
static long double signaling_NaN() throw()
- {
- return *reinterpret_cast<const long double*>
- (__glibcpp_long_double_SNaN);
- }
-
+ { return __builtin_nansl (""); }
static long double denorm_min() throw()
{ return __LDBL_DENORM_MIN__; }
@@ -1844,8 +1668,6 @@ namespace std
};
#undef __glibcpp_long_double_round_error
-#undef __glibcpp_long_double_has_QNaN
-#undef __glibcpp_long_double_has_SNaN
#undef __glibcpp_long_double_has_denorm_loss
#undef __glibcpp_long_double_is_iec559
#undef __glibcpp_long_double_is_bounded
diff --git a/libstdc++-v3/src/limits.cc b/libstdc++-v3/src/limits.cc
index 93cb3bce3df..294673ea186 100644
--- a/libstdc++-v3/src/limits.cc
+++ b/libstdc++-v3/src/limits.cc
@@ -38,17 +38,6 @@
namespace std
{
- const __float_storage __glibcpp_float_QNaN = __glibcpp_float_QNaN_bytes;
- const __float_storage __glibcpp_float_SNaN = __glibcpp_float_SNaN_bytes;
-
- const __double_storage __glibcpp_double_QNaN = __glibcpp_double_QNaN_bytes;
- const __double_storage __glibcpp_double_SNaN = __glibcpp_double_SNaN_bytes;
-
- const __long_double_storage __glibcpp_long_double_QNaN =
- __glibcpp_long_double_QNaN_bytes;
- const __long_double_storage __glibcpp_long_double_SNaN =
- __glibcpp_long_double_SNaN_bytes;
-
const bool __numeric_limits_base::is_specialized;
const int __numeric_limits_base::digits;
const int __numeric_limits_base::digits10;
diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits.cc b/libstdc++-v3/testsuite/18_support/numeric_limits.cc
index 9d6fa7380c8..75c70277ff6 100644
--- a/libstdc++-v3/testsuite/18_support/numeric_limits.cc
+++ b/libstdc++-v3/testsuite/18_support/numeric_limits.cc
@@ -117,6 +117,83 @@ void test_sign()
template<typename T>
+void
+test_infinity()
+{
+ bool test;
+
+ if (std::numeric_limits<T>::has_infinity)
+ {
+ T inf = std::numeric_limits<T>::infinity();
+ test = (inf + inf == inf);
+ }
+ else
+ test = true;
+
+ VERIFY (test);
+}
+
+template<typename T>
+void
+test_denorm_min()
+{
+ bool test;
+
+ if (std::numeric_limits<T>::has_denorm == std::denorm_present)
+ {
+ T denorm = std::numeric_limits<T>::denorm_min();
+ test = (denorm > 0);
+ }
+ else
+ test = true;
+
+ VERIFY (test);
+}
+
+template<typename T>
+void
+test_qnan()
+{
+ bool test;
+
+ if (std::numeric_limits<T>::has_quiet_NaN)
+ {
+ T nan = std::numeric_limits<T>::quiet_NaN();
+ test = (nan != nan);
+ }
+ else
+ test = true;
+
+ VERIFY (test);
+}
+
+
+template<typename T>
+void
+test_is_iec559()
+{
+ bool test;
+
+ if (std::numeric_limits<T>::is_iec559)
+ {
+ // IEC 559 requires all of the following.
+ test = (std::numeric_limits<T>::has_infinity
+ && std::numeric_limits<T>::has_quiet_NaN
+ && std::numeric_limits<T>::has_signaling_NaN);
+ }
+ else
+ {
+ // If we had all of the following, why didn't we set IEC 559?
+ test = (!std::numeric_limits<T>::has_infinity
+ || !std::numeric_limits<T>::has_quiet_NaN
+ || !std::numeric_limits<T>::has_signaling_NaN);
+ }
+
+ VERIFY (test);
+}
+
+
+template<typename T>
struct A
{
int key;
@@ -237,5 +314,25 @@ int main()
test_sign();
- return 0;
+ test_infinity<float>();
+ test_infinity<double>();
+ test_infinity<long double>();
+
+ test_denorm_min<float>();
+ test_denorm_min<double>();
+ test_denorm_min<long double>();
+
+ test_qnan<float>();
+ test_qnan<double>();
+ test_qnan<long double>();
+
+ // ??? How to test SNaN? We'd perhaps have to be prepared
+ // to catch SIGFPE. Can't rely on a signal getting through
+ // since the exception can be disabled in the FPU.
+
+ test_is_iec559<float>();
+ test_is_iec559<double>();
+ test_is_iec559<long double>();
+
+ return 0;
}