From 5b68fb47bd24abc2e6a65e5617f586d1c1b81d4e Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Fri, 6 Jan 2023 19:31:26 +0000 Subject: c: C2x semantics for __builtin_tgmath __builtin_tgmath implements semantics for integer generic arguments that handle cases involving _FloatN / _FloatNx types as specified in TS 18661-3 plus some defect fixes. C2x has further changes to the semantics for macros with such types, which should also be considered defect fixes (although handled through the integration of TS 18661-3 in C2x rather than through an issue tracking process). Specifically, the rules were changed because of problems raised with using the macros with the evaluation format types such as float_t and _Float32_t: the older version of the rules didn't allow passing _FloatN / _FloatNx types to the narrowing macros returning float or double, or passing float / double / long double to the narrowing macros returning _FloatN / _FloatNx, which was a problem with the evaluation format types which could be either kind of type depending on the value of FLT_EVAL_METHOD. Thus the new rules allow cases of mixing types which were not allowed before - which is not itself a problem for __builtin_tgmath - and, as part of the changes, the handling of integer arguments was also changed: if there is any _FloatNx generic argument, integer generic arguments are treated as _Float32x (not double), while the rule about treating integer arguments to narrowing macros returning _FloatN or _FloatNx as _Float64 not double was removed (no longer needed now double is a valid argument to such macros). Implement the changes for __builtin_tgmath. (The changes also added a rule that if any argument is _DecimalNx, integer arguments are treated as _Decimal64x, but GCC doesn't support _DecimalNx types so nothing is done about that.) I have a corresponding glibc patch to update glibc test expectations for C2x and also ensure that appropriate semantics are followed when GCC 7 through 12 are used with (avoiding __builtin_tgmath in cases where it doesn't match the C2x semantics). Bootstrapped with no regressions for x86_64-pc-linux-gnu. gcc/ * doc/extend.texi (__builtin_tgmath): Do not restate standard rule for handling real integer types. gcc/c/ * c-parser.cc (c_parser_postfix_expression): Handle integer generic arguments to functions passed to __builtin_tgmath as _Float32x if any argument has _FloatNx or _Complex _FloatNx type. Do not handle integer arguments to some narrowing functions as _Float64. gcc/testsuite/ * gcc.dg/builtin-tgmath-3.c: Update expectations and add more tests. --- gcc/c/c-parser.cc | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'gcc/c') diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 7d6960f..3a59980 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -10276,16 +10276,17 @@ c_parser_postfix_expression (c_parser *parser) types are treated as _Decimal64 if any type-generic argument is decimal, or if the only alternatives for type-generic arguments are of decimal types, and are - otherwise treated as double (or _Complex double for - complex integer types, or _Float64 or _Complex _Float64 - if all the return types are the same _FloatN or - _FloatNx type). After that adjustment, types are - combined following the usual arithmetic conversions. - If the function only accepts complex arguments, a - complex type is produced. */ + otherwise treated as _Float32x (or _Complex _Float32x + for complex integer types) if any type-generic argument + has _FloatNx type, otherwise as double (or _Complex + double for complex integer types). After that + adjustment, types are combined following the usual + arithmetic conversions. If the function only accepts + complex arguments, a complex type is produced. */ bool arg_complex = all_complex; bool arg_binary = all_binary; bool arg_int_decimal = all_decimal; + bool arg_int_floatnx = false; for (unsigned int j = 1; j <= nargs; j++) { if (parm_kind[j] == tgmath_fixed) @@ -10380,20 +10381,17 @@ c_parser_postfix_expression (c_parser *parser) goto out; } } + tree rtype = TYPE_MAIN_VARIANT (type); + if (TREE_CODE (rtype) == COMPLEX_TYPE) + rtype = TREE_TYPE (rtype); + if (SCALAR_FLOAT_TYPE_P (rtype)) + for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++) + if (rtype == FLOATNX_TYPE_NODE (j)) + { + arg_int_floatnx = true; + break; + } } - /* For a macro rounding its result to a narrower type, map - integer types to _Float64 not double if the return type - is a _FloatN or _FloatNx type. */ - bool arg_int_float64 = false; - if (parm_kind[0] == tgmath_fixed - && SCALAR_FLOAT_TYPE_P (parm_first[0]) - && float64_type_node != NULL_TREE) - for (unsigned int j = 0; j < NUM_FLOATN_NX_TYPES; j++) - if (parm_first[0] == FLOATN_TYPE_NODE (j)) - { - arg_int_float64 = true; - break; - } tree arg_real = NULL_TREE; for (unsigned int j = 1; j <= nargs; j++) { @@ -10406,8 +10404,8 @@ c_parser_postfix_expression (c_parser *parser) if (INTEGRAL_TYPE_P (type)) type = (arg_int_decimal ? dfloat64_type_node - : arg_int_float64 - ? float64_type_node + : arg_int_floatnx + ? float32x_type_node : double_type_node); if (arg_real == NULL_TREE) arg_real = type; -- cgit v1.1