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)
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++)
{
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;
The standard rules for @code{<tgmath.h>} macros are used to find a
common type @var{u} from the types of the arguments for parameters
whose types vary between the functions; complex integer types (a GNU
-extension) are treated like @code{_Complex double} for this purpose
-(or @code{_Complex _Float64} if all the function return types are the
-same @code{_Float@var{n}} or @code{_Float@var{n}x} type).
+extension) are treated like the complex type corresponding to the real
+floating type that would be chosen for the corresponding real integer type.
If the function return types vary, or are all the same integer type,
the function called is the one for which @var{t} is @var{u}, and it is
an error if there is no such function. If the function return types
-/* Test __builtin_tgmath: integer arguments mapped to _Float64. */
+/* Test __builtin_tgmath: integer arguments with _FloatN / _FloatNx. */
/* { dg-do run } */
/* { dg-options "" } */
/* { dg-add-options float32 } */
/* { dg-add-options float64 } */
+/* { dg-add-options float32x } */
/* { dg-require-effective-target float32_runtime } */
/* { dg-require-effective-target float64_runtime } */
+/* { dg-require-effective-target float32x_runtime } */
extern void abort (void);
extern void exit (int);
} \
while (0)
+extern double var_d;
extern _Float32 var_f32;
+extern _Float64 var_f64;
+extern _Float32x var_f32x;
+extern _Complex _Float32x var_cf32x;
_Float32 t1f (float x) { return x + 1; }
_Float32 t1d (double x) { return x + 2; }
CHECK_CALL (t1v (d), 4, var_f32);
CHECK_CALL (t1v (ld), 6, var_f32);
CHECK_CALL (t1v (f64), 8, var_f32);
- CHECK_CALL (t1v (i), 9, var_f32);
+ CHECK_CALL (t1v (i), 7, var_f32);
+}
+
+float t2f (float x, float y) { return 10 * x + y; }
+double t2d (double x, double y) { return 100 * x + y; }
+long double t2l (long double x, long double y) { return 1000 * x + y; }
+_Float32x t2f32x (_Float32x x, _Float32x y) { return 10000 * x + y; }
+_Float64 t2f64 (_Float64 x, _Float64 y) { return 100000 * x + y; }
+
+_Complex _Float32x
+ct2f32x (_Complex _Float32x x, _Complex _Float32x y)
+{
+ return 1000000 * x + y;
+}
+
+#define t2v(x, y) __builtin_tgmath (t2f, t2d, t2l, t2f32x, t2f64, ct2f32x, x, y)
+
+static void
+test_2 (void)
+{
+ double d = 3;
+ _Float64 f64 = 6;
+ _Float32x f32x = 7;
+ int i = 5;
+ _Complex _Float32x cf32x = 8;
+ CHECK_CALL (t2v (f32x, i), 70005, var_f32x);
+ CHECK_CALL (t2v (i, f32x), 50007, var_f32x);
+ CHECK_CALL (t2v (f64, i), 600005, var_f64);
+ CHECK_CALL (t2v (i, f64), 500006, var_f64);
+ CHECK_CALL (t2v (d, i), 305, var_d);
+ CHECK_CALL (t2v (i, d), 503, var_d);
+ CHECK_CALL (t2v (cf32x, i), 8000005, var_cf32x);
+ CHECK_CALL (t2v (i, cf32x), 5000008, var_cf32x);
}
int
main (void)
{
test_1 ();
+ test_2 ();
exit (0);
}