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 + + * 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 Danny Smith 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 + + * 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::has_quiet_NaN): Use __builtin_nanf. + (std::numeric_limits::has_signaling_NaN): Mirror has_quiet_NaN. + (std::numeric_limits::quiet_NaN): Use __builtin_nanf. + (std::numeric_limits::signaling_NaN): Use __builtin_nansf. + (std::numeric_limits): Similarly. + (std::numeric_limits): 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 * 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(__glibcpp_float_QNaN); } + { return __builtin_nanf (""); } static float signaling_NaN() throw() - { return *reinterpret_cast(__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(__glibcpp_double_QNaN); } + { return __builtin_nan (""); } static double signaling_NaN() throw() - { return *reinterpret_cast(__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 - (__glibcpp_long_double_QNaN); - } - + { return __builtin_nanl (""); } static long double signaling_NaN() throw() - { - return *reinterpret_cast - (__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 @@ -116,6 +116,83 @@ void test_sign() } +template +void +test_infinity() +{ + bool test; + + if (std::numeric_limits::has_infinity) + { + T inf = std::numeric_limits::infinity(); + test = (inf + inf == inf); + } + else + test = true; + + VERIFY (test); +} + +template +void +test_denorm_min() +{ + bool test; + + if (std::numeric_limits::has_denorm == std::denorm_present) + { + T denorm = std::numeric_limits::denorm_min(); + test = (denorm > 0); + } + else + test = true; + + VERIFY (test); +} + +template +void +test_qnan() +{ + bool test; + + if (std::numeric_limits::has_quiet_NaN) + { + T nan = std::numeric_limits::quiet_NaN(); + test = (nan != nan); + } + else + test = true; + + VERIFY (test); +} + + +template +void +test_is_iec559() +{ + bool test; + + if (std::numeric_limits::is_iec559) + { + // IEC 559 requires all of the following. + test = (std::numeric_limits::has_infinity + && std::numeric_limits::has_quiet_NaN + && std::numeric_limits::has_signaling_NaN); + } + else + { + // If we had all of the following, why didn't we set IEC 559? + test = (!std::numeric_limits::has_infinity + || !std::numeric_limits::has_quiet_NaN + || !std::numeric_limits::has_signaling_NaN); + } + + VERIFY (test); +} + + template struct A { @@ -237,5 +314,25 @@ int main() test_sign(); - return 0; + test_infinity(); + test_infinity(); + test_infinity(); + + test_denorm_min(); + test_denorm_min(); + test_denorm_min(); + + test_qnan(); + test_qnan(); + test_qnan(); + + // ??? 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(); + test_is_iec559(); + test_is_iec559(); + + return 0; }