On Thu, Nov 14, 2024 at 05:10:53PM +0000, Joseph Myers wrote: > On Thu, 14 Nov 2024, Jakub Jelinek wrote: > > > Should DEC64X_SUBNORMAL_MIN/DEC64X_TRUE_MIN macros be defined at all and if > > yes, under the same conditions as the rest? > > C23 only talks about *_TRUE_MIN, not about *_SUBNORMAL_MIN. > > So there should be no DEC64X_SUBNORMAL_MIN (but should be DEC64X_TRUE_MIN, > given __STDC_WANT_IEC_60559_TYPES_EXT__).
Ok, removed. > > Shouldn't the DEC32_MANT_DIG etc. macros also be enabled if just > > __STDC_WANT_IEC_60559_TYPES_EXT__ is defined and no C23? > > No, since __STDC_WANT_IEC_60559_TYPES_EXT__ only relates to _DecimalN for > N not 32, 64 or 128. and _DecimalNx; it doesn't have anything to do with > _Decimal32, _Decimal64 or _Decimal128 (beyond a few encoding conversion > functions that aren't in the main body of the standard at all). Before > C23, _Decimal32, _Decimal64 and _Decimal128 were in TR 24732:2009 > (__STDC_WANT_DEC_FP__) and TS 18661-2 (__STDC_WANT_IEC_60559_DFP_EXT__); > the other types, but not those three, were in TS 18661-3 > (__STDC_WANT_IEC_60559_TYPES_EXT__). Thanks for the clarification. Here is an updated patch, in addition to removing the DEC64X_SUBNORMAL_MIN redefinition I've also adjusted the c23-decimal64x-4.c test to use the __STDC_WANT_IEC_60559_TYPES_EXT__ macro which is now needed and test DEC64X_TRUE_MIN rather than DEC64X_SUBNORMAL_MIN and also verify types of the DEC64X_{MIN,MAX,TRUE_MIN,EPSILON} macro expansions. Smoke tested so far, ok for trunk if it passes full bootstrap/regtest? 2024-11-14 Jakub Jelinek <ja...@redhat.com> gcc/ * tree-core.h (enum tree_index): Add TI_DFLOAT64X_TYPE. * tree.h (dfloat64x_type_node): Define. * tree.cc (build_common_tree_nodes): Initialize dfloat64x_type_node. * builtin-types.def (BT_DFLOAT64X): New DEF_PRIMITIVE_TYPE. (BT_FN_DFLOAT64X): New DEF_FUNCTION_TYPE_0. (BT_FN_DFLOAT64X_CONST_STRING, BT_FN_DFLOAT64X_DFLOAT64X): New DEF_FUNCTION_TYPE_1. * builtins.def (BUILT_IN_FABSD64X, BUILT_IN_INFD64X, BUILT_IN_NAND64X, BUILT_IN_NANSD64X): New builtins. * builtins.cc (expand_builtin): Handle BUILT_IN_FABSD64X. (fold_builtin_0): Handle BUILT_IN_INFD64X. (fold_builtin_1): Handle BUILT_IN_FABSD64X. * fold-const-call.cc (fold_const_call): Handle CFN_BUILT_IN_NAND64X and CFN_BUILT_IN_NANSD64X. * ginclude/float.h (DEC64X_MANT_DIG, DEC64X_MIN_EXP, DEC64X_MAX_EXP, DEC64X_MAX, DEC64X_EPSILON, DEC64X_MIN, DEC64X_TRUE_MIN, DEC64X_SNAN): Redefine. gcc/c-family/ * c-common.h (enum rid): Add RID_DFLOAT64X. * c-common.cc (c_global_trees): Fix comment typo. Add dfloat64x_type_node. (c_common_nodes_and_builtins): Handle RID_DFLOAT64X. * c-cppbuiltin.cc (c_cpp_builtins): Call builtin_define_decimal_float_constants also for dfloat64x_type_node if non-NULL. * c-lex.cc (interpret_float): Handle d64x suffixes. * c-pretty-print.cc (pp_c_floating_constant): Print d64x suffixes on dfloat64x_type_node typed constants. gcc/c/ * c-tree.h (enum c_typespec_keyword): Add cts_dfloat64x and adjust comment. * c-parser.cc (c_keyword_starts_typename, c_token_starts_declspecs, c_parser_declspecs, c_parser_gnu_attribute_any_word): Handle RID_DFLOAT64X. (c_parser_postfix_expression): Handle _Decimal64x arguments in __builtin_tgmath. (warn_for_abs): Handle BUILT_IN_FABSD64X. * c-decl.cc (declspecs_add_type): Handle cts_dfloat64x and RID_DFLOAT64X. (finish_declspecs): Handle cts_dfloat64x. * c-typeck.cc (c_common_type): Handle dfloat64x_type_node. gcc/testsuite/ * gcc.dg/dfp/c11-decimal64x-1.c: New test. * gcc.dg/dfp/c11-decimal64x-2.c: New test. * gcc.dg/dfp/c23-decimal64x-1.c: New test. * gcc.dg/dfp/c23-decimal64x-2.c: New test. * gcc.dg/dfp/c23-decimal64x-3.c: New test. * gcc.dg/dfp/c23-decimal64x-4.c: New test. libcpp/ * expr.cc (interpret_float_suffix): Handle d64x and D64x suffixes, adjust comment. --- gcc/tree-core.h.jj 2024-11-14 17:40:22.509803211 +0100 +++ gcc/tree-core.h 2024-11-14 18:27:43.528231863 +0100 @@ -781,6 +781,7 @@ enum tree_index : unsigned { TI_DFLOAT32_TYPE, TI_DFLOAT64_TYPE, TI_DFLOAT128_TYPE, + TI_DFLOAT64X_TYPE, TI_VOID_LIST_NODE, --- gcc/tree.h.jj 2024-11-14 17:40:22.596801975 +0100 +++ gcc/tree.h 2024-11-14 18:27:43.529231849 +0100 @@ -4537,6 +4537,7 @@ tree_strip_any_location_wrapper (tree ex #define dfloat32_type_node global_trees[TI_DFLOAT32_TYPE] #define dfloat64_type_node global_trees[TI_DFLOAT64_TYPE] #define dfloat128_type_node global_trees[TI_DFLOAT128_TYPE] +#define dfloat64x_type_node global_trees[TI_DFLOAT64X_TYPE] /* The fixed-point types. */ #define sat_short_fract_type_node global_trees[TI_SAT_SFRACT_TYPE] --- gcc/tree.cc.jj 2024-11-14 18:26:16.940458122 +0100 +++ gcc/tree.cc 2024-11-14 18:27:43.531231821 +0100 @@ -9698,6 +9698,11 @@ build_common_tree_nodes (bool signed_cha TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE; SET_TYPE_MODE (dfloat128_type_node, TDmode); layout_type (dfloat128_type_node); + + dfloat64x_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (dfloat64x_type_node) = DECIMAL128_TYPE_SIZE; + SET_TYPE_MODE (dfloat64x_type_node, TDmode); + layout_type (dfloat64x_type_node); } complex_integer_type_node = build_complex_type (integer_type_node, true); --- gcc/builtin-types.def.jj 2024-11-14 17:40:21.966810933 +0100 +++ gcc/builtin-types.def 2024-11-14 18:27:43.531231821 +0100 @@ -202,6 +202,9 @@ DEF_PRIMITIVE_TYPE (BT_DFLOAT64, (dfloat DEF_PRIMITIVE_TYPE (BT_DFLOAT128, (dfloat128_type_node ? dfloat128_type_node : error_mark_node)) +DEF_PRIMITIVE_TYPE (BT_DFLOAT64X, (dfloat64x_type_node + ? dfloat64x_type_node + : error_mark_node)) DEF_PRIMITIVE_TYPE (BT_VALIST_REF, va_list_ref_type_node) DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node) @@ -249,6 +252,7 @@ DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT128X, BT DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT32, BT_DFLOAT32) DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT64, BT_DFLOAT64) DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT128, BT_DFLOAT128) +DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT64X, BT_DFLOAT64X) DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONG, BT_LONG, BT_LONG) DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_LONGLONG, BT_LONGLONG, BT_LONGLONG) @@ -377,6 +381,8 @@ DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_CONS DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_CONST_STRING, BT_DFLOAT64, BT_CONST_STRING) DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_CONST_STRING, BT_DFLOAT128, BT_CONST_STRING) +DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64X_CONST_STRING, BT_DFLOAT64X, + BT_CONST_STRING) DEF_FUNCTION_TYPE_1 (BT_FN_STRING_CONST_STRING, BT_STRING, BT_CONST_STRING) DEF_FUNCTION_TYPE_1 (BT_FN_UNWINDWORD_PTR, BT_UNWINDWORD, BT_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_INT_WINT, BT_INT, BT_WINT) @@ -384,6 +390,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_WINT_WINT, BT DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_DFLOAT32, BT_DFLOAT32, BT_DFLOAT32) DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_DFLOAT64, BT_DFLOAT64, BT_DFLOAT64) DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_DFLOAT128, BT_DFLOAT128, BT_DFLOAT128) +DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64X_DFLOAT64X, BT_DFLOAT64X, BT_DFLOAT64X) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_CONST_PTR, BT_VOID, BT_CONST_PTR) --- gcc/builtins.def.jj 2024-11-14 17:40:21.996810506 +0100 +++ gcc/builtins.def 2024-11-14 18:27:43.532231806 +0100 @@ -387,6 +387,7 @@ DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN DEF_C23_BUILTIN (BUILT_IN_FABSD32, "fabsd32", BT_FN_DFLOAT32_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C23_BUILTIN (BUILT_IN_FABSD64, "fabsd64", BT_FN_DFLOAT64_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C23_BUILTIN (BUILT_IN_FABSD128, "fabsd128", BT_FN_DFLOAT128_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_C23_BUILTIN (BUILT_IN_FABSD64X, "fabsd64x", BT_FN_DFLOAT64X_DFLOAT64X, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_FDIM, "fdim", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_FDIMF, "fdimf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_C99_BUILTIN (BUILT_IN_FDIML, "fdiml", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) @@ -477,6 +478,7 @@ DEF_GCC_FLOATN_NX_BUILTINS (BUILT_IN_INF DEF_GCC_BUILTIN (BUILT_IN_INFD32, "infd32", BT_FN_DFLOAT32, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_INFD64, "infd64", BT_FN_DFLOAT64, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_INFD128, "infd128", BT_FN_DFLOAT128, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_GCC_BUILTIN (BUILT_IN_INFD64X, "infd64x", BT_FN_DFLOAT64X, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_IRINT, "irint", BT_FN_INT_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_GCC_BUILTIN (BUILT_IN_IRINTF, "irintf", BT_FN_INT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) DEF_GCC_BUILTIN (BUILT_IN_IRINTL, "irintl", BT_FN_INT_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO) @@ -575,6 +577,7 @@ DEF_EXT_LIB_FLOATN_NX_BUILTINS (BUILT_IN DEF_C23_BUILTIN (BUILT_IN_NAND32, "nand32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_C23_BUILTIN (BUILT_IN_NAND64, "nand64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_C23_BUILTIN (BUILT_IN_NAND128, "nand128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) +DEF_C23_BUILTIN (BUILT_IN_NAND64X, "nand64x", BT_FN_DFLOAT64X_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANS, "nans", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) @@ -584,6 +587,7 @@ DEF_GCC_BUILTIN (BUILT_IN_NANSF16 DEF_GCC_BUILTIN (BUILT_IN_NANSD32, "nansd32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANSD64, "nansd64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_GCC_BUILTIN (BUILT_IN_NANSD128, "nansd128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) +DEF_GCC_BUILTIN (BUILT_IN_NANSD64X, "nansd64x", BT_FN_DFLOAT64X_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL) DEF_C99_BUILTIN (BUILT_IN_NEARBYINT, "nearbyint", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_NEARBYINTF, "nearbyintf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_C99_BUILTIN (BUILT_IN_NEARBYINTL, "nearbyintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LEAF_LIST) --- gcc/builtins.cc.jj 2024-11-14 18:26:16.854459340 +0100 +++ gcc/builtins.cc 2024-11-14 18:27:43.533231792 +0100 @@ -7851,6 +7851,7 @@ expand_builtin (tree exp, rtx target, rt case BUILT_IN_FABSD32: case BUILT_IN_FABSD64: case BUILT_IN_FABSD128: + case BUILT_IN_FABSD64X: target = expand_builtin_fabs (exp, target, subtarget); if (target) return target; @@ -10447,6 +10448,7 @@ fold_builtin_0 (location_t loc, tree fnd case BUILT_IN_INFD32: case BUILT_IN_INFD64: case BUILT_IN_INFD128: + case BUILT_IN_INFD64X: return fold_builtin_inf (loc, type, true); CASE_FLT_FN (BUILT_IN_HUGE_VAL): @@ -10509,6 +10511,7 @@ fold_builtin_1 (location_t loc, tree exp case BUILT_IN_FABSD32: case BUILT_IN_FABSD64: case BUILT_IN_FABSD128: + case BUILT_IN_FABSD64X: return fold_builtin_fabs (loc, arg0, type); case BUILT_IN_ABS: --- gcc/fold-const-call.cc.jj 2024-11-14 17:40:22.383805003 +0100 +++ gcc/fold-const-call.cc 2024-11-14 18:27:43.534231778 +0100 @@ -1350,6 +1350,7 @@ fold_const_call (combined_fn fn, tree ty case CFN_BUILT_IN_NAND32: case CFN_BUILT_IN_NAND64: case CFN_BUILT_IN_NAND128: + case CFN_BUILT_IN_NAND64X: return fold_const_builtin_nan (type, arg, true); CASE_CFN_NANS: @@ -1358,6 +1359,7 @@ fold_const_call (combined_fn fn, tree ty case CFN_BUILT_IN_NANSD32: case CFN_BUILT_IN_NANSD64: case CFN_BUILT_IN_NANSD128: + case CFN_BUILT_IN_NANSD64X: return fold_const_builtin_nan (type, arg, false); case CFN_REDUC_PLUS: --- gcc/ginclude/float.h.jj 2024-11-14 17:40:22.383805003 +0100 +++ gcc/ginclude/float.h 2024-11-14 18:28:54.095232002 +0100 @@ -602,6 +602,23 @@ see the files COPYING3 and COPYING.RUNTI #endif /* __STDC_WANT_IEC_60559_DFP_EXT__ || C23. */ +#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__ +#undef DEC64X_MANT_DIG +#define DEC64X_MANT_DIG __DEC64X_MANT_DIG__ +#undef DEC64X_MIN_EXP +#define DEC64X_MIN_EXP __DEC64X_MIN_EXP__ +#undef DEC64X_MAX_EXP +#define DEC64X_MAX_EXP __DEC64X_MAX_EXP__ +#undef DEC64X_MAX +#define DEC64X_MAX __DEC64X_MAX__ +#undef DEC64X_EPSILON +#define DEC64X_EPSILON __DEC64X_EPSILON__ +#undef DEC64X_MIN +#define DEC64X_MIN __DEC64X_MIN__ +#undef DEC64X_TRUE_MIN +#define DEC64X_TRUE_MIN __DEC64X_SUBNORMAL_MIN__ +#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__ */ + #if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L /* Infinity in type _Decimal32. */ @@ -619,6 +636,10 @@ see the files COPYING3 and COPYING.RUNTI #define DEC64_SNAN (__builtin_nansd64 ("")) #undef DEC128_SNAN #define DEC128_SNAN (__builtin_nansd128 ("")) +#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__ +#undef DEC64X_SNAN +#define DEC64X_SNAN (__builtin_nansd64x ("")) +#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__ */ #endif /* C23 */ --- gcc/c/c-tree.h.jj 2024-11-14 17:40:22.175807961 +0100 +++ gcc/c/c-tree.h 2024-11-14 18:27:43.534231778 +0100 @@ -287,8 +287,8 @@ enum c_storage_class { }; /* A type specifier keyword "void", "_Bool", "char", "int", "float", - "double", "_Decimal32", "_Decimal64", "_Decimal128", "_Fract", "_Accum", - "_BitInt", or none of these. */ + "double", "_Decimal32", "_Decimal64", "_Decimal128", "_Decimal64x", + "_Fract", "_Accum", "_BitInt", or none of these. */ enum c_typespec_keyword { cts_none, cts_void, @@ -301,6 +301,7 @@ enum c_typespec_keyword { cts_dfloat32, cts_dfloat64, cts_dfloat128, + cts_dfloat64x, cts_floatn_nx, cts_fract, cts_accum, --- gcc/c/c-parser.cc.jj 2024-11-14 17:40:22.174807975 +0100 +++ gcc/c/c-parser.cc 2024-11-14 18:27:43.537231735 +0100 @@ -597,6 +597,7 @@ c_keyword_starts_typename (enum rid keyw case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + case RID_DFLOAT64X: CASE_RID_FLOATN_NX: case RID_BOOL: case RID_BITINT: @@ -801,6 +802,7 @@ c_token_starts_declspecs (c_token *token case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + case RID_DFLOAT64X: CASE_RID_FLOATN_NX: case RID_BOOL: case RID_BITINT: @@ -3505,6 +3507,7 @@ c_parser_declspecs (c_parser *parser, st case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + case RID_DFLOAT64X: CASE_RID_FLOATN_NX: case RID_BOOL: case RID_FRACT: @@ -5229,6 +5232,7 @@ c_parser_gnu_attribute_any_word (c_parse case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + case RID_DFLOAT64X: CASE_RID_FLOATN_NX: case RID_BOOL: case RID_BITINT: @@ -11897,6 +11901,7 @@ c_parser_postfix_expression (c_parser *p bool arg_binary = all_binary; bool arg_int_decimal = all_decimal; bool arg_int_floatnx = false; + bool arg_int_decimalx = false; for (unsigned int j = 1; j <= nargs; j++) { if (parm_kind[j] == tgmath_fixed) @@ -12001,6 +12006,8 @@ c_parser_postfix_expression (c_parser *p arg_int_floatnx = true; break; } + if (rtype == dfloat64x_type_node) + arg_int_decimalx = true; } tree arg_real = NULL_TREE; for (unsigned int j = 1; j <= nargs; j++) @@ -12012,10 +12019,12 @@ c_parser_postfix_expression (c_parser *p if (TREE_CODE (type) == COMPLEX_TYPE) type = TREE_TYPE (type); if (INTEGRAL_TYPE_P (type)) - type = (arg_int_decimal - ? dfloat64_type_node + type = (arg_int_decimalx + ? dfloat64x_type_node : arg_int_floatnx ? float32x_type_node + : arg_int_decimal + ? dfloat64_type_node : double_type_node); if (arg_real == NULL_TREE) arg_real = type; @@ -13173,6 +13182,7 @@ warn_for_abs (location_t loc, tree fndec case BUILT_IN_FABSD32: case BUILT_IN_FABSD64: case BUILT_IN_FABSD128: + case BUILT_IN_FABSD64X: if (!DECIMAL_FLOAT_TYPE_P (atype)) { if (INTEGRAL_TYPE_P (atype)) --- gcc/c/c-decl.cc.jj 2024-11-14 17:40:22.147808359 +0100 +++ gcc/c/c-decl.cc 2024-11-14 18:27:43.539231707 +0100 @@ -12119,6 +12119,10 @@ declspecs_add_type (location_t loc, stru error_at (loc, ("both %<long%> and %<_Decimal128%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat64x) + error_at (loc, + ("both %<long%> and %<_Decimal64x%> in " + "declaration specifiers")); else { specs->long_p = true; @@ -12184,6 +12188,10 @@ declspecs_add_type (location_t loc, stru error_at (loc, ("both %<short%> and %<_Decimal128%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat64x) + error_at (loc, + ("both %<short%> and %<_Decimal64x%> in " + "declaration specifiers")); else { specs->short_p = true; @@ -12236,6 +12244,10 @@ declspecs_add_type (location_t loc, stru error_at (loc, ("both %<signed%> and %<_Decimal128%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat64x) + error_at (loc, + ("both %<signed%> and %<_Decimal64x%> in " + "declaration specifiers")); else { specs->signed_p = true; @@ -12288,6 +12300,10 @@ declspecs_add_type (location_t loc, stru error_at (loc, ("both %<unsigned%> and %<_Decimal128%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat64x) + error_at (loc, + ("both %<unsigned%> and %<_Decimal64x%> in " + "declaration specifiers")); else { specs->unsigned_p = true; @@ -12327,6 +12343,10 @@ declspecs_add_type (location_t loc, stru error_at (loc, ("both %<complex%> and %<_Decimal128%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat64x) + error_at (loc, + ("both %<complex%> and %<_Decimal64x%> in " + "declaration specifiers")); else if (specs->typespec_word == cts_fract) error_at (loc, ("both %<complex%> and %<_Fract%> in " @@ -12408,6 +12428,10 @@ declspecs_add_type (location_t loc, stru error_at (loc, ("both %<_Sat%> and %<_Decimal128%> in " "declaration specifiers")); + else if (specs->typespec_word == cts_dfloat64x) + error_at (loc, + ("both %<_Sat%> and %<_Decimal64x%> in " + "declaration specifiers")); else if (specs->complex_p) error_at (loc, ("both %<_Sat%> and %<complex%> in " @@ -12733,14 +12757,17 @@ declspecs_add_type (location_t loc, stru case RID_DFLOAT32: case RID_DFLOAT64: case RID_DFLOAT128: + case RID_DFLOAT64X: { const char *str; if (i == RID_DFLOAT32) str = "_Decimal32"; else if (i == RID_DFLOAT64) str = "_Decimal64"; - else + else if (i == RID_DFLOAT128) str = "_Decimal128"; + else + str = "_Decimal64x"; if (specs->long_long_p) error_at (loc, ("both %<long long%> and %qs in " @@ -12780,8 +12807,10 @@ declspecs_add_type (location_t loc, stru specs->typespec_word = cts_dfloat32; else if (i == RID_DFLOAT64) specs->typespec_word = cts_dfloat64; - else + else if (i == RID_DFLOAT128) specs->typespec_word = cts_dfloat128; + else + specs->typespec_word = cts_dfloat64x; specs->locations[cdw_typespec] = loc; } if (!targetm.decimal_float_supported_p ()) @@ -13350,6 +13379,7 @@ finish_declspecs (struct c_declspecs *sp case cts_dfloat32: case cts_dfloat64: case cts_dfloat128: + case cts_dfloat64x: gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p && !specs->signed_p && !specs->unsigned_p && !specs->complex_p); if (!targetm.decimal_float_supported_p ()) @@ -13358,8 +13388,10 @@ finish_declspecs (struct c_declspecs *sp specs->type = dfloat32_type_node; else if (specs->typespec_word == cts_dfloat64) specs->type = dfloat64_type_node; - else + else if (specs->typespec_word == cts_dfloat128) specs->type = dfloat128_type_node; + else + specs->type = dfloat64x_type_node; break; case cts_fract: gcc_assert (!specs->complex_p); --- gcc/c/c-typeck.cc.jj 2024-11-14 17:40:22.199807620 +0100 +++ gcc/c/c-typeck.cc 2024-11-14 18:27:43.541231678 +0100 @@ -1158,6 +1158,11 @@ c_common_type (tree t1, tree t2) if (TYPE_MAIN_VARIANT (t1) == dfloat128_type_node || TYPE_MAIN_VARIANT (t2) == dfloat128_type_node) return dfloat128_type_node; + /* And prefer _Decimal128 over _Decimal64x which has in GCC's + implementation the same mode. */ + else if (TYPE_MAIN_VARIANT (t1) == dfloat64x_type_node + || TYPE_MAIN_VARIANT (t2) == dfloat64x_type_node) + return dfloat64x_type_node; else if (TYPE_MAIN_VARIANT (t1) == dfloat64_type_node || TYPE_MAIN_VARIANT (t2) == dfloat64_type_node) return dfloat64_type_node; --- gcc/c-family/c-common.h.jj 2024-11-14 17:40:22.041809866 +0100 +++ gcc/c-family/c-common.h 2024-11-14 18:27:43.541231678 +0100 @@ -111,7 +111,7 @@ enum rid RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH, RID_BUILTIN_HAS_ATTRIBUTE, RID_BUILTIN_ASSOC_BARRIER, RID_BUILTIN_STDC, RID_BUILTIN_COUNTED_BY_REF, - RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, + RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, RID_DFLOAT64X, /* TS 18661-3 keywords, in the same sequence as the TI_* values. */ RID_FLOAT16, --- gcc/c-family/c-common.cc.jj 2024-11-14 18:26:16.856459312 +0100 +++ gcc/c-family/c-common.cc 2024-11-14 18:27:43.542231664 +0100 @@ -100,7 +100,8 @@ machine_mode c_default_pointer_mode = VO tree dfloat32_type_node; tree dfloat64_type_node; - tree_dfloat128_type_node; + tree dfloat128_type_node; + tree dfloat64x_type_node; tree intQI_type_node; tree intHI_type_node; @@ -407,6 +408,7 @@ const struct c_common_resword c_common_r { "_Decimal32", RID_DFLOAT32, D_CONLY }, { "_Decimal64", RID_DFLOAT64, D_CONLY }, { "_Decimal128", RID_DFLOAT128, D_CONLY }, + { "_Decimal64x", RID_DFLOAT64X, D_CONLY }, { "_Fract", RID_FRACT, D_CONLY | D_EXT }, { "_Accum", RID_ACCUM, D_CONLY | D_EXT }, { "_Sat", RID_SAT, D_CONLY | D_EXT }, @@ -4480,6 +4482,7 @@ c_common_nodes_and_builtins (void) record_builtin_type (RID_DFLOAT32, NULL, dfloat32_type_node); record_builtin_type (RID_DFLOAT64, NULL, dfloat64_type_node); record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node); + record_builtin_type (RID_DFLOAT64X, NULL, dfloat64x_type_node); } if (targetm.fixed_point_supported_p ()) --- gcc/c-family/c-cppbuiltin.cc.jj 2024-11-14 17:40:22.042809852 +0100 +++ gcc/c-family/c-cppbuiltin.cc 2024-11-14 18:27:43.543231650 +0100 @@ -1323,6 +1323,9 @@ c_cpp_builtins (cpp_reader *pfile) dfloat64_type_node); builtin_define_decimal_float_constants ("DEC128", "DL", dfloat128_type_node); + if (dfloat64x_type_node) + builtin_define_decimal_float_constants ("DEC64X", "D64x", + dfloat64x_type_node); } /* For fixed-point fibt, ibit, max, min, and epsilon. */ --- gcc/c-family/c-lex.cc.jj 2024-11-14 17:40:22.042809852 +0100 +++ gcc/c-family/c-lex.cc 2024-11-14 18:27:43.543231650 +0100 @@ -1235,6 +1235,8 @@ interpret_float (const cpp_token *token, type = dfloat128_type_node; else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL) type = dfloat32_type_node; + else if ((flags & CPP_N_FLOATNX) != 0) + type = dfloat64x_type_node; else type = dfloat64_type_node; else @@ -1350,6 +1352,8 @@ interpret_float (const cpp_token *token, { if (ISDIGIT (token->val.str.text[copylen - 1])) copylen -= (flags & CPP_N_LARGE) ? 4 : 3; + else if ((flags & CPP_N_FLOATNX) != 0) + copylen -= 4; else copylen -= 2; } --- gcc/c-family/c-pretty-print.cc.jj 2024-11-14 17:40:22.067809496 +0100 +++ gcc/c-family/c-pretty-print.cc 2024-11-14 18:27:43.543231650 +0100 @@ -1159,6 +1159,8 @@ pp_c_floating_constant (c_pretty_printer pp_string (pp, "dd"); else if (TREE_TYPE (r) == dfloat32_type_node) pp_string (pp, "df"); + else if (TREE_TYPE (r) == dfloat64x_type_node) + pp_string (pp, "d64x"); else if (TREE_TYPE (r) != double_type_node) for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) if (TREE_TYPE (r) == FLOATN_NX_TYPE_NODE (i)) --- gcc/testsuite/gcc.dg/dfp/c11-decimal64x-1.c.jj 2024-11-14 18:27:43.543231650 +0100 +++ gcc/testsuite/gcc.dg/dfp/c11-decimal64x-1.c 2024-11-14 18:27:43.543231650 +0100 @@ -0,0 +1,7 @@ +/* Test that DFP constants and _Decimal64x keyword are diagnosed in C11 mode: -pedantic. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic" } */ + +int a = (int) 1.1D64x; /* { dg-warning "C23 feature" } */ +int b = (int) 2.d64x; /* { dg-warning "C23 feature" } */ +_Decimal64x c = 1; /* { dg-warning "ISO C does not support decimal floating-point before C23" } */ --- gcc/testsuite/gcc.dg/dfp/c11-decimal64x-2.c.jj 2024-11-14 18:27:43.544231635 +0100 +++ gcc/testsuite/gcc.dg/dfp/c11-decimal64x-2.c 2024-11-14 18:27:43.544231635 +0100 @@ -0,0 +1,7 @@ +/* Test that DFP constants and _Decimal64x keyword are diagnosed in C11 mode: -pedantic-errors. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ + +int a = (int) 1.1D64x; /* { dg-error "C23 feature" } */ +int b = (int) 2.d64x; /* { dg-error "C23 feature" } */ +_Decimal64x c = 1; /* { dg-error "ISO C does not support decimal floating-point before C23" } */ --- gcc/testsuite/gcc.dg/dfp/c23-decimal64x-1.c.jj 2024-11-14 18:27:43.544231635 +0100 +++ gcc/testsuite/gcc.dg/dfp/c23-decimal64x-1.c 2024-11-14 18:27:43.544231635 +0100 @@ -0,0 +1,74 @@ +/* Test _Decimal64x in C23 mode. */ +/* { dg-do run } */ +/* { dg-options "-std=c23 -pedantic-errors" } */ + +int a = (int) 1.1D64x; +int b = (int) 2.d64x; +_Decimal64x c = 1; + +#define expr_has_type(e, t) _Generic (e, default : 0, t : 1) +static_assert (expr_has_type (1.1D64x, _Decimal64x)); +static_assert (expr_has_type (2.d64x, _Decimal64x)); +static_assert (expr_has_type (.33D64x, _Decimal64x)); +static_assert (expr_has_type (2e1d64x, _Decimal64x)); +static_assert (expr_has_type (.3e2D64x, _Decimal64x)); +static_assert (expr_has_type (4.5e3d64x, _Decimal64x)); +static_assert (expr_has_type (5.e0D64x, _Decimal64x)); +static_assert (expr_has_type (1e+2d64x, _Decimal64x)); +static_assert (expr_has_type (1000e-3D64x, _Decimal64x)); +static_assert (expr_has_type (__DEC64X_MIN__, _Decimal64x)); +static_assert (expr_has_type (__DEC64X_MAX__, _Decimal64x)); +static_assert (expr_has_type (__DEC64X_EPSILON__, _Decimal64x)); +static_assert (expr_has_type (__DEC64X_SUBNORMAL_MIN__, _Decimal64x)); +#if __DEC64X_MANT_DIG__ == __DEC128_MANT_DIG__ \ + && __DEC64X_MAX_EXP__ == __DEC128_MAX_EXP__ +static_assert (expr_has_type (1.1D32 + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1.1D64 + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1.1D128 + 1.1D64x, _Decimal128)); +static_assert (expr_has_type (1 + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1U + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1L + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1UL + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1LL + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1ULL + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1.1D32, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1.1D64, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1.1D64x, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1.1D128, _Decimal128)); +static_assert (expr_has_type (1.1D64x + 1, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1U, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1L, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1UL, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1LL, _Decimal64x)); +static_assert (expr_has_type (1.1D64x + 1ULL, _Decimal64x)); +#endif + +_Decimal64x +foo (_Decimal64x x, _Decimal64x y) +{ + return x + y; +} + +int +main () +{ +#if __DEC64X_MANT_DIG__ == __DEC128_MANT_DIG__ \ + && __DEC64X_MAX_EXP__ == __DEC128_MAX_EXP__ + if (1.1D64x != 1.1dl + || 2.d64x != 2.dl + || .33D64x != .33dl + || 2e1d64x != 2e1dl + || .3e2D64x != .3e2dl + || 4.5e3d64x != 4.5e3dl + || 5.e0D64x != 5.e0dl + || 1e+2d64x != 1e+2dl + || 1000e-3D64x != 1000e-3dl + || __DEC64X_MIN__ != __DEC128_MIN__ + || __DEC64X_MAX__ != __DEC128_MAX__ + || __DEC64X_EPSILON__ != __DEC128_EPSILON__ + || __DEC64X_SUBNORMAL_MIN__ != __DEC128_SUBNORMAL_MIN__ + || foo (0.5d64x, 0.5D64x) != 1.D64x) + __builtin_abort (); +#endif +} --- gcc/testsuite/gcc.dg/dfp/c23-decimal64x-2.c.jj 2024-11-14 18:27:43.544231635 +0100 +++ gcc/testsuite/gcc.dg/dfp/c23-decimal64x-2.c 2024-11-14 18:27:43.544231635 +0100 @@ -0,0 +1,7 @@ +/* Test that DFP constants and _Decimal64x keyword are accepted in C23 mode: compat warnings. */ +/* { dg-do compile } */ +/* { dg-options "-std=c23 -Wc11-c23-compat" } */ + +int a = (int) 1.1D64x; /* { dg-warning "C23 feature" } */ +int b = (int) 2.d64x; /* { dg-warning "C23 feature" } */ +_Decimal64x c = 1; /* { dg-warning "ISO C does not support decimal floating-point before C23" } */ --- gcc/testsuite/gcc.dg/dfp/c23-decimal64x-3.c.jj 2024-11-14 18:27:43.544231635 +0100 +++ gcc/testsuite/gcc.dg/dfp/c23-decimal64x-3.c 2024-11-14 18:27:43.544231635 +0100 @@ -0,0 +1,26 @@ +/* Test _Decimal64x in C23 mode - builtins. */ +/* { dg-do run } */ +/* { dg-options "-std=c23 -pedantic-errors" } */ + +_Decimal64x a = __builtin_infd64x (); +_Decimal64x b = __builtin_nand64x (""); +_Decimal64x c = __builtin_nansd64x (""); +_Decimal64x d = -42.D64x; +_Decimal64x e = 5.25d64x; + +int +main () +{ + if (__builtin_fabsd64x (-2.5d64x) != 2.5D64x + || __builtin_fabsd64x (42.25D64x) != 42.25d64x + || __builtin_fabsd64x (d) != 42.d64x + || __builtin_fabsd64x (e) != 5.25D64x + || __builtin_isinf (42.d64x) + || __builtin_isnan (0.d64x) + || !__builtin_isinf (__builtin_infd64x ()) + || !__builtin_isnan (__builtin_nand64x ("")) + /* || !__builtin_isinf (a) */ + || !__builtin_isnan (b) + || !__builtin_isnan (c)) + __builtin_abort (); +} --- gcc/testsuite/gcc.dg/dfp/c23-decimal64x-4.c.jj 2024-11-14 18:27:43.544231635 +0100 +++ gcc/testsuite/gcc.dg/dfp/c23-decimal64x-4.c 2024-11-14 18:31:31.016008620 +0100 @@ -0,0 +1,43 @@ +/* Test _Decimal64x in C23 mode - float.h macros. */ +/* { dg-do run } */ +/* { dg-options "-std=c23 -pedantic-errors" } */ + +#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ +#define __STDC_WANT_IEC_60559_TYPES_EXT__ 1 +#endif + +#include <float.h> + +#define expr_has_type(e, t) _Generic (e, default : 0, t : 1) +static_assert (expr_has_type (DEC64X_MAX, _Decimal64x)); +static_assert (expr_has_type (DEC64X_MIN, _Decimal64x)); +static_assert (expr_has_type (DEC64X_EPSILON, _Decimal64x)); +static_assert (expr_has_type (DEC64X_TRUE_MIN, _Decimal64x)); + +int +main () +{ +#if __DEC64X_MANT_DIG__ == __DEC128_MANT_DIG__ \ + && __DEC64X_MAX_EXP__ == __DEC128_MAX_EXP__ + if (DEC64X_MANT_DIG != 34) + __builtin_abort (); + + if (DEC64X_MIN_EXP != -6142) + __builtin_abort (); + + if (DEC64X_MAX_EXP != 6145) + __builtin_abort (); + + if (DEC64X_MAX != 9.999999999999999999999999999999999E6144D64x) + __builtin_abort (); + + if (DEC64X_EPSILON != 1E-33D64x) + __builtin_abort (); + + if (DEC64X_MIN != 1E-6143D64x) + __builtin_abort (); + + if (DEC64X_TRUE_MIN != 0.000000000000000000000000000000001E-6143D64x) + __builtin_abort (); +#endif +} --- libcpp/expr.cc.jj 2024-11-14 17:40:22.597801960 +0100 +++ libcpp/expr.cc 2024-11-14 18:27:43.544231635 +0100 @@ -102,9 +102,7 @@ interpret_float_suffix (cpp_reader *pfil df, DF, d32, D32 - _Decimal32. dd, DD, d64, D64 - _Decimal64. dl, DL, d128, D128 - _Decimal128. - - The dN and DN suffixes for _DecimalN, and dNx and DNx for - _DecimalNx, defined in TS 18661-3:2015, are not supported. + d64x, D64x - _Decimal64x. Fixed-point suffixes, from TR 18037:2008, are supported. They consist of three parts, in order: @@ -258,8 +256,13 @@ interpret_float_suffix (cpp_reader *pfil { if (s[1] == '3' && s[2] == '2' && len == 2) return CPP_N_DFLOAT | CPP_N_SMALL; - if (s[1] == '6' && s[2] == '4' && len == 2) - return CPP_N_DFLOAT | CPP_N_MEDIUM; + if (s[1] == '6' && s[2] == '4') + { + if (len == 2) + return CPP_N_DFLOAT | CPP_N_MEDIUM; + if (len == 3 && s[3] == 'x') + return CPP_N_DFLOAT | CPP_N_FLOATNX; + } if (s[1] == '1' && s[2] == '2' && len == 3 && s[3] == '8') return CPP_N_DFLOAT | CPP_N_LARGE; } Jakub