From: Joseph Myers Date: Tue, 4 Nov 2025 17:12:00 +0000 (+0000) Subject: Add C23 long_double_t, _FloatN_t X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=26d11a094424e29971d3fed7ec2db52cb2c3057d;p=thirdparty%2Fglibc.git Add C23 long_double_t, _FloatN_t C23 Annex H adds typedefs long_double_t and _FloatN_t (originally introduced in TS 18661-3), analogous to float_t and double_t. Add these typedefs to glibc. (There are no _FloatNx_t typedefs.) C23 also slightly changes the rules for how such typedef names should be defined, compared to the definition in TS 18661-3. In both cases, _t corresponds to the evaluation format for , as specified by FLT_EVAL_METHOD (for which uses glibc's internal __GLIBC_FLT_EVAL_METHOD). Specifically, each FLT_EVAL_METHOD value corresponds to some type U (for example, 64 corresponds to U = _Float64), and for types with exactly the same set of values as U, TS 18661-3 says expressions with those types are to be evaluated to the range and precision of type U (so _t is defined to U), whereas C23 only does that for types whose values are a strict subset of those of type U (so _t is defined to ). As with other cases where semantics changed between TS 18661 and C23, this patch only implements the newer version of the semantics (including adjusting existing definitions of float_t and double_t as needed). The new semantics are contradictory between the main standard and Annex H for the case of FLT_EVAL_METHOD == 2 and the choice of double_t when double and long double have the same values (the main standard says it's defined as long double in that case, whereas Annex H would define it as double), which I've raised on the WG14 reflector (but I think setting FLT_EVAL_METHOD == 2 when double and long double have the same values is a fairly theoretical combination of features); for now glibc follows the value in the main standard in that case. Note that I think all existing GCC targets supported by glibc only use values -1, 0, 1, 2 or 16 for FLT_EVAL_METHOD (so most of the header code is somewhat theoretical, though potentially relevant with other compilers since the choice of FLT_EVAL_METHOD is only an API choice, not an ABI one; it can vary with compiler options, and these typedefs should not be used in ABIs). The testcase (expanded to cover the new typedefs) is really just repeating the same logic in a second place (so all it really tests is that __GLIBC_FLT_EVAL_METHOD is consistent with FLT_EVAL_METHOD). Tested for x86_64 and x86, and with build-many-glibcs.py. --- diff --git a/NEWS b/NEWS index 6ffc7df286..0f01b751f9 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,10 @@ Major new features: arguments to support expressions with a comma inside a compound literal initializer not surrounded by parentheses. +* The C23 typedef names long_double_t, _Float32_t, _Float64_t, and (on + platforms supporting _Float128) _Float128_t, introduced in TS + 18661-3:2015, have been added to . + Deprecated and removed features, and other changes affecting compatibility: * Support for dumped heaps has been removed - malloc_set_state() now always diff --git a/math/math.h b/math/math.h index b0d99cff8e..61a4338ce3 100644 --- a/math/math.h +++ b/math/math.h @@ -162,34 +162,201 @@ __BEGIN_DECLS to evaluate `float' expressions double_t floating-point type at least as wide as `double' used to evaluate `double' expressions + + TS 18661-3 and C23 additionally define long_double_t and _FloatN_t. */ -# if __GLIBC_FLT_EVAL_METHOD == 0 || __GLIBC_FLT_EVAL_METHOD == 16 +# if __GLIBC_FLT_EVAL_METHOD == 0 typedef float float_t; typedef double double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +typedef long double long_double_t; +# if __HAVE_FLOAT16 +typedef float _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32 _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif # elif __GLIBC_FLT_EVAL_METHOD == 1 typedef double float_t; typedef double double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +typedef long double long_double_t; +# if __HAVE_FLOAT16 +typedef double _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef double _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif # elif __GLIBC_FLT_EVAL_METHOD == 2 typedef long double float_t; typedef long double double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +typedef long double long_double_t; +# if __HAVE_FLOAT16 +typedef long double _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef long double _Float32_t; +# endif +# if __HAVE_FLOAT64 +# ifdef __NO_LONG_DOUBLE_MATH +typedef _Float64 _Float64_t; +# else +typedef long double _Float64_t; +# endif +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif +# elif __GLIBC_FLT_EVAL_METHOD == 16 +typedef float float_t; +typedef double double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +typedef long double long_double_t; +# if __HAVE_FLOAT16 +typedef _Float16 _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32 _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif # elif __GLIBC_FLT_EVAL_METHOD == 32 -typedef _Float32 float_t; +typedef float float_t; typedef double double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +typedef long double long_double_t; +# if __HAVE_FLOAT16 +typedef _Float32 _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32 _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif # elif __GLIBC_FLT_EVAL_METHOD == 33 typedef _Float32x float_t; -typedef _Float32x double_t; +typedef double double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +typedef long double long_double_t; +# if __HAVE_FLOAT16 +typedef _Float32x _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32x _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif # elif __GLIBC_FLT_EVAL_METHOD == 64 typedef _Float64 float_t; -typedef _Float64 double_t; +typedef double double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +typedef long double long_double_t; +# if __HAVE_FLOAT16 +typedef _Float64 _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float64 _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif # elif __GLIBC_FLT_EVAL_METHOD == 65 typedef _Float64x float_t; typedef _Float64x double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +typedef long double long_double_t; +# if __HAVE_FLOAT16 +typedef _Float64x _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float64x _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64x _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif # elif __GLIBC_FLT_EVAL_METHOD == 128 typedef _Float128 float_t; typedef _Float128 double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +# if __HAVE_FLOAT128_UNLIKE_LDBL && __LDBL_MANT_DIG__ != 106 +typedef _Float128 long_double_t; +# else +typedef long double long_double_t; +# endif +# if __HAVE_FLOAT16 +typedef _Float128 _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float128 _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float128 _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 _Float128_t; +# endif +# endif # elif __GLIBC_FLT_EVAL_METHOD == 129 typedef _Float128x float_t; typedef _Float128x double_t; +# if __GLIBC_USE (IEC_60559_TYPES_EXT) +# if __LDBL_MANT_DIG__ != 106 +typedef _Float128x long_double_t; +# else +typedef long double long_double_t; +# endif +# if __HAVE_FLOAT16 +typedef _Float128x _Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float128x _Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float128x _Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128x _Float128_t; +# endif +# endif # else # error "Unknown __GLIBC_FLT_EVAL_METHOD" # endif diff --git a/math/test-flt-eval-method.c b/math/test-flt-eval-method.c index 6fb3e86c15..2996d3de02 100644 --- a/math/test-flt-eval-method.c +++ b/math/test-flt-eval-method.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ +#define __STDC_WANT_IEC_60559_TYPES_EXT__ #include #include @@ -23,33 +24,191 @@ /* Cannot test. */ typedef float_t my_float_t; typedef double_t my_double_t; -#elif FLT_EVAL_METHOD == 0 || FLT_EVAL_METHOD == 16 +typedef long_double_t my_long_double_t; +# if __HAVE_FLOAT16 +typedef _Float16_t my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32_t my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64_t my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128_t my_Float128_t; +# endif +#elif FLT_EVAL_METHOD == 0 typedef float my_float_t; typedef double my_double_t; +typedef long double my_long_double_t; +# if __HAVE_FLOAT16 +typedef float my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32 my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif #elif FLT_EVAL_METHOD == 1 typedef double my_float_t; typedef double my_double_t; +typedef long double my_long_double_t; +# if __HAVE_FLOAT16 +typedef double my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef double my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif #elif FLT_EVAL_METHOD == 2 typedef long double my_float_t; typedef long double my_double_t; +typedef long double my_long_double_t; +# if __HAVE_FLOAT16 +typedef long double my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef long double my_Float32_t; +# endif +# if __HAVE_FLOAT64 +# ifdef __NO_LONG_DOUBLE_MATH +typedef _Float64 my_Float64_t; +# else +typedef long double my_Float64_t; +# endif +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif +#elif FLT_EVAL_METHOD == 16 +typedef float my_float_t; +typedef double my_double_t; +typedef long double my_long_double_t; +# if __HAVE_FLOAT16 +typedef _Float16 my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32 my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif #elif FLT_EVAL_METHOD == 32 -typedef _Float32 my_float_t; +typedef float my_float_t; typedef double my_double_t; +typedef long double my_long_double_t; +# if __HAVE_FLOAT16 +typedef _Float32 my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32 my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif #elif FLT_EVAL_METHOD == 33 typedef _Float32x my_float_t; -typedef _Float32x my_double_t; +typedef double my_double_t; +typedef long double my_long_double_t; +# if __HAVE_FLOAT16 +typedef _Float32x my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float32x my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif #elif FLT_EVAL_METHOD == 64 typedef _Float64 my_float_t; -typedef _Float64 my_double_t; +typedef double my_double_t; +typedef long double my_long_double_t; +# if __HAVE_FLOAT16 +typedef _Float64 my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float64 my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64 my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif #elif FLT_EVAL_METHOD == 65 typedef _Float64x my_float_t; typedef _Float64x my_double_t; +typedef long double my_long_double_t; +# if __HAVE_FLOAT16 +typedef _Float64x my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float64x my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float64x my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif #elif FLT_EVAL_METHOD == 128 typedef _Float128 my_float_t; typedef _Float128 my_double_t; +# if __HAVE_FLOAT128_UNLIKE_LDBL && __LDBL_MANT_DIG__ != 106 +typedef _Float128 my_long_double_t; +# else +typedef long double my_long_double_t; +# endif +# if __HAVE_FLOAT16 +typedef _Float128 my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float128 my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float128 my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128 my_Float128_t; +# endif #elif FLT_EVAL_METHOD == 129 typedef _Float128x my_float_t; typedef _Float128x my_double_t; +# if __LDBL_MANT_DIG__ != 106 +typedef _Float128x my_long_double_t; +# else +typedef long double my_long_double_t; +# endif +# if __HAVE_FLOAT16 +typedef _Float128x my_Float16_t; +# endif +# if __HAVE_FLOAT32 +typedef _Float128x my_Float32_t; +# endif +# if __HAVE_FLOAT64 +typedef _Float128x my_Float64_t; +# endif +# if __HAVE_FLOAT128 +typedef _Float128x my_Float128_t; +# endif #else # error "Unknown FLT_EVAL_METHOD" #endif @@ -60,6 +219,29 @@ extern my_float_t test_float_t; extern double_t test_double_t; extern my_double_t test_double_t; +extern long_double_t test_long_double_t; +extern my_long_double_t test_long_double_t; + +#if __HAVE_FLOAT16 +extern _Float16_t test_Float16_t; +extern my_Float16_t test_Float16_t; +#endif + +#if __HAVE_FLOAT32 +extern _Float32_t test_Float32_t; +extern my_Float32_t test_Float32_t; +#endif + +#if __HAVE_FLOAT64 +extern _Float64_t test_Float64_t; +extern my_Float64_t test_Float64_t; +#endif + +#if __HAVE_FLOAT128 +extern _Float128_t test_Float128_t; +extern my_Float128_t test_Float128_t; +#endif + /* This is a compilation test. */ #define TEST_FUNCTION 0 #include "../test-skeleton.c"