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

Reply via email to