summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog62
-rw-r--r--gcc/c-family/ChangeLog25
-rw-r--r--gcc/c-family/c-common.c38
-rw-r--r--gcc/c-family/c-common.h14
-rw-r--r--gcc/c-family/c-cppbuiltin.c45
-rw-r--r--gcc/c-family/c-lex.c31
-rw-r--r--gcc/c-family/c-pretty-print.c10
-rw-r--r--gcc/c/ChangeLog14
-rw-r--r--gcc/c/c-decl.c115
-rw-r--r--gcc/c/c-parser.c5
-rw-r--r--gcc/c/c-tree.h4
-rw-r--r--gcc/c/c-typeck.c62
-rw-r--r--gcc/config/i386/i386.c23
-rw-r--r--gcc/config/ia64/ia64.c32
-rw-r--r--gcc/config/pdp11/pdp11.c2
-rw-r--r--gcc/config/rs6000/rs6000.c56
-rw-r--r--gcc/doc/extend.texi31
-rw-r--r--gcc/doc/sourcebuild.texi25
-rw-r--r--gcc/doc/tm.texi18
-rw-r--r--gcc/doc/tm.texi.in2
-rw-r--r--gcc/fortran/ChangeLog10
-rw-r--r--gcc/fortran/iso-c-binding.def8
-rw-r--r--gcc/fortran/trans-intrinsic.c6
-rw-r--r--gcc/fortran/trans-types.c8
-rw-r--r--gcc/fortran/trans-types.h4
-rw-r--r--gcc/ginclude/float.h183
-rw-r--r--gcc/real.c24
-rw-r--r--gcc/real.h11
-rw-r--r--gcc/target.def20
-rw-r--r--gcc/targhooks.c87
-rw-r--r--gcc/targhooks.h1
-rw-r--r--gcc/testsuite/ChangeLog74
-rw-r--r--gcc/testsuite/gcc.dg/dfp/floatn.c20
-rw-r--r--gcc/testsuite/gcc.dg/float128-typeof.c9
-rw-r--r--gcc/testsuite/gcc.dg/float128x-typeof.c9
-rw-r--r--gcc/testsuite/gcc.dg/float16-typeof.c9
-rw-r--r--gcc/testsuite/gcc.dg/float32-typeof.c9
-rw-r--r--gcc/testsuite/gcc.dg/float32x-typeof.c9
-rw-r--r--gcc/testsuite/gcc.dg/float64-typeof.c9
-rw-r--r--gcc/testsuite/gcc.dg/float64x-typeof.c9
-rw-r--r--gcc/testsuite/gcc.dg/floatn-arithconv.c50
-rw-r--r--gcc/testsuite/gcc.dg/floatn-errs.c44
-rw-r--r--gcc/testsuite/gcc.dg/floatn-typeof.h22
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128-basic.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128-complex.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128-floath.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128-tg.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128x-basic.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128x-complex.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128x-floath.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/float128x-tg.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float16-basic.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float16-complex.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float16-floath.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/float16-tg.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32-basic.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32-complex.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32-floath.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32-tg.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32x-basic.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32x-complex.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32x-floath.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/float32x-tg.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64-basic.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64-complex.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64-floath.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64-tg.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64x-basic.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64x-complex.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64x-floath.c61
-rw-r--r--gcc/testsuite/gcc.dg/torture/float64x-tg.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/floatn-basic.h141
-rw-r--r--gcc/testsuite/gcc.dg/torture/floatn-complex.h76
-rw-r--r--gcc/testsuite/gcc.dg/torture/floatn-convert.c104
-rw-r--r--gcc/testsuite/gcc.dg/torture/floatn-floath.h52
-rw-r--r--gcc/testsuite/gcc.dg/torture/floatn-tg.h113
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee-timode.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c3
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x-timode.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float16-timode.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float16.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float32-timode.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float32.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x-timode.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float64-timode.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float64.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x-timode.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x.c20
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c3
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c10
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c6
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert.h24
-rw-r--r--gcc/testsuite/lib/target-supports.exp129
-rw-r--r--gcc/tree-core.h47
-rw-r--r--gcc/tree.c44
-rw-r--r--gcc/tree.h13
-rw-r--r--libcpp/ChangeLog9
-rw-r--r--libcpp/expr.c118
-rw-r--r--libcpp/include/cpplib.h7
106 files changed, 2932 insertions, 126 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 04ad7c1c316..3e03050ede4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,65 @@
+2016-08-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/32187
+ * tree-core.h (TI_COMPLEX_FLOAT16_TYPE)
+ (TI_COMPLEX_FLOATN_NX_TYPE_FIRST, TI_COMPLEX_FLOAT32_TYPE)
+ (TI_COMPLEX_FLOAT64_TYPE, TI_COMPLEX_FLOAT128_TYPE)
+ (TI_COMPLEX_FLOAT32X_TYPE, TI_COMPLEX_FLOAT64X_TYPE)
+ (TI_COMPLEX_FLOAT128X_TYPE, TI_FLOAT16_TYPE, TI_FLOATN_TYPE_FIRST)
+ (TI_FLOATN_NX_TYPE_FIRST, TI_FLOAT32_TYPE, TI_FLOAT64_TYPE)
+ (TI_FLOAT128_TYPE, TI_FLOATN_TYPE_LAST, TI_FLOAT32X_TYPE)
+ (TI_FLOATNX_TYPE_FIRST, TI_FLOAT64X_TYPE, TI_FLOAT128X_TYPE)
+ (TI_FLOATNX_TYPE_LAST, TI_FLOATN_NX_TYPE_LAST): New enum
+ tree_index values.
+ (NUM_FLOATN_TYPES, NUM_FLOATNX_TYPES, NUM_FLOATN_NX_TYPES): New
+ macros.
+ (struct floatn_type_info): New structure type.
+ (floatn_nx_types): New variable declaration.
+ * tree.h (FLOATN_TYPE_NODE, FLOATN_NX_TYPE_NODE)
+ (FLOATNX_TYPE_NODE, float128_type_node, float64x_type_node)
+ (COMPLEX_FLOATN_NX_TYPE_NODE): New macros.
+ * tree.c (floatn_nx_types): New variable.
+ (build_common_tree_nodes): Initialize _FloatN, _FloatNx and
+ corresponding complex types.
+ * target.def (floatn_mode): New hook.
+ * targhooks.c: Include "real.h".
+ (default_floatn_mode): New function.
+ * targhooks.h (default_floatn_mode): New prototype.
+ * doc/extend.texi (Floating Types): Document _FloatN and _FloatNx
+ types.
+ * doc/sourcebuild.texi (float@var{n}, float@var{n}x): Document new
+ effective-target and dg-add-options keywords.
+ (float@var{n}_runtime, float@var{n}x_runtime, floatn_nx_runtime):
+ Document new effective-target keywords.
+ * doc/tm.texi.in (TARGET_FLOATN_MODE): New @hook.
+ * doc/tm.texi: Regenerate.
+ * ginclude/float.h (LDBL_DECIMAL_DIG): Define to
+ __LDBL_DECIMAL_DIG__, not __DECIMAL_DIG__.
+ [__STDC_WANT_IEC_60559_TYPES_EXT__]: Define macros from TS
+ 18661-3.
+ * real.h (struct real_format): Add field ieee_bits.
+ * real.c (ieee_single_format, mips_single_format)
+ (motorola_single_format, spu_single_format, ieee_double_format)
+ (mips_double_format, motorola_double_format)
+ (ieee_extended_motorola_format, ieee_extended_intel_96_format)
+ (ieee_extended_intel_128_format)
+ (ieee_extended_intel_96_round_53_format, ibm_extended_format)
+ (mips_extended_format, ieee_quad_format, mips_quad_format)
+ (vax_f_format, vax_d_format, vax_g_format, decimal_single_format)
+ (decimal_double_format, decimal_quad_format, ieee_half_format)
+ (arm_half_format, real_internal_format: Initialize ieee_bits
+ field.
+ * config/i386/i386.c (ix86_init_builtin_types): Do not initialize
+ float128_type_node. Set float80_type_node to float64x_type_node
+ if appropriate and long_double_type_node not appropriate.
+ * config/ia64/ia64.c (ia64_init_builtins): Likewise.
+ * config/pdp11/pdp11.c (pdp11_f_format, pdp11_d_format):
+ Initialize ieee_bits field.
+ * config/rs6000/rs6000.c (TARGET_FLOATN_MODE): New macro.
+ (rs6000_init_builtins): Set ieee128_float_type_node to
+ float128_type_node.
+ (rs6000_floatn_mode): New function.
+
2016-08-19 Jakub Jelinek <jakub@redhat.com>
* config/i386/rdseedintrin.h (_rdseed16_step, _rdseed32_step,
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 616ca132de3..bec37cffd75 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,28 @@
+2016-08-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/32187
+ * c-common.h (RID_FLOAT16, RID_FLOATN_NX_FIRST, RID_FLOAT32)
+ (RID_FLOAT64, RID_FLOAT128, RID_FLOAT32X, RID_FLOAT64X)
+ (RID_FLOAT128X): New enum rid values.
+ (CASE_RID_FLOATN_NX): New macro.
+ * c-common.c (c_common_reswords): Add _FloatN and _FloatNx
+ keywords.
+ (c_common_type_for_mode): Check for _FloatN and _FloatNx and
+ corresponding complex types.
+ (c_common_nodes_and_builtins): For non-C++, register _FloatN and
+ _FloatNx and corresponding complex types.
+ (keyword_begins_type_specifier): Use CASE_RID_FLOATN_NX.
+ * c-cppbuiltin.c (builtin_define_float_constants): Check _FloatN
+ and _FloatNx types for the widest type for determining
+ DECIMAL_DIG. Define __LDBL_DECIMAL_DIG__ as well as
+ __DECIMAL_DIG__ for long double. Handle FMA_SUFFIX being NULL.
+ (c_cpp_builtins): Call builtin_define_float_constants for _FloatN
+ and _FloatNx types.
+ * c-lex.c (interpret_float): Handle _FloatN and _FloatNx
+ constants.
+ * c-pretty-print.c (pp_c_floating_constant): Handle _FloatN and
+ _FloatNx types.
+
2016-08-18 David Malcolm <dmalcolm@redhat.com>
* c-opts.c (c_diagnostic_finalizer): Update for change to
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 9082883cb68..32468ca1351 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -434,6 +434,13 @@ const struct c_common_resword c_common_reswords[] =
{ "_Cilk_sync", RID_CILK_SYNC, 0 },
{ "_Cilk_for", RID_CILK_FOR, 0 },
{ "_Imaginary", RID_IMAGINARY, D_CONLY },
+ { "_Float16", RID_FLOAT16, D_CONLY },
+ { "_Float32", RID_FLOAT32, D_CONLY },
+ { "_Float64", RID_FLOAT64, D_CONLY },
+ { "_Float128", RID_FLOAT128, D_CONLY },
+ { "_Float32x", RID_FLOAT32X, D_CONLY },
+ { "_Float64x", RID_FLOAT64X, D_CONLY },
+ { "_Float128x", RID_FLOAT128X, D_CONLY },
{ "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT },
{ "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT },
{ "_Decimal128", RID_DFLOAT128, D_CONLY | D_EXT },
@@ -3478,6 +3485,11 @@ c_common_type_for_mode (machine_mode mode, int unsignedp)
if (mode == TYPE_MODE (long_double_type_node))
return long_double_type_node;
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE
+ && mode == TYPE_MODE (FLOATN_NX_TYPE_NODE (i)))
+ return FLOATN_NX_TYPE_NODE (i);
+
if (mode == TYPE_MODE (void_type_node))
return void_type_node;
@@ -3503,6 +3515,11 @@ c_common_type_for_mode (machine_mode mode, int unsignedp)
if (mode == TYPE_MODE (complex_long_double_type_node))
return complex_long_double_type_node;
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE
+ && mode == TYPE_MODE (COMPLEX_FLOATN_NX_TYPE_NODE (i)))
+ return COMPLEX_FLOATN_NX_TYPE_NODE (i);
+
if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
return complex_integer_type_node;
@@ -5406,6 +5423,12 @@ c_common_nodes_and_builtins (void)
record_builtin_type (RID_DOUBLE, NULL, double_type_node);
record_builtin_type (RID_MAX, "long double", long_double_type_node);
+ if (!c_dialect_cxx ())
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
+ record_builtin_type ((enum rid) (RID_FLOATN_NX_FIRST + i), NULL,
+ FLOATN_NX_TYPE_NODE (i));
+
/* Only supported decimal floating point extension if the target
actually supports underlying modes. */
if (targetm.scalar_mode_supported_p (SDmode)
@@ -5495,6 +5518,20 @@ c_common_nodes_and_builtins (void)
TYPE_DECL, get_identifier ("complex long double"),
complex_long_double_type_node));
+ if (!c_dialect_cxx ())
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (COMPLEX_FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
+ {
+ char buf[30];
+ sprintf (buf, "complex _Float%d%s", floatn_nx_types[i].n,
+ floatn_nx_types[i].extended ? "x" : "");
+ lang_hooks.decls.pushdecl
+ (build_decl (UNKNOWN_LOCATION,
+ TYPE_DECL,
+ get_identifier (buf),
+ COMPLEX_FLOATN_NX_TYPE_NODE (i)));
+ }
+
if (c_dialect_cxx ())
/* For C++, make fileptr_type_node a distinct void * type until
FILE type is defined. */
@@ -12523,6 +12560,7 @@ keyword_begins_type_specifier (enum rid keyword)
case RID_LONG:
case RID_SHORT:
case RID_SIGNED:
+ CASE_RID_FLOATN_NX:
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 31320bf7c87..bc22baa26b8 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -102,6 +102,20 @@ enum rid
RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR,
RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE,
RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
+
+ /* TS 18661-3 keywords, in the same sequence as the TI_* values. */
+ RID_FLOAT16,
+ RID_FLOATN_NX_FIRST = RID_FLOAT16,
+ RID_FLOAT32,
+ RID_FLOAT64,
+ RID_FLOAT128,
+ RID_FLOAT32X,
+ RID_FLOAT64X,
+ RID_FLOAT128X,
+#define CASE_RID_FLOATN_NX \
+ case RID_FLOAT16: case RID_FLOAT32: case RID_FLOAT64: case RID_FLOAT128: \
+ case RID_FLOAT32X: case RID_FLOAT64X: case RID_FLOAT128X
+
RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
/* C11 */
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 82ed19d1f8d..1f7d013239f 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -125,7 +125,7 @@ builtin_define_float_constants (const char *name_prefix,
const double log10_2 = .30102999566398119521;
double log10_b;
const struct real_format *fmt;
- const struct real_format *ldfmt;
+ const struct real_format *widefmt;
char name[64], buf[128];
int dig, min_10_exp, max_10_exp;
@@ -134,8 +134,20 @@ builtin_define_float_constants (const char *name_prefix,
fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
gcc_assert (fmt->b != 10);
- ldfmt = REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node));
- gcc_assert (ldfmt->b != 10);
+ widefmt = REAL_MODE_FORMAT (TYPE_MODE (long_double_type_node));
+ gcc_assert (widefmt->b != 10);
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ {
+ tree wtype = FLOATN_NX_TYPE_NODE (i);
+ if (wtype != NULL_TREE)
+ {
+ const struct real_format *wfmt
+ = REAL_MODE_FORMAT (TYPE_MODE (wtype));
+ gcc_assert (wfmt->b != 10);
+ if (wfmt->p > widefmt->p)
+ widefmt = wfmt;
+ }
+ }
/* The radix of the exponent representation. */
if (type == float_type_node)
@@ -219,7 +231,7 @@ builtin_define_float_constants (const char *name_prefix,
floating type, but we want this value for rendering constants below. */
{
double d_decimal_dig
- = 1 + (fmt->p < ldfmt->p ? ldfmt->p : fmt->p) * log10_b;
+ = 1 + (fmt->p < widefmt->p ? widefmt->p : fmt->p) * log10_b;
decimal_dig = d_decimal_dig;
if (decimal_dig < d_decimal_dig)
decimal_dig++;
@@ -231,13 +243,13 @@ builtin_define_float_constants (const char *name_prefix,
if (type_decimal_dig < type_d_decimal_dig)
type_decimal_dig++;
}
+ /* Arbitrarily, define __DECIMAL_DIG__ when defining macros for long
+ double, although it may be greater than the value for long
+ double. */
if (type == long_double_type_node)
builtin_define_with_int_value ("__DECIMAL_DIG__", decimal_dig);
- else
- {
- sprintf (name, "__%s_DECIMAL_DIG__", name_prefix);
- builtin_define_with_int_value (name, type_decimal_dig);
- }
+ sprintf (name, "__%s_DECIMAL_DIG__", name_prefix);
+ builtin_define_with_int_value (name, type_decimal_dig);
/* Since, for the supported formats, B is always a power of 2, we
construct the following numbers directly as a hexadecimal
@@ -289,7 +301,7 @@ builtin_define_float_constants (const char *name_prefix,
builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type)));
/* Note whether we have fast FMA. */
- if (mode_has_fma (TYPE_MODE (type)))
+ if (mode_has_fma (TYPE_MODE (type)) && fma_suffix != NULL)
{
sprintf (name, "__FP_FAST_FMA%s", fma_suffix);
builtin_define_with_int_value (name, 1);
@@ -984,6 +996,19 @@ c_cpp_builtins (cpp_reader *pfile)
builtin_define_float_constants ("LDBL", "L", "%s", "L",
long_double_type_node);
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ {
+ if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE)
+ continue;
+ char prefix[20], csuffix[20];
+ sprintf (prefix, "FLT%d%s", floatn_nx_types[i].n,
+ floatn_nx_types[i].extended ? "X" : "");
+ sprintf (csuffix, "F%d%s", floatn_nx_types[i].n,
+ floatn_nx_types[i].extended ? "x" : "");
+ builtin_define_float_constants (prefix, csuffix, "%s", NULL,
+ FLOATN_NX_TYPE_NODE (i));
+ }
+
/* For decfloat.h. */
builtin_define_decimal_float_constants ("DEC32", "DF", dfloat32_type_node);
builtin_define_decimal_float_constants ("DEC64", "DD", dfloat64_type_node);
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index c904ee67fc0..829c18b26a4 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -840,6 +840,26 @@ interpret_float (const cpp_token *token, unsigned int flags,
type = c_common_type_for_mode (mode, 0);
gcc_assert (type);
}
+ else if ((flags & (CPP_N_FLOATN | CPP_N_FLOATNX)) != 0)
+ {
+ unsigned int n = (flags & CPP_N_WIDTH_FLOATN_NX) >> CPP_FLOATN_SHIFT;
+ bool extended = (flags & CPP_N_FLOATNX) != 0;
+ type = NULL_TREE;
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (floatn_nx_types[i].n == (int) n
+ && floatn_nx_types[i].extended == extended)
+ {
+ type = FLOATN_NX_TYPE_NODE (i);
+ break;
+ }
+ if (type == NULL_TREE)
+ {
+ error ("unsupported non-standard suffix on floating constant");
+ return error_mark_node;
+ }
+ else
+ pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant");
+ }
else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
type = long_double_type_node;
else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL
@@ -868,6 +888,17 @@ interpret_float (const cpp_token *token, unsigned int flags,
if (flags & CPP_N_IMAGINARY)
/* I or J suffix. */
copylen--;
+ if (flags & CPP_N_FLOATNX)
+ copylen--;
+ if (flags & (CPP_N_FLOATN | CPP_N_FLOATNX))
+ {
+ unsigned int n = (flags & CPP_N_WIDTH_FLOATN_NX) >> CPP_FLOATN_SHIFT;
+ while (n > 0)
+ {
+ copylen--;
+ n /= 10;
+ }
+ }
}
copy = (char *) alloca (copylen + 1);
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 374bd1a3484..90428cac183 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -1045,6 +1045,16 @@ pp_c_floating_constant (c_pretty_printer *pp, tree r)
pp_string (pp, "dd");
else if (TREE_TYPE (r) == dfloat32_type_node)
pp_string (pp, "df");
+ 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))
+ {
+ pp_character (pp, 'f');
+ pp_decimal_int (pp, floatn_nx_types[i].n);
+ if (floatn_nx_types[i].extended)
+ pp_character (pp, 'x');
+ break;
+ }
}
/* Print out a FIXED value as a decimal-floating-constant. */
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 522da71ff64..8d9d4aabb0a 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,17 @@
+2016-08-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/32187
+ * c-tree.h (cts_floatn_nx): New enum c_typespec_keyword value.
+ (struct c_declspecs): Add field floatn_nx_idx.
+ * c-decl.c (declspecs_add_type, finish_declspecs): Handle _FloatN
+ and _FloatNx type specifiers.
+ * c-parser.c (c_keyword_starts_typename, c_token_starts_declspecs)
+ (c_parser_declspecs, c_parser_attribute_any_word)
+ (c_parser_objc_selector): Use CASE_RID_FLOATN_NX.
+ * c-typeck.c (c_common_type): Handle _FloatN and _FloatNx types.
+ (convert_arguments): Avoid promoting _FloatN and _FloatNx types
+ narrower than double.
+
2016-08-12 Jakub Jelinek <jakub@redhat.com>
Martin Liska <mliska@suse.cz>
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 9ad473cdbcb..0fb2d206458 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -9804,6 +9804,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<long%> and %<float%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<long%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<long%> and %<_Decimal32%> in "
@@ -9857,6 +9865,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<short%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<short%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<short%> and %<_Decimal32%> in "
@@ -9901,6 +9917,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<signed%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<signed%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<signed%> and %<_Decimal32%> in "
@@ -9945,6 +9969,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<unsigned%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<unsigned%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<unsigned%> and %<_Decimal32%> in "
@@ -10049,6 +10081,14 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
error_at (loc,
("both %<_Sat%> and %<double%> in "
"declaration specifiers"));
+ else if (specs->typespec_word == cts_floatn_nx)
+ error_at (loc,
+ ("both %<_Sat%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
else if (specs->typespec_word == cts_dfloat32)
error_at (loc,
("both %<_Sat%> and %<_Decimal32%> in "
@@ -10082,8 +10122,9 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
}
else
{
- /* "void", "_Bool", "char", "int", "float", "double", "_Decimal32",
- "__intN", "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
+ /* "void", "_Bool", "char", "int", "float", "double",
+ "_FloatN", "_FloatNx", "_Decimal32", "__intN",
+ "_Decimal64", "_Decimal128", "_Fract", "_Accum" or
"__auto_type". */
if (specs->typespec_word != cts_none)
{
@@ -10308,6 +10349,69 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs,
specs->locations[cdw_typespec] = loc;
}
return specs;
+ CASE_RID_FLOATN_NX:
+ specs->floatn_nx_idx = i - RID_FLOATN_NX_FIRST;
+ if (!in_system_header_at (input_location))
+ pedwarn (loc, OPT_Wpedantic,
+ "ISO C does not support the %<_Float%d%s%> type",
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+
+ if (specs->long_p)
+ error_at (loc,
+ ("both %<long%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->short_p)
+ error_at (loc,
+ ("both %<short%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->signed_p)
+ error_at (loc,
+ ("both %<signed%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->unsigned_p)
+ error_at (loc,
+ ("both %<unsigned%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (specs->saturating_p)
+ error_at (loc,
+ ("both %<_Sat%> and %<_Float%d%s%> in "
+ "declaration specifiers"),
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else if (FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx) == NULL_TREE)
+ error_at (loc,
+ "%<_Float%d%s%> is not supported on this target",
+ floatn_nx_types[specs->floatn_nx_idx].n,
+ (floatn_nx_types[specs->floatn_nx_idx].extended
+ ? "x"
+ : ""));
+ else
+ {
+ specs->typespec_word = cts_floatn_nx;
+ specs->locations[cdw_typespec] = loc;
+ }
+ return specs;
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
@@ -10785,6 +10889,13 @@ finish_declspecs (struct c_declspecs *specs)
: double_type_node);
}
break;
+ case cts_floatn_nx:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p);
+ specs->type = (specs->complex_p
+ ? COMPLEX_FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx)
+ : FLOATN_NX_TYPE_NODE (specs->floatn_nx_idx));
+ break;
case cts_dfloat32:
case cts_dfloat64:
case cts_dfloat128:
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index c050f644566..fe0c95f3b1b 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -540,6 +540,7 @@ c_keyword_starts_typename (enum rid keyword)
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_ENUM:
case RID_STRUCT:
@@ -727,6 +728,7 @@ c_token_starts_declspecs (c_token *token)
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_ENUM:
case RID_STRUCT:
@@ -2536,6 +2538,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_FRACT:
case RID_ACCUM:
@@ -4009,6 +4012,7 @@ c_parser_attribute_any_word (c_parser *parser)
case RID_DFLOAT32:
case RID_DFLOAT64:
case RID_DFLOAT128:
+ CASE_RID_FLOATN_NX:
case RID_BOOL:
case RID_FRACT:
case RID_ACCUM:
@@ -9638,6 +9642,7 @@ c_parser_objc_selector (c_parser *parser)
case RID_CHAR:
case RID_FLOAT:
case RID_DOUBLE:
+ CASE_RID_FLOATN_NX:
case RID_VOID:
case RID_BOOL:
case RID_ATOMIC:
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 46be53ece21..5a8ab6df483 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -230,6 +230,7 @@ enum c_typespec_keyword {
cts_dfloat32,
cts_dfloat64,
cts_dfloat128,
+ cts_floatn_nx,
cts_fract,
cts_accum,
cts_auto_type
@@ -295,6 +296,9 @@ struct c_declspecs {
int align_log;
/* For the __intN declspec, this stores the index into the int_n_* arrays. */
int int_n_idx;
+ /* For the _FloatN and _FloatNx declspec, this stores the index into
+ the floatn_nx_types array. */
+ int floatn_nx_idx;
/* The storage class specifier, or csc_none if none. */
enum c_storage_class storage_class;
/* Any type specifier keyword used such as "int", not reflecting
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 2e1e09dab00..bc8728a49b6 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -927,18 +927,41 @@ c_common_type (tree t1, tree t2)
return long_integer_type_node;
}
+ /* For floating types of the same TYPE_PRECISION (which we here
+ assume means either the same set of values, or sets of values
+ neither a subset of the other, with behavior being undefined in
+ the latter case), follow the rules from TS 18661-3: prefer
+ interchange types _FloatN, then standard types long double,
+ double, float, then extended types _FloatNx. For extended types,
+ check them starting with _Float128x as that seems most consistent
+ in spirit with preferring long double to double; for interchange
+ types, also check in that order for consistency although it's not
+ possible for more than one of them to have the same
+ precision. */
+ tree mv1 = TYPE_MAIN_VARIANT (t1);
+ tree mv2 = TYPE_MAIN_VARIANT (t2);
+
+ for (int i = NUM_FLOATN_TYPES - 1; i >= 0; i--)
+ if (mv1 == FLOATN_TYPE_NODE (i) || mv2 == FLOATN_TYPE_NODE (i))
+ return FLOATN_TYPE_NODE (i);
+
/* Likewise, prefer long double to double even if same size. */
- if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
- || TYPE_MAIN_VARIANT (t2) == long_double_type_node)
+ if (mv1 == long_double_type_node || mv2 == long_double_type_node)
return long_double_type_node;
/* Likewise, prefer double to float even if same size.
We got a couple of embedded targets with 32 bit doubles, and the
pdp11 might have 64 bit floats. */
- if (TYPE_MAIN_VARIANT (t1) == double_type_node
- || TYPE_MAIN_VARIANT (t2) == double_type_node)
+ if (mv1 == double_type_node || mv2 == double_type_node)
return double_type_node;
+ if (mv1 == float_type_node || mv2 == float_type_node)
+ return float_type_node;
+
+ for (int i = NUM_FLOATNX_TYPES - 1; i >= 0; i--)
+ if (mv1 == FLOATNX_TYPE_NODE (i) || mv2 == FLOATNX_TYPE_NODE (i))
+ return FLOATNX_TYPE_NODE (i);
+
/* Otherwise prefer the unsigned one. */
if (TYPE_UNSIGNED (t1))
@@ -3284,6 +3307,30 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
val = require_complete_type (ploc, val);
+ /* Some floating-point arguments must be promoted to double when
+ no type is specified by a prototype. This applies to
+ arguments of type float, and to architecture-specific types
+ (ARM __fp16), but not to _FloatN or _FloatNx types. */
+ bool promote_float_arg = false;
+ if (type == NULL_TREE
+ && TREE_CODE (valtype) == REAL_TYPE
+ && (TYPE_PRECISION (valtype)
+ <= TYPE_PRECISION (double_type_node))
+ && TYPE_MAIN_VARIANT (valtype) != double_type_node
+ && TYPE_MAIN_VARIANT (valtype) != long_double_type_node
+ && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype)))
+ {
+ /* Promote this argument, unless it has a _FloatN or
+ _FloatNx type. */
+ promote_float_arg = true;
+ for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ if (TYPE_MAIN_VARIANT (valtype) == FLOATN_NX_TYPE_NODE (i))
+ {
+ promote_float_arg = false;
+ break;
+ }
+ }
+
if (type != 0)
{
/* Formal parm type is specified by a function prototype. */
@@ -3450,12 +3497,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
parmval = default_conversion (parmval);
}
}
- else if (TREE_CODE (valtype) == REAL_TYPE
- && (TYPE_PRECISION (valtype)
- <= TYPE_PRECISION (double_type_node))
- && TYPE_MAIN_VARIANT (valtype) != double_type_node
- && TYPE_MAIN_VARIANT (valtype) != long_double_type_node
- && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype)))
+ else if (promote_float_arg)
{
if (type_generic)
parmval = val;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index be027f5e2dd..39794230c10 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -33325,24 +33325,29 @@ ix86_init_builtins_va_builtins_abi (void)
static void
ix86_init_builtin_types (void)
{
- tree float128_type_node, float80_type_node, const_string_type_node;
+ tree float80_type_node, const_string_type_node;
/* The __float80 type. */
float80_type_node = long_double_type_node;
if (TYPE_MODE (float80_type_node) != XFmode)
{
- /* The __float80 type. */
- float80_type_node = make_node (REAL_TYPE);
+ if (float64x_type_node != NULL_TREE
+ && TYPE_MODE (float64x_type_node) == XFmode)
+ float80_type_node = float64x_type_node;
+ else
+ {
+ /* The __float80 type. */
+ float80_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (float80_type_node) = 80;
- layout_type (float80_type_node);
+ TYPE_PRECISION (float80_type_node) = 80;
+ layout_type (float80_type_node);
+ }
}
lang_hooks.types.register_builtin_type (float80_type_node, "__float80");
- /* The __float128 type. */
- float128_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (float128_type_node) = 128;
- layout_type (float128_type_node);
+ /* The __float128 type. The node has already been created as
+ _Float128, so we only need to register the __float128 name for
+ it. */
lang_hooks.types.register_builtin_type (float128_type_node, "__float128");
const_string_type_node
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 4fd7c84a18d..ebd2c86b8d8 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -10350,9 +10350,15 @@ ia64_init_builtins (void)
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
/* The __float80 type. */
- float80_type = make_node (REAL_TYPE);
- TYPE_PRECISION (float80_type) = 80;
- layout_type (float80_type);
+ if (float64x_type_node != NULL_TREE
+ && TYPE_MODE (float64x_type_node) == XFmode)
+ float80_type = float64x_type_node;
+ else
+ {
+ float80_type = make_node (REAL_TYPE);
+ TYPE_PRECISION (float80_type) = 80;
+ layout_type (float80_type);
+ }
(*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
/* The __float128 type. */
@@ -10362,14 +10368,12 @@ ia64_init_builtins (void)
tree const_string_type
= build_pointer_type (build_qualified_type
(char_type_node, TYPE_QUAL_CONST));
- tree float128_type = make_node (REAL_TYPE);
- TYPE_PRECISION (float128_type) = 128;
- layout_type (float128_type);
- (*lang_hooks.types.register_builtin_type) (float128_type, "__float128");
+ (*lang_hooks.types.register_builtin_type) (float128_type_node,
+ "__float128");
/* TFmode support builtins. */
- ftype = build_function_type_list (float128_type, NULL_TREE);
+ ftype = build_function_type_list (float128_type_node, NULL_TREE);
decl = add_builtin_function ("__builtin_infq", ftype,
IA64_BUILTIN_INFQ, BUILT_IN_MD,
NULL, NULL_TREE);
@@ -10380,7 +10384,7 @@ ia64_init_builtins (void)
NULL, NULL_TREE);
ia64_builtins[IA64_BUILTIN_HUGE_VALQ] = decl;
- ftype = build_function_type_list (float128_type,
+ ftype = build_function_type_list (float128_type_node,
const_string_type,
NULL_TREE);
decl = add_builtin_function ("__builtin_nanq", ftype,
@@ -10395,8 +10399,8 @@ ia64_init_builtins (void)
TREE_READONLY (decl) = 1;
ia64_builtins[IA64_BUILTIN_NANSQ] = decl;
- ftype = build_function_type_list (float128_type,
- float128_type,
+ ftype = build_function_type_list (float128_type_node,
+ float128_type_node,
NULL_TREE);
decl = add_builtin_function ("__builtin_fabsq", ftype,
IA64_BUILTIN_FABSQ, BUILT_IN_MD,
@@ -10404,9 +10408,9 @@ ia64_init_builtins (void)
TREE_READONLY (decl) = 1;
ia64_builtins[IA64_BUILTIN_FABSQ] = decl;
- ftype = build_function_type_list (float128_type,
- float128_type,
- float128_type,
+ ftype = build_function_type_list (float128_type_node,
+ float128_type_node,
+ float128_type_node,
NULL_TREE);
decl = add_builtin_function ("__builtin_copysignq", ftype,
IA64_BUILTIN_COPYSIGNQ, BUILT_IN_MD,
diff --git a/gcc/config/pdp11/pdp11.c b/gcc/config/pdp11/pdp11.c
index ec3d61a03ed..35d57c72488 100644
--- a/gcc/config/pdp11/pdp11.c
+++ b/gcc/config/pdp11/pdp11.c
@@ -69,6 +69,7 @@ const struct real_format pdp11_f_format =
127,
15,
15,
+ 0,
false,
false,
false,
@@ -91,6 +92,7 @@ const struct real_format pdp11_d_format =
127,
15,
15,
+ 0,
false,
false,
false,
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e58ede1e9f2..b232099b9e7 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -1703,6 +1703,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_VECTOR_MODE_SUPPORTED_P
#define TARGET_VECTOR_MODE_SUPPORTED_P rs6000_vector_mode_supported_p
+#undef TARGET_FLOATN_MODE
+#define TARGET_FLOATN_MODE rs6000_floatn_mode
+
#undef TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN
#define TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN invalid_arg_for_unprototyped_fn
@@ -16303,10 +16306,7 @@ rs6000_init_builtins (void)
layout_type (ibm128_float_type_node);
SET_TYPE_MODE (ibm128_float_type_node, IFmode);
- ieee128_float_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (ieee128_float_type_node) = 128;
- layout_type (ieee128_float_type_node);
- SET_TYPE_MODE (ieee128_float_type_node, KFmode);
+ ieee128_float_type_node = float128_type_node;
lang_hooks.types.register_builtin_type (ieee128_float_type_node,
"__float128");
@@ -36199,6 +36199,54 @@ rs6000_vector_mode_supported_p (machine_mode mode)
return false;
}
+/* Target hook for floatn_mode. */
+static machine_mode
+rs6000_floatn_mode (int n, bool extended)
+{
+ if (extended)
+ {
+ switch (n)
+ {
+ case 32:
+ return DFmode;
+
+ case 64:
+ if (TARGET_FLOAT128)
+ return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
+ else
+ return VOIDmode;
+
+ case 128:
+ return VOIDmode;
+
+ default:
+ /* Those are the only valid _FloatNx types. */
+ gcc_unreachable ();
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 32:
+ return SFmode;
+
+ case 64:
+ return DFmode;
+
+ case 128:
+ if (TARGET_FLOAT128)
+ return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
+ else
+ return VOIDmode;
+
+ default:
+ return VOIDmode;
+ }
+ }
+
+}
+
/* Target hook for c_mode_for_suffix. */
static machine_mode
rs6000_c_mode_for_suffix (char suffix)
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 5285e002d7e..5124883ae5c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -927,6 +927,8 @@ examine and set these two fictitious variables with your debugger.
@node Floating Types
@section Additional Floating Types
@cindex additional floating types
+@cindex @code{_Float@var{n}} data types
+@cindex @code{_Float@var{n}x} data types
@cindex @code{__float80} data type
@cindex @code{__float128} data type
@cindex @code{__ibm128} data type
@@ -935,9 +937,19 @@ examine and set these two fictitious variables with your debugger.
@cindex @code{W} floating point suffix
@cindex @code{Q} floating point suffix
-As an extension, GNU C supports additional floating
+ISO/IEC TS 18661-3:2015 defines C support for additional floating
+types @code{_Float@var{n}} and @code{_Float@var{n}x}, and GCC supports
+these type names; the set of types supported depends on the target
+architecture. These types are not supported when compiling C++.
+Constants with these types use suffixes @code{f@var{n}} or
+@code{F@var{n}} and @code{f@var{n}x} or @code{F@var{n}x}. These type
+names can be used together with @code{_Complex} to declare complex
+types.
+
+As an extension, GNU C and GNU C++ support additional floating
types, @code{__float80} and @code{__float128} to support 80-bit
-(@code{XFmode}) and 128-bit (@code{TFmode}) floating types.
+(@code{XFmode}) and 128-bit (@code{TFmode}) floating types; these are
+aliases for the type names @code{_Float64x} and @code{_Float128}.
Support for additional types includes the arithmetic operators:
add, subtract, multiply, divide; unary arithmetic operators;
relational operators; equality operators; and conversions to and from
@@ -954,9 +966,11 @@ typedef _Complex float __attribute__((mode(TC))) _Complex128;
typedef _Complex float __attribute__((mode(XC))) _Complex80;
@end smallexample
-In order to use @code{__float128} and @code{__ibm128} on PowerPC Linux
+In order to use @code{_Float128}, @code{__float128} and
+@code{__ibm128} on PowerPC Linux
systems, you must use the @option{-mfloat128}. It is expected in
-future versions of GCC that @code{__float128} will be enabled
+future versions of GCC that @code{_Float128} and @code{__float128}
+will be enabled
automatically. In addition, there are currently problems in using the
complex @code{__float128} type. When these problems are fixed, you
would use the following syntax to declare @code{_Complex128} to be a
@@ -976,7 +990,14 @@ Not all targets support additional floating-point types.
IA-64 targets. The @code{__float128} type is supported on hppa HP-UX.
The @code{__float128} type is supported on PowerPC 64-bit Linux
systems by default if the vector scalar instruction set (VSX) is
-enabled.
+enabled. The @code{_Float128} type is supported on all systems where
+@code{__float128} is supported or where @code{long double} has the
+IEEE binary128 format. The @code{_Float64x} type is supported on all
+systems where @code{__float128} is supported. The @code{_Float32}
+type is supported on all systems supporting IEEE binary32; the
+@code{_Float64} and @code{Float32x} types are supported on all systems
+supporting IEEE binary64. GCC does not currently support
+@code{_Float16} or @code{_Float128x} on any systems.
On the PowerPC, @code{__ibm128} provides access to the IBM extended
double format, and it is intended to be used by the library functions
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index fa41fc04f95..d18c3b4c27b 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1321,6 +1321,25 @@ Target supports array and structure sizes that are 32 bits or longer.
@item 4byte_wchar_t
Target has @code{wchar_t} that is at least 4 bytes.
+
+@item float@var{n}
+Target has the @code{_Float@var{n}} type.
+
+@item float@var{n}x
+Target has the @code{_Float@var{n}x} type.
+
+@item float@var{n}_runtime
+Target has the @code{_Float@var{n}} type, including runtime support
+for any options added with @code{dg-add-options}.
+
+@item float@var{n}x_runtime
+Target has the @code{_Float@var{n}x} type, including runtime support
+for any options added with @code{dg-add-options}.
+
+@item floatn_nx_runtime
+Target has runtime support for any options added with
+@code{dg-add-options} for any @code{_Float@var{n}} or
+@code{_Float@var{n}x} type.
@end table
@subsubsection Fortran-specific attributes
@@ -2135,6 +2154,12 @@ locally when using pic/PIC passes in the testsuite.
@item c99_runtime
Add the target-specific flags needed to access the C99 runtime.
+@item float@var{n}
+Add the target-specific flags needed to use the @code{_Float@var{n}} type.
+
+@item float@var{n}x
+Add the target-specific flags needed to use the @code{_Float@var{n}x} type.
+
@item ieee
Add the target-specific flags needed to enable full IEEE
compliance mode.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 9edb006cb06..58662606243 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -4269,6 +4269,24 @@ hook returns true for all of @code{SFmode}, @code{DFmode},
@code{XFmode} and @code{TFmode}, if such modes exist.
@end deftypefn
+@deftypefn {Target Hook} machine_mode TARGET_FLOATN_MODE (int @var{n}, bool @var{extended})
+Define this to return the machine mode to use for the type
+@code{_Float@var{n}}, if @var{extended} is false, or the type
+@code{_Float@var{n}x}, if @var{extended} is true. If such a type
+is not supported, return @code{VOIDmode}. The default version of this
+hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for
+@code{_Float64} and @code{_Float32x} and @code{TFmode} for
+@code{_Float128}, if those modes exist and satisfy the requirements for
+those types and pass @code{TARGET_SCALAR_MODE_SUPPORTED_P} and
+@code{TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P}; for @code{_Float64x}, it
+returns the first of @code{XFmode} and @code{TFmode} that exists and
+satisfies the same requirements; for other types, it returns
+@code{VOIDmode}. The hook is only called for values of @var{n} and
+@var{extended} that are valid according to ISO/IEC TS 18661-3:2015; that
+is, @var{n} is one of 32, 64, 128, or, if @var{extended} is false, 16 or
+greater than 128 and a multiple of 32.
+@end deftypefn
+
@deftypefn {Target Hook} bool TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P (machine_mode @var{mode})
Define this to return nonzero for machine modes for which the port has
small register classes. If this target hook returns nonzero for a given
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index a72c3d8ab10..da133a4b701 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3527,6 +3527,8 @@ stack.
@hook TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P
+@hook TARGET_FLOATN_MODE
+
@hook TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P
@node Scalar Return
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 23386cce487..a404c432d64 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2016-08-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/32187
+ * trans-types.h (float128_type_node): Rename to
+ gfc_float128_type_node.
+ (complex_float128_type_node): Rename to
+ gfc_complex_float128_type_node.
+ * iso-c-binding.def, trans-intrinsic.c, trans-types.c: All users
+ changed.
+
2016-08-19 Jakub Jelinek <jakub@redhat.com>
PR fortran/71014
diff --git a/gcc/fortran/iso-c-binding.def b/gcc/fortran/iso-c-binding.def
index c3f87e9da83..472e7ae4faf 100644
--- a/gcc/fortran/iso-c-binding.def
+++ b/gcc/fortran/iso-c-binding.def
@@ -115,8 +115,8 @@ NAMED_REALCST (ISOCBINDING_DOUBLE, "c_double", \
NAMED_REALCST (ISOCBINDING_LONG_DOUBLE, "c_long_double", \
get_real_kind_from_node (long_double_type_node), GFC_STD_F2003)
NAMED_REALCST (ISOCBINDING_FLOAT128, "c_float128", \
- float128_type_node == NULL_TREE \
- ? -4 : get_real_kind_from_node (float128_type_node), \
+ gfc_float128_type_node == NULL_TREE \
+ ? -4 : get_real_kind_from_node (gfc_float128_type_node), \
GFC_STD_GNU)
NAMED_CMPXCST (ISOCBINDING_FLOAT_COMPLEX, "c_float_complex", \
get_real_kind_from_node (float_type_node), GFC_STD_F2003)
@@ -125,8 +125,8 @@ NAMED_CMPXCST (ISOCBINDING_DOUBLE_COMPLEX, "c_double_complex", \
NAMED_CMPXCST (ISOCBINDING_LONG_DOUBLE_COMPLEX, "c_long_double_complex", \
get_real_kind_from_node (long_double_type_node), GFC_STD_F2003)
NAMED_CMPXCST (ISOCBINDING_FLOAT128_COMPLEX, "c_float128_complex", \
- float128_type_node == NULL_TREE \
- ? -4 : get_real_kind_from_node (float128_type_node), \
+ gfc_float128_type_node == NULL_TREE \
+ ? -4 : get_real_kind_from_node (gfc_float128_type_node), \
GFC_STD_GNU)
NAMED_LOGCST (ISOCBINDING_BOOL, "c_bool", \
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 17dd8c266a2..81678428f18 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -149,7 +149,7 @@ builtin_decl_for_precision (enum built_in_function base_built_in,
i = m->double_built_in;
else if (precision == TYPE_PRECISION (long_double_type_node))
i = m->long_double_built_in;
- else if (precision == TYPE_PRECISION (float128_type_node))
+ else if (precision == TYPE_PRECISION (gfc_float128_type_node))
{
/* Special treatment, because it is not exactly a built-in, but
a library function. */
@@ -621,8 +621,8 @@ gfc_build_intrinsic_lib_fndecls (void)
memset (quad_decls, 0, sizeof(tree) * (END_BUILTINS + 1));
- type = float128_type_node;
- complex_type = complex_float128_type_node;
+ type = gfc_float128_type_node;
+ complex_type = gfc_complex_float128_type_node;
/* type (*) (type) */
func_1 = build_function_type_list (type, type, NULL_TREE);
/* int (*) (type) */
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index bde64f499c7..6a89b30e3bf 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -62,8 +62,8 @@ tree pfunc_type_node;
tree gfc_charlen_type_node;
-tree float128_type_node = NULL_TREE;
-tree complex_float128_type_node = NULL_TREE;
+tree gfc_float128_type_node = NULL_TREE;
+tree gfc_complex_float128_type_node = NULL_TREE;
bool gfc_real16_is_float128 = false;
@@ -901,7 +901,7 @@ gfc_init_types (void)
PUSH_TYPE (name_buf, type);
if (gfc_real_kinds[index].c_float128)
- float128_type_node = type;
+ gfc_float128_type_node = type;
type = gfc_build_complex_type (type);
gfc_complex_types[index] = type;
@@ -910,7 +910,7 @@ gfc_init_types (void)
PUSH_TYPE (name_buf, type);
if (gfc_real_kinds[index].c_float128)
- complex_float128_type_node = type;
+ gfc_complex_float128_type_node = type;
}
for (index = 0; gfc_character_kinds[index].kind != 0; ++index)
diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h
index 95d98e9359c..c518cc18926 100644
--- a/gcc/fortran/trans-types.h
+++ b/gcc/fortran/trans-types.h
@@ -30,8 +30,8 @@ extern GTY(()) tree ppvoid_type_node;
extern GTY(()) tree pvoid_type_node;
extern GTY(()) tree prvoid_type_node;
extern GTY(()) tree pchar_type_node;
-extern GTY(()) tree float128_type_node;
-extern GTY(()) tree complex_float128_type_node;
+extern GTY(()) tree gfc_float128_type_node;
+extern GTY(()) tree gfc_complex_float128_type_node;
/* This is the type used to hold the lengths of character variables.
It must be the same as the corresponding definition in gfortran.h. */
diff --git a/gcc/ginclude/float.h b/gcc/ginclude/float.h
index 862f7cc40b4..de46a2711a9 100644
--- a/gcc/ginclude/float.h
+++ b/gcc/ginclude/float.h
@@ -165,7 +165,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#undef LDBL_DECIMAL_DIG
#define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__
#define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__
-#define LDBL_DECIMAL_DIG __DECIMAL_DIG__
+#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
/* Whether types support subnormal numbers. */
#undef FLT_HAS_SUBNORM
@@ -185,6 +185,187 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#endif /* C11 */
+#ifdef __STDC_WANT_IEC_60559_TYPES_EXT__
+/* Constants for _FloatN and _FloatNx types from TS 18661-3. See
+ comments above for their semantics. */
+
+#ifdef __FLT16_MANT_DIG__
+#undef FLT16_MANT_DIG
+#define FLT16_MANT_DIG __FLT16_MANT_DIG__
+#undef FLT16_DIG
+#define FLT16_DIG __FLT16_DIG__
+#undef FLT16_MIN_EXP
+#define FLT16_MIN_EXP __FLT16_MIN_EXP__
+#undef FLT16_MIN_10_EXP
+#define FLT16_MIN_10_EXP __FLT16_MIN_10_EXP__
+#undef FLT16_MAX_EXP
+#define FLT16_MAX_EXP __FLT16_MAX_EXP__
+#undef FLT16_MAX_10_EXP
+#define FLT16_MAX_10_EXP __FLT16_MAX_10_EXP__
+#undef FLT16_MAX
+#define FLT16_MAX __FLT16_MAX__
+#undef FLT16_EPSILON
+#define FLT16_EPSILON __FLT16_EPSILON__
+#undef FLT16_MIN
+#define FLT16_MIN __FLT16_MIN__
+#undef FLT16_DECIMAL_DIG
+#define FLT16_DECIMAL_DIG __FLT16_DECIMAL_DIG__
+#undef FLT16_TRUE_MIN
+#define FLT16_TRUE_MIN __FLT16_DENORM_MIN__
+#endif /* __FLT16_MANT_DIG__. */
+
+#ifdef __FLT32_MANT_DIG__
+#undef FLT32_MANT_DIG
+#define FLT32_MANT_DIG __FLT32_MANT_DIG__
+#undef FLT32_DIG
+#define FLT32_DIG __FLT32_DIG__
+#undef FLT32_MIN_EXP
+#define FLT32_MIN_EXP __FLT32_MIN_EXP__
+#undef FLT32_MIN_10_EXP
+#define FLT32_MIN_10_EXP __FLT32_MIN_10_EXP__
+#undef FLT32_MAX_EXP
+#define FLT32_MAX_EXP __FLT32_MAX_EXP__
+#undef FLT32_MAX_10_EXP
+#define FLT32_MAX_10_EXP __FLT32_MAX_10_EXP__
+#undef FLT32_MAX
+#define FLT32_MAX __FLT32_MAX__
+#undef FLT32_EPSILON
+#define FLT32_EPSILON __FLT32_EPSILON__
+#undef FLT32_MIN
+#define FLT32_MIN __FLT32_MIN__
+#undef FLT32_DECIMAL_DIG
+#define FLT32_DECIMAL_DIG __FLT32_DECIMAL_DIG__
+#undef FLT32_TRUE_MIN
+#define FLT32_TRUE_MIN __FLT32_DENORM_MIN__
+#endif /* __FLT32_MANT_DIG__. */
+
+#ifdef __FLT64_MANT_DIG__
+#undef FLT64_MANT_DIG
+#define FLT64_MANT_DIG __FLT64_MANT_DIG__
+#undef FLT64_DIG
+#define FLT64_DIG __FLT64_DIG__
+#undef FLT64_MIN_EXP
+#define FLT64_MIN_EXP __FLT64_MIN_EXP__
+#undef FLT64_MIN_10_EXP
+#define FLT64_MIN_10_EXP __FLT64_MIN_10_EXP__
+#undef FLT64_MAX_EXP
+#define FLT64_MAX_EXP __FLT64_MAX_EXP__
+#undef FLT64_MAX_10_EXP
+#define FLT64_MAX_10_EXP __FLT64_MAX_10_EXP__
+#undef FLT64_MAX
+#define FLT64_MAX __FLT64_MAX__
+#undef FLT64_EPSILON
+#define FLT64_EPSILON __FLT64_EPSILON__
+#undef FLT64_MIN
+#define FLT64_MIN __FLT64_MIN__
+#undef FLT64_DECIMAL_DIG
+#define FLT64_DECIMAL_DIG __FLT64_DECIMAL_DIG__
+#undef FLT64_TRUE_MIN
+#define FLT64_TRUE_MIN __FLT64_DENORM_MIN__
+#endif /* __FLT64_MANT_DIG__. */
+
+#ifdef __FLT128_MANT_DIG__
+#undef FLT128_MANT_DIG
+#define FLT128_MANT_DIG __FLT128_MANT_DIG__
+#undef FLT128_DIG
+#define FLT128_DIG __FLT128_DIG__
+#undef FLT128_MIN_EXP
+#define FLT128_MIN_EXP __FLT128_MIN_EXP__
+#undef FLT128_MIN_10_EXP
+#define FLT128_MIN_10_EXP __FLT128_MIN_10_EXP__
+#undef FLT128_MAX_EXP
+#define FLT128_MAX_EXP __FLT128_MAX_EXP__
+#undef FLT128_MAX_10_EXP
+#define FLT128_MAX_10_EXP __FLT128_MAX_10_EXP__
+#undef FLT128_MAX
+#define FLT128_MAX __FLT128_MAX__
+#undef FLT128_EPSILON
+#define FLT128_EPSILON __FLT128_EPSILON__
+#undef FLT128_MIN
+#define FLT128_MIN __FLT128_MIN__
+#undef FLT128_DECIMAL_DIG
+#define FLT128_DECIMAL_DIG __FLT128_DECIMAL_DIG__
+#undef FLT128_TRUE_MIN
+#define FLT128_TRUE_MIN __FLT128_DENORM_MIN__
+#endif /* __FLT128_MANT_DIG__. */
+
+#ifdef __FLT32X_MANT_DIG__
+#undef FLT32X_MANT_DIG
+#define FLT32X_MANT_DIG __FLT32X_MANT_DIG__
+#undef FLT32X_DIG
+#define FLT32X_DIG __FLT32X_DIG__
+#undef FLT32X_MIN_EXP
+#define FLT32X_MIN_EXP __FLT32X_MIN_EXP__
+#undef FLT32X_MIN_10_EXP
+#define FLT32X_MIN_10_EXP __FLT32X_MIN_10_EXP__
+#undef FLT32X_MAX_EXP
+#define FLT32X_MAX_EXP __FLT32X_MAX_EXP__
+#undef FLT32X_MAX_10_EXP
+#define FLT32X_MAX_10_EXP __FLT32X_MAX_10_EXP__
+#undef FLT32X_MAX
+#define FLT32X_MAX __FLT32X_MAX__
+#undef FLT32X_EPSILON
+#define FLT32X_EPSILON __FLT32X_EPSILON__
+#undef FLT32X_MIN
+#define FLT32X_MIN __FLT32X_MIN__
+#undef FLT32X_DECIMAL_DIG
+#define FLT32X_DECIMAL_DIG __FLT32X_DECIMAL_DIG__
+#undef FLT32X_TRUE_MIN
+#define FLT32X_TRUE_MIN __FLT32X_DENORM_MIN__
+#endif /* __FLT32X_MANT_DIG__. */
+
+#ifdef __FLT64X_MANT_DIG__
+#undef FLT64X_MANT_DIG
+#define FLT64X_MANT_DIG __FLT64X_MANT_DIG__
+#undef FLT64X_DIG
+#define FLT64X_DIG __FLT64X_DIG__
+#undef FLT64X_MIN_EXP
+#define FLT64X_MIN_EXP __FLT64X_MIN_EXP__
+#undef FLT64X_MIN_10_EXP
+#define FLT64X_MIN_10_EXP __FLT64X_MIN_10_EXP__
+#undef FLT64X_MAX_EXP
+#define FLT64X_MAX_EXP __FLT64X_MAX_EXP__
+#undef FLT64X_MAX_10_EXP
+#define FLT64X_MAX_10_EXP __FLT64X_MAX_10_EXP__
+#undef FLT64X_MAX
+#define FLT64X_MAX __FLT64X_MAX__
+#undef FLT64X_EPSILON
+#define FLT64X_EPSILON __FLT64X_EPSILON__
+#undef FLT64X_MIN
+#define FLT64X_MIN __FLT64X_MIN__
+#undef FLT64X_DECIMAL_DIG
+#define FLT64X_DECIMAL_DIG __FLT64X_DECIMAL_DIG__
+#undef FLT64X_TRUE_MIN
+#define FLT64X_TRUE_MIN __FLT64X_DENORM_MIN__
+#endif /* __FLT64X_MANT_DIG__. */
+
+#ifdef __FLT128X_MANT_DIG__
+#undef FLT128X_MANT_DIG
+#define FLT128X_MANT_DIG __FLT128X_MANT_DIG__
+#undef FLT128X_DIG
+#define FLT128X_DIG __FLT128X_DIG__
+#undef FLT128X_MIN_EXP
+#define FLT128X_MIN_EXP __FLT128X_MIN_EXP__
+#undef FLT128X_MIN_10_EXP
+#define FLT128X_MIN_10_EXP __FLT128X_MIN_10_EXP__
+#undef FLT128X_MAX_EXP
+#define FLT128X_MAX_EXP __FLT128X_MAX_EXP__
+#undef FLT128X_MAX_10_EXP
+#define FLT128X_MAX_10_EXP __FLT128X_MAX_10_EXP__
+#undef FLT128X_MAX
+#define FLT128X_MAX __FLT128X_MAX__
+#undef FLT128X_EPSILON
+#define FLT128X_EPSILON __FLT128X_EPSILON__
+#undef FLT128X_MIN
+#define FLT128X_MIN __FLT128X_MIN__
+#undef FLT128X_DECIMAL_DIG
+#define FLT128X_DECIMAL_DIG __FLT128X_DECIMAL_DIG__
+#undef FLT128X_TRUE_MIN
+#define FLT128X_TRUE_MIN __FLT128X_DENORM_MIN__
+#endif /* __FLT128X_MANT_DIG__. */
+
+#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__. */
+
#ifdef __STDC_WANT_DEC_FP__
/* Draft Technical Report 24732, extension for decimal floating-point
arithmetic: Characteristic of decimal floating types <float.h>. */
diff --git a/gcc/real.c b/gcc/real.c
index 25f0a5b1466..66e88e2ad36 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -3043,6 +3043,7 @@ const struct real_format ieee_single_format =
128,
31,
31,
+ 32,
false,
true,
true,
@@ -3065,6 +3066,7 @@ const struct real_format mips_single_format =
128,
31,
31,
+ 32,
false,
true,
true,
@@ -3087,6 +3089,7 @@ const struct real_format motorola_single_format =
128,
31,
31,
+ 32,
false,
true,
true,
@@ -3120,6 +3123,7 @@ const struct real_format spu_single_format =
129,
31,
31,
+ 0,
true,
false,
false,
@@ -3330,6 +3334,7 @@ const struct real_format ieee_double_format =
1024,
63,
63,
+ 64,
false,
true,
true,
@@ -3352,6 +3357,7 @@ const struct real_format mips_double_format =
1024,
63,
63,
+ 64,
false,
true,
true,
@@ -3374,6 +3380,7 @@ const struct real_format motorola_double_format =
1024,
63,
63,
+ 64,
false,
true,
true,
@@ -3719,6 +3726,7 @@ const struct real_format ieee_extended_motorola_format =
16384,
95,
95,
+ 0,
false,
true,
true,
@@ -3741,6 +3749,7 @@ const struct real_format ieee_extended_intel_96_format =
16384,
79,
79,
+ 65,
false,
true,
true,
@@ -3763,6 +3772,7 @@ const struct real_format ieee_extended_intel_128_format =
16384,
79,
79,
+ 65,
false,
true,
true,
@@ -3787,6 +3797,7 @@ const struct real_format ieee_extended_intel_96_round_53_format =
16384,
79,
79,
+ 33,
false,
true,
true,
@@ -3876,6 +3887,7 @@ const struct real_format ibm_extended_format =
1024,
127,
-1,
+ 0,
false,
true,
true,
@@ -3898,6 +3910,7 @@ const struct real_format mips_extended_format =
1024,
127,
-1,
+ 0,
false,
true,
true,
@@ -4162,6 +4175,7 @@ const struct real_format ieee_quad_format =
16384,
127,
127,
+ 128,
false,
true,
true,
@@ -4184,6 +4198,7 @@ const struct real_format mips_quad_format =
16384,
127,
127,
+ 128,
false,
true,
true,
@@ -4485,6 +4500,7 @@ const struct real_format vax_f_format =
127,
15,
15,
+ 0,
false,
false,
false,
@@ -4507,6 +4523,7 @@ const struct real_format vax_d_format =
127,
15,
15,
+ 0,
false,
false,
false,
@@ -4529,6 +4546,7 @@ const struct real_format vax_g_format =
1023,
15,
15,
+ 0,
false,
false,
false,
@@ -4606,6 +4624,7 @@ const struct real_format decimal_single_format =
97,
31,
31,
+ 32,
false,
true,
true,
@@ -4629,6 +4648,7 @@ const struct real_format decimal_double_format =
385,
63,
63,
+ 64,
false,
true,
true,
@@ -4652,6 +4672,7 @@ const struct real_format decimal_quad_format =
6145,
127,
127,
+ 128,
false,
true,
true,
@@ -4790,6 +4811,7 @@ const struct real_format ieee_half_format =
16,
15,
15,
+ 16,
false,
true,
true,
@@ -4815,6 +4837,7 @@ const struct real_format arm_half_format =
17,
15,
15,
+ 0,
false,
true,
false,
@@ -4861,6 +4884,7 @@ const struct real_format real_internal_format =
MAX_EXP,
-1,
-1,
+ 0,
false,
false,
true,
diff --git a/gcc/real.h b/gcc/real.h
index be95161cf0a..59af580e78f 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -139,6 +139,17 @@ struct real_format
or -1 for a complex encoding. */
int signbit_rw;
+ /* If this is an IEEE interchange format, the number of bits in the
+ format; otherwise, if it is an IEEE extended format, one more
+ than the greatest number of bits in an interchange format it
+ extends; otherwise 0. Formats need not follow the IEEE 754-2008
+ recommended practice regarding how signaling NaNs are identified,
+ and may vary in the choice of default NaN, but must follow other
+ IEEE practice regarding having NaNs, infinities and subnormal
+ values, and the relation of minimum and maximum exponents, and,
+ for interchange formats, the details of the encoding. */
+ int ieee_bits;
+
/* Default rounding mode for operations on this format. */
bool round_towards_zero;
bool has_sign_dependent_rounding;
diff --git a/gcc/target.def b/gcc/target.def
index 929d9ea05a8..8d506912063 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -3333,6 +3333,26 @@ hook returns true for all of @code{SFmode}, @code{DFmode}, \n\
bool, (machine_mode mode),
default_libgcc_floating_mode_supported_p)
+DEFHOOK
+(floatn_mode,
+ "Define this to return the machine mode to use for the type \n\
+@code{_Float@var{n}}, if @var{extended} is false, or the type \n\
+@code{_Float@var{n}x}, if @var{extended} is true. If such a type \n\
+is not supported, return @code{VOIDmode}. The default version of this \n\
+hook returns @code{SFmode} for @code{_Float32}, @code{DFmode} for \n\
+@code{_Float64} and @code{_Float32x} and @code{TFmode} for \n\
+@code{_Float128}, if those modes exist and satisfy the requirements for \n\
+those types and pass @code{TARGET_SCALAR_MODE_SUPPORTED_P} and \n\
+@code{TARGET_LIBGCC_FLOATING_MODE_SUPPORTED_P}; for @code{_Float64x}, it \n\
+returns the first of @code{XFmode} and @code{TFmode} that exists and \n\
+satisfies the same requirements; for other types, it returns \n\
+@code{VOIDmode}. The hook is only called for values of @var{n} and \n\
+@var{extended} that are valid according to ISO/IEC TS 18661-3:2015; that \n\
+is, @var{n} is one of 32, 64, 128, or, if @var{extended} is false, 16 or \n\
+greater than 128 and a multiple of 32.",
+ machine_mode, (int n, bool extended),
+ default_floatn_mode)
+
/* Compute cost of moving data from a register of class FROM to one of
TO, using MODE. */
DEFHOOK
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index 69037c1ca0f..9d5be1706dd 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -76,6 +76,7 @@ along with GCC; see the file COPYING3. If not see
#include "gimplify.h"
#include "predict.h"
#include "params.h"
+#include "real.h"
bool
@@ -461,6 +462,92 @@ default_libgcc_floating_mode_supported_p (machine_mode mode)
}
}
+/* Return the machine mode to use for the type _FloatN, if EXTENDED is
+ false, or _FloatNx, if EXTENDED is true, or VOIDmode if not
+ supported. */
+machine_mode
+default_floatn_mode (int n, bool extended)
+{
+ if (extended)
+ {
+ machine_mode cand1 = VOIDmode, cand2 = VOIDmode;
+ switch (n)
+ {
+ case 32:
+#ifdef HAVE_DFmode
+ cand1 = DFmode;
+#endif
+ break;
+
+ case 64:
+#ifdef HAVE_XFmode
+ cand1 = XFmode;
+#endif
+#ifdef HAVE_TFmode
+ cand2 = TFmode;
+#endif
+ break;
+
+ case 128:
+ break;
+
+ default:
+ /* Those are the only valid _FloatNx types. */
+ gcc_unreachable ();
+ }
+ if (cand1 != VOIDmode
+ && REAL_MODE_FORMAT (cand1)->ieee_bits > n
+ && targetm.scalar_mode_supported_p (cand1)
+ && targetm.libgcc_floating_mode_supported_p (cand1))
+ return cand1;
+ if (cand2 != VOIDmode
+ && REAL_MODE_FORMAT (cand2)->ieee_bits > n
+ && targetm.scalar_mode_supported_p (cand2)
+ && targetm.libgcc_floating_mode_supported_p (cand2))
+ return cand2;
+ }
+ else
+ {
+ machine_mode cand = VOIDmode;
+ switch (n)
+ {
+ case 16:
+ /* We do not use HFmode for _Float16 by default because the
+ required excess precision support is not present and the
+ interactions with promotion of the older __fp16 need to
+ be worked out. */
+ break;
+
+ case 32:
+#ifdef HAVE_SFmode
+ cand = SFmode;
+#endif
+ break;
+
+ case 64:
+#ifdef HAVE_DFmode
+ cand = DFmode;
+#endif
+ break;
+
+ case 128:
+#ifdef HAVE_TFmode
+ cand = TFmode;
+#endif
+ break;
+
+ default:
+ break;
+ }
+ if (cand != VOIDmode
+ && REAL_MODE_FORMAT (cand)->ieee_bits == n
+ && targetm.scalar_mode_supported_p (cand)
+ && targetm.libgcc_floating_mode_supported_p (cand))
+ return cand;
+ }
+ return VOIDmode;
+}
+
/* Make some target macros useable by target-independent code. */
bool
targhook_words_big_endian (void)
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index 2e7ca72a871..a2fa49f89b3 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -73,6 +73,7 @@ extern tree default_mangle_assembler_name (const char *);
extern bool default_scalar_mode_supported_p (machine_mode);
extern bool default_libgcc_floating_mode_supported_p (machine_mode);
+extern machine_mode default_floatn_mode (int, bool);
extern bool targhook_words_big_endian (void);
extern bool targhook_float_words_big_endian (void);
extern bool default_float_exceptions_rounding_supported_p (void);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index fa0c6985b9e..91ea2788d4c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,77 @@
+2016-08-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/32187
+ * lib/target-supports.exp (check_effective_target_float16)
+ (check_effective_target_float32, check_effective_target_float64)
+ (check_effective_target_float128, check_effective_target_float32x)
+ (check_effective_target_float64x)
+ (check_effective_target_float128x)
+ (check_effective_target_float16_runtime)
+ (check_effective_target_float32_runtime)
+ (check_effective_target_float64_runtime)
+ (check_effective_target_float128_runtime)
+ (check_effective_target_float32x_runtime)
+ (check_effective_target_float64x_runtime)
+ (check_effective_target_float128x_runtime)
+ (check_effective_target_floatn_nx_runtime)
+ (add_options_for_float16, add_options_for_float32)
+ (add_options_for_float64, add_options_for_float128)
+ (add_options_for_float32x, add_options_for_float64x)
+ (add_options_for_float128x): New procedures.
+ * gcc.dg/dfp/floatn.c, gcc.dg/float128-typeof.c,
+ gcc.dg/float128x-typeof.c, gcc.dg/float16-typeof.c,
+ gcc.dg/float32-typeof.c, gcc.dg/float32x-typeof.c,
+ gcc.dg/float64-typeof.c, gcc.dg/float64x-typeof.c,
+ gcc.dg/floatn-arithconv.c, gcc.dg/floatn-errs.c,
+ gcc.dg/floatn-typeof.h, gcc.dg/torture/float128-basic.c,
+ gcc.dg/torture/float128-complex.c,
+ gcc.dg/torture/float128-floath.c, gcc.dg/torture/float128-tg.c,
+ gcc.dg/torture/float128x-basic.c,
+ gcc.dg/torture/float128x-complex.c,
+ gcc.dg/torture/float128x-floath.c, gcc.dg/torture/float128x-tg.c,
+ gcc.dg/torture/float16-basic.c, gcc.dg/torture/float16-complex.c,
+ gcc.dg/torture/float16-floath.c, gcc.dg/torture/float16-tg.c,
+ gcc.dg/torture/float32-basic.c, gcc.dg/torture/float32-complex.c,
+ gcc.dg/torture/float32-floath.c, gcc.dg/torture/float32-tg.c,
+ gcc.dg/torture/float32x-basic.c,
+ gcc.dg/torture/float32x-complex.c,
+ gcc.dg/torture/float32x-floath.c, gcc.dg/torture/float32x-tg.c,
+ gcc.dg/torture/float64-basic.c, gcc.dg/torture/float64-complex.c,
+ gcc.dg/torture/float64-floath.c, gcc.dg/torture/float64-tg.c,
+ gcc.dg/torture/float64x-basic.c,
+ gcc.dg/torture/float64x-complex.c,
+ gcc.dg/torture/float64x-floath.c, gcc.dg/torture/float64x-tg.c,
+ gcc.dg/torture/floatn-basic.h, gcc.dg/torture/floatn-complex.h,
+ gcc.dg/torture/floatn-convert.c, gcc.dg/torture/floatn-floath.h,
+ gcc.dg/torture/floatn-tg.h,
+ gcc.dg/torture/fp-int-convert-float128-ieee-timode.c,
+ gcc.dg/torture/fp-int-convert-float128-ieee.c,
+ gcc.dg/torture/fp-int-convert-float128x-timode.c,
+ gcc.dg/torture/fp-int-convert-float128x.c,
+ gcc.dg/torture/fp-int-convert-float16-timode.c,
+ gcc.dg/torture/fp-int-convert-float16.c,
+ gcc.dg/torture/fp-int-convert-float32-timode.c,
+ gcc.dg/torture/fp-int-convert-float32.c,
+ gcc.dg/torture/fp-int-convert-float32x-timode.c,
+ gcc.dg/torture/fp-int-convert-float32x.c,
+ gcc.dg/torture/fp-int-convert-float64-timode.c,
+ gcc.dg/torture/fp-int-convert-float64.c,
+ gcc.dg/torture/fp-int-convert-float64x-timode.c,
+ gcc.dg/torture/fp-int-convert-float64x.c: New tests.
+ * gcc.dg/torture/fp-int-convert.h (TEST_I_F): Add argument for
+ maximum exponent of floating-point type. Use it in testing
+ whether 0x8...0 fits in the floating-point type. Always treat -1
+ (signed 0xf...f) as fitting in the floating-point type.
+ (M_OK1): New macro.
+ * gcc.dg/torture/fp-int-convert-double.c,
+ gcc.dg/torture/fp-int-convert-float.c,
+ gcc.dg/torture/fp-int-convert-float128-timode.c,
+ gcc.dg/torture/fp-int-convert-float128.c,
+ gcc.dg/torture/fp-int-convert-float80-timode.c,
+ gcc.dg/torture/fp-int-convert-float80.c,
+ gcc.dg/torture/fp-int-convert-long-double.c,
+ gcc.dg/torture/fp-int-convert-timode.c: Update calls to TEST_I_F.
+
2016-08-19 Jakub Jelinek <jakub@redhat.com>
PR fortran/72744
diff --git a/gcc/testsuite/gcc.dg/dfp/floatn.c b/gcc/testsuite/gcc.dg/dfp/floatn.c
new file mode 100644
index 00000000000..4fa7a091ab9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dfp/floatn.c
@@ -0,0 +1,20 @@
+/* Tests for _FloatN / _FloatNx types: test erroneous mixing with DFP. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32 } */
+/* { dg-require-effective-target float32x } */
+
+_Decimal32 d32;
+_Float32 f32;
+_Float32x f32x;
+int i;
+
+void
+f (void)
+{
+ (void) (d32 + f32); /* { dg-error "mix operands" } */
+ (void) (f32x * d32); /* { dg-error "mix operands" } */
+ (void) (i ? d32 : f32); /* { dg-error "mix operands" } */
+}
diff --git a/gcc/testsuite/gcc.dg/float128-typeof.c b/gcc/testsuite/gcc.dg/float128-typeof.c
new file mode 100644
index 00000000000..b6f95b770aa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float128-typeof.c
@@ -0,0 +1,9 @@
+/* Test _Float128 constant types. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128 } */
+
+#define WIDTH 128
+#define EXT 0
+#include "floatn-typeof.h"
diff --git a/gcc/testsuite/gcc.dg/float128x-typeof.c b/gcc/testsuite/gcc.dg/float128x-typeof.c
new file mode 100644
index 00000000000..3ab2ce2debb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float128x-typeof.c
@@ -0,0 +1,9 @@
+/* Test _Float128x constant types. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float128x } */
+
+#define WIDTH 128
+#define EXT 1
+#include "floatn-typeof.h"
diff --git a/gcc/testsuite/gcc.dg/float16-typeof.c b/gcc/testsuite/gcc.dg/float16-typeof.c
new file mode 100644
index 00000000000..a781239efa2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float16-typeof.c
@@ -0,0 +1,9 @@
+/* Test _Float16 constant types. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-require-effective-target float16 } */
+
+#define WIDTH 16
+#define EXT 0
+#include "floatn-typeof.h"
diff --git a/gcc/testsuite/gcc.dg/float32-typeof.c b/gcc/testsuite/gcc.dg/float32-typeof.c
new file mode 100644
index 00000000000..4b9ccf82cc3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float32-typeof.c
@@ -0,0 +1,9 @@
+/* Test _Float32 constant types. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-require-effective-target float32 } */
+
+#define WIDTH 32
+#define EXT 0
+#include "floatn-typeof.h"
diff --git a/gcc/testsuite/gcc.dg/float32x-typeof.c b/gcc/testsuite/gcc.dg/float32x-typeof.c
new file mode 100644
index 00000000000..9af60778d44
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float32x-typeof.c
@@ -0,0 +1,9 @@
+/* Test _Float32x constant types. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32x } */
+
+#define WIDTH 32
+#define EXT 1
+#include "floatn-typeof.h"
diff --git a/gcc/testsuite/gcc.dg/float64-typeof.c b/gcc/testsuite/gcc.dg/float64-typeof.c
new file mode 100644
index 00000000000..aa7d504efda
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float64-typeof.c
@@ -0,0 +1,9 @@
+/* Test _Float64 constant types. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float64 } */
+/* { dg-require-effective-target float64 } */
+
+#define WIDTH 64
+#define EXT 0
+#include "floatn-typeof.h"
diff --git a/gcc/testsuite/gcc.dg/float64x-typeof.c b/gcc/testsuite/gcc.dg/float64x-typeof.c
new file mode 100644
index 00000000000..934d6cf5f4e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float64x-typeof.c
@@ -0,0 +1,9 @@
+/* Test _Float64x constant types. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float64x } */
+/* { dg-require-effective-target float64x } */
+
+#define WIDTH 64
+#define EXT 1
+#include "floatn-typeof.h"
diff --git a/gcc/testsuite/gcc.dg/floatn-arithconv.c b/gcc/testsuite/gcc.dg/floatn-arithconv.c
new file mode 100644
index 00000000000..c3eb24e1fcd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/floatn-arithconv.c
@@ -0,0 +1,50 @@
+/* Tests for _FloatN / _FloatNx types: test usual arithmetic
+ conversions. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-add-options float64 } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32 } */
+/* { dg-require-effective-target float64 } */
+/* { dg-require-effective-target float32x } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+
+int i;
+
+#define TEST(VAR, TYPE1, TYPE2, RESTYPE) \
+ do \
+ { \
+ typedef __typeof__ ((TYPE1) 0 + (TYPE2) 1) restype; \
+ typedef __typeof__ (i ? (TYPE1) 0 : (TYPE2) 1) restype2; \
+ typedef RESTYPE exptype; \
+ extern restype VAR; \
+ extern restype2 VAR; \
+ extern exptype VAR; \
+ } \
+ while (0)
+
+void
+f (void)
+{
+ TEST (v1, float, double, double);
+#if DBL_MANT_DIG > FLT32_MANT_DIG
+ TEST (v2, double, _Float32, double);
+#endif
+#if DBL_MANT_DIG <= FLT64_MANT_DIG
+ TEST (v3, double, _Float64, _Float64);
+#endif
+#if DBL_MANT_DIG >= FLT32X_MANT_DIG
+ TEST (v4, double, _Float32x, double);
+#endif
+#if FLT_MANT_DIG <= FLT32_MANT_DIG
+ TEST (v5, float, _Float32, _Float32);
+#endif
+#if FLT32X_MANT_DIG <= FLT64_MANT_DIG
+ TEST (v6, _Float32x, _Float64, _Float64);
+#endif
+ TEST (v7, _Float32, _Float64, _Float64);
+ TEST (v8, _Float32, _Float32x, _Float32x);
+}
diff --git a/gcc/testsuite/gcc.dg/floatn-errs.c b/gcc/testsuite/gcc.dg/floatn-errs.c
new file mode 100644
index 00000000000..0dcc2f1bb97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/floatn-errs.c
@@ -0,0 +1,44 @@
+/* Tests for _FloatN / _FloatNx types: test erroneous code. */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-add-options float64 } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32 } */
+/* { dg-require-effective-target float32x } */
+/* { dg-require-effective-target float64 } */
+
+/* _FloatN, _FloatNx and standard types are incompatible even if they
+ have the same ABI. */
+
+extern float a; /* { dg-message "previous declaration" } */
+extern _Float32 a; /* { dg-error "conflicting" } */
+
+extern double b; /* { dg-message "previous declaration" } */
+extern _Float32x b; /* { dg-error "conflicting" } */
+
+extern _Float64 c; /* { dg-message "previous declaration" } */
+extern _Float32x c; /* { dg-error "conflicting" } */
+
+/* These types are not promoted in old-style function definitions. */
+
+void f (_Float32);
+void
+f (x)
+ _Float32 x;
+{
+}
+
+void g (double); /* { dg-error "prototype declaration" } */
+void
+g (x)
+ _Float32 x; /* { dg-error "match prototype" } */
+{
+}
+
+void h (_Float64); /* { dg-error "prototype declaration" } */
+void
+h (x)
+ _Float32 x; /* { dg-error "match prototype" } */
+{
+}
diff --git a/gcc/testsuite/gcc.dg/floatn-typeof.h b/gcc/testsuite/gcc.dg/floatn-typeof.h
new file mode 100644
index 00000000000..4a3e5865a4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/floatn-typeof.h
@@ -0,0 +1,22 @@
+/* Tests for _FloatN / _FloatNx types: test types of constants.
+ Before including this file, define WIDTH as the value N; define EXT
+ to 1 for _FloatNx and 0 for _FloatN. */
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
+
+#if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define CSTU(C) CONCAT4 (C, F, WIDTH, x)
+#else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define CSTU(C) CONCAT3 (C, F, WIDTH)
+#endif
+
+extern TYPE test_type;
+extern __typeof (CST (1.0)) test_type;
+extern __typeof (CSTU (1.0)) test_type;
diff --git a/gcc/testsuite/gcc.dg/torture/float128-basic.c b/gcc/testsuite/gcc.dg/torture/float128-basic.c
new file mode 100644
index 00000000000..b23d45bf72b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-basic.c
@@ -0,0 +1,9 @@
+/* Test _Float128. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128_runtime } */
+
+#define WIDTH 128
+#define EXT 0
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float128-complex.c b/gcc/testsuite/gcc.dg/torture/float128-complex.c
new file mode 100644
index 00000000000..fe93fe69a57
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-complex.c
@@ -0,0 +1,9 @@
+/* Test _Float128 complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128_runtime } */
+
+#define WIDTH 128
+#define EXT 0
+#include "floatn-complex.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float128-floath.c b/gcc/testsuite/gcc.dg/torture/float128-floath.c
new file mode 100644
index 00000000000..68147c35fb6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-floath.c
@@ -0,0 +1,61 @@
+/* Test _Float128 <float.h> macros. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128_runtime } */
+
+#define WIDTH 128
+#define EXT 0
+#include "floatn-floath.h"
+
+#ifndef FLT128_MANT_DIG
+# error "FLT128_MANT_DIG undefined"
+#endif
+
+#ifndef FLT128_DECIMAL_DIG
+# error "FLT128_DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT128_DIG
+# error "FLT128_DIG undefined"
+#endif
+
+#ifndef FLT128_MIN_EXP
+# error "FLT128_MIN_EXP undefined"
+#endif
+
+#ifndef FLT128_MIN_10_EXP
+# error "FLT128_MIN_10_EXP undefined"
+#endif
+
+#ifndef FLT128_MAX_EXP
+# error "FLT128_MAX_EXP undefined"
+#endif
+
+#ifndef FLT128_MAX_10_EXP
+# error "FLT128_MAX_10_EXP undefined"
+#endif
+
+#ifndef FLT128_MAX
+# error "FLT128_MAX undefined"
+#endif
+
+#ifndef FLT128_EPSILON
+# error "FLT128_EPSILON undefined"
+#endif
+
+#ifndef FLT128_MIN
+# error "FLT128_MIN undefined"
+#endif
+
+#ifndef FLT128_TRUE_MIN
+# error "FLT128_TRUE_MIN undefined"
+#endif
+
+#if FLT128_DECIMAL_DIG > DECIMAL_DIG
+# error "FLT128_DECIMAL_DIG > DECIMAL_DIG"
+#endif
+
+#if FLT128_MANT_DIG != 113 || FLT128_MAX_EXP != 16384 || FLT128_MIN_EXP != -16381
+# error "_Float128 bad format"
+#endif
diff --git a/gcc/testsuite/gcc.dg/torture/float128-tg.c b/gcc/testsuite/gcc.dg/torture/float128-tg.c
new file mode 100644
index 00000000000..c1b6398d92b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128-tg.c
@@ -0,0 +1,9 @@
+/* Test _Float128 type-generic built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128_runtime } */
+
+#define WIDTH 128
+#define EXT 0
+#include "floatn-tg.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float128x-basic.c b/gcc/testsuite/gcc.dg/torture/float128x-basic.c
new file mode 100644
index 00000000000..75c5a28bb9d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128x-basic.c
@@ -0,0 +1,9 @@
+/* Test _Float128x. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float128x_runtime } */
+
+#define WIDTH 128
+#define EXT 1
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float128x-complex.c b/gcc/testsuite/gcc.dg/torture/float128x-complex.c
new file mode 100644
index 00000000000..185b501840c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128x-complex.c
@@ -0,0 +1,9 @@
+/* Test _Float128x complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float128x_runtime } */
+
+#define WIDTH 128
+#define EXT 1
+#include "floatn-complex.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float128x-floath.c b/gcc/testsuite/gcc.dg/torture/float128x-floath.c
new file mode 100644
index 00000000000..0fc3db2744f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128x-floath.c
@@ -0,0 +1,61 @@
+/* Test _Float128x <float.h> macros. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float128x_runtime } */
+
+#define WIDTH 128
+#define EXT 1
+#include "floatn-floath.h"
+
+#ifndef FLT128X_MANT_DIG
+# error "FLT128X_MANT_DIG undefined"
+#endif
+
+#ifndef FLT128X_DECIMAL_DIG
+# error "FLT128X_DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT128X_DIG
+# error "FLT128X_DIG undefined"
+#endif
+
+#ifndef FLT128X_MIN_EXP
+# error "FLT128X_MIN_EXP undefined"
+#endif
+
+#ifndef FLT128X_MIN_10_EXP
+# error "FLT128X_MIN_10_EXP undefined"
+#endif
+
+#ifndef FLT128X_MAX_EXP
+# error "FLT128X_MAX_EXP undefined"
+#endif
+
+#ifndef FLT128X_MAX_10_EXP
+# error "FLT128X_MAX_10_EXP undefined"
+#endif
+
+#ifndef FLT128X_MAX
+# error "FLT128X_MAX undefined"
+#endif
+
+#ifndef FLT128X_EPSILON
+# error "FLT128X_EPSILON undefined"
+#endif
+
+#ifndef FLT128X_MIN
+# error "FLT128X_MIN undefined"
+#endif
+
+#ifndef FLT128X_TRUE_MIN
+# error "FLT128X_TRUE_MIN undefined"
+#endif
+
+#if FLT128X_DECIMAL_DIG > DECIMAL_DIG
+# error "FLT128X_DECIMAL_DIG > DECIMAL_DIG"
+#endif
+
+#if FLT128X_MANT_DIG < 128 || FLT128X_MAX_EXP < 65536 || FLT128X_MIN_EXP + FLT128X_MAX_EXP != 3
+# error "_Float128x bad format"
+#endif
diff --git a/gcc/testsuite/gcc.dg/torture/float128x-tg.c b/gcc/testsuite/gcc.dg/torture/float128x-tg.c
new file mode 100644
index 00000000000..0dc1e0f6823
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float128x-tg.c
@@ -0,0 +1,9 @@
+/* Test _Float128x type-generic built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float128x_runtime } */
+
+#define WIDTH 128
+#define EXT 1
+#include "floatn-tg.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float16-basic.c b/gcc/testsuite/gcc.dg/torture/float16-basic.c
new file mode 100644
index 00000000000..e94aa203d40
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float16-basic.c
@@ -0,0 +1,9 @@
+/* Test _Float16. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-require-effective-target float16_runtime } */
+
+#define WIDTH 16
+#define EXT 0
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float16-complex.c b/gcc/testsuite/gcc.dg/torture/float16-complex.c
new file mode 100644
index 00000000000..463e703d6c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float16-complex.c
@@ -0,0 +1,9 @@
+/* Test _Float16 complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-require-effective-target float16_runtime } */
+
+#define WIDTH 16
+#define EXT 0
+#include "floatn-complex.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float16-floath.c b/gcc/testsuite/gcc.dg/torture/float16-floath.c
new file mode 100644
index 00000000000..6857c2e9aa8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float16-floath.c
@@ -0,0 +1,61 @@
+/* Test _Float16 <float.h> macros. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-require-effective-target float16_runtime } */
+
+#define WIDTH 16
+#define EXT 0
+#include "floatn-floath.h"
+
+#ifndef FLT16_MANT_DIG
+# error "FLT16_MANT_DIG undefined"
+#endif
+
+#ifndef FLT16_DECIMAL_DIG
+# error "FLT16_DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT16_DIG
+# error "FLT16_DIG undefined"
+#endif
+
+#ifndef FLT16_MIN_EXP
+# error "FLT16_MIN_EXP undefined"
+#endif
+
+#ifndef FLT16_MIN_10_EXP
+# error "FLT16_MIN_10_EXP undefined"
+#endif
+
+#ifndef FLT16_MAX_EXP
+# error "FLT16_MAX_EXP undefined"
+#endif
+
+#ifndef FLT16_MAX_10_EXP
+# error "FLT16_MAX_10_EXP undefined"
+#endif
+
+#ifndef FLT16_MAX
+# error "FLT16_MAX undefined"
+#endif
+
+#ifndef FLT16_EPSILON
+# error "FLT16_EPSILON undefined"
+#endif
+
+#ifndef FLT16_MIN
+# error "FLT16_MIN undefined"
+#endif
+
+#ifndef FLT16_TRUE_MIN
+# error "FLT16_TRUE_MIN undefined"
+#endif
+
+#if FLT16_DECIMAL_DIG > DECIMAL_DIG
+# error "FLT16_DECIMAL_DIG > DECIMAL_DIG"
+#endif
+
+#if FLT16_MANT_DIG != 11 || FLT16_MAX_EXP != 16 || FLT16_MIN_EXP != -13
+# error "_Float16 bad format"
+#endif
diff --git a/gcc/testsuite/gcc.dg/torture/float16-tg.c b/gcc/testsuite/gcc.dg/torture/float16-tg.c
new file mode 100644
index 00000000000..39e8285b6e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float16-tg.c
@@ -0,0 +1,9 @@
+/* Test _Float16 type-generic built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-require-effective-target float16_runtime } */
+
+#define WIDTH 16
+#define EXT 0
+#include "floatn-tg.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32-basic.c b/gcc/testsuite/gcc.dg/torture/float32-basic.c
new file mode 100644
index 00000000000..2d3e7a96175
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32-basic.c
@@ -0,0 +1,9 @@
+/* Test _Float32. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-require-effective-target float32_runtime } */
+
+#define WIDTH 32
+#define EXT 0
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32-complex.c b/gcc/testsuite/gcc.dg/torture/float32-complex.c
new file mode 100644
index 00000000000..8717a3f4571
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32-complex.c
@@ -0,0 +1,9 @@
+/* Test _Float32 complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-require-effective-target float32_runtime } */
+
+#define WIDTH 32
+#define EXT 0
+#include "floatn-complex.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32-floath.c b/gcc/testsuite/gcc.dg/torture/float32-floath.c
new file mode 100644
index 00000000000..795cb21082f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32-floath.c
@@ -0,0 +1,61 @@
+/* Test _Float32 <float.h> macros. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-require-effective-target float32_runtime } */
+
+#define WIDTH 32
+#define EXT 0
+#include "floatn-floath.h"
+
+#ifndef FLT32_MANT_DIG
+# error "FLT32_MANT_DIG undefined"
+#endif
+
+#ifndef FLT32_DECIMAL_DIG
+# error "FLT32_DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT32_DIG
+# error "FLT32_DIG undefined"
+#endif
+
+#ifndef FLT32_MIN_EXP
+# error "FLT32_MIN_EXP undefined"
+#endif
+
+#ifndef FLT32_MIN_10_EXP
+# error "FLT32_MIN_10_EXP undefined"
+#endif
+
+#ifndef FLT32_MAX_EXP
+# error "FLT32_MAX_EXP undefined"
+#endif
+
+#ifndef FLT32_MAX_10_EXP
+# error "FLT32_MAX_10_EXP undefined"
+#endif
+
+#ifndef FLT32_MAX
+# error "FLT32_MAX undefined"
+#endif
+
+#ifndef FLT32_EPSILON
+# error "FLT32_EPSILON undefined"
+#endif
+
+#ifndef FLT32_MIN
+# error "FLT32_MIN undefined"
+#endif
+
+#ifndef FLT32_TRUE_MIN
+# error "FLT32_TRUE_MIN undefined"
+#endif
+
+#if FLT32_DECIMAL_DIG > DECIMAL_DIG
+# error "FLT32_DECIMAL_DIG > DECIMAL_DIG"
+#endif
+
+#if FLT32_MANT_DIG != 24 || FLT32_MAX_EXP != 128 || FLT32_MIN_EXP != -125
+# error "_Float32 bad format"
+#endif
diff --git a/gcc/testsuite/gcc.dg/torture/float32-tg.c b/gcc/testsuite/gcc.dg/torture/float32-tg.c
new file mode 100644
index 00000000000..da480ca87c5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32-tg.c
@@ -0,0 +1,9 @@
+/* Test _Float32 type-generic built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-require-effective-target float32_runtime } */
+
+#define WIDTH 32
+#define EXT 0
+#include "floatn-tg.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32x-basic.c b/gcc/testsuite/gcc.dg/torture/float32x-basic.c
new file mode 100644
index 00000000000..f2abc332488
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32x-basic.c
@@ -0,0 +1,9 @@
+/* Test _Float32x. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32x_runtime } */
+
+#define WIDTH 32
+#define EXT 1
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32x-complex.c b/gcc/testsuite/gcc.dg/torture/float32x-complex.c
new file mode 100644
index 00000000000..4a63a50b5c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32x-complex.c
@@ -0,0 +1,9 @@
+/* Test _Float32x complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32x_runtime } */
+
+#define WIDTH 32
+#define EXT 1
+#include "floatn-complex.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float32x-floath.c b/gcc/testsuite/gcc.dg/torture/float32x-floath.c
new file mode 100644
index 00000000000..49e7ba4ed3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32x-floath.c
@@ -0,0 +1,61 @@
+/* Test _Float32x <float.h> macros. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32x_runtime } */
+
+#define WIDTH 32
+#define EXT 1
+#include "floatn-floath.h"
+
+#ifndef FLT32X_MANT_DIG
+# error "FLT32X_MANT_DIG undefined"
+#endif
+
+#ifndef FLT32X_DECIMAL_DIG
+# error "FLT32X_DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT32X_DIG
+# error "FLT32X_DIG undefined"
+#endif
+
+#ifndef FLT32X_MIN_EXP
+# error "FLT32X_MIN_EXP undefined"
+#endif
+
+#ifndef FLT32X_MIN_10_EXP
+# error "FLT32X_MIN_10_EXP undefined"
+#endif
+
+#ifndef FLT32X_MAX_EXP
+# error "FLT32X_MAX_EXP undefined"
+#endif
+
+#ifndef FLT32X_MAX_10_EXP
+# error "FLT32X_MAX_10_EXP undefined"
+#endif
+
+#ifndef FLT32X_MAX
+# error "FLT32X_MAX undefined"
+#endif
+
+#ifndef FLT32X_EPSILON
+# error "FLT32X_EPSILON undefined"
+#endif
+
+#ifndef FLT32X_MIN
+# error "FLT32X_MIN undefined"
+#endif
+
+#ifndef FLT32X_TRUE_MIN
+# error "FLT32X_TRUE_MIN undefined"
+#endif
+
+#if FLT32X_DECIMAL_DIG > DECIMAL_DIG
+# error "FLT32X_DECIMAL_DIG > DECIMAL_DIG"
+#endif
+
+#if FLT32X_MANT_DIG < 32 || FLT32X_MAX_EXP < 1024 || FLT32X_MIN_EXP + FLT32X_MAX_EXP != 3
+# error "_Float32x bad format"
+#endif
diff --git a/gcc/testsuite/gcc.dg/torture/float32x-tg.c b/gcc/testsuite/gcc.dg/torture/float32x-tg.c
new file mode 100644
index 00000000000..9f9a3bf8682
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float32x-tg.c
@@ -0,0 +1,9 @@
+/* Test _Float32x type-generic built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32x_runtime } */
+
+#define WIDTH 32
+#define EXT 1
+#include "floatn-tg.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64-basic.c b/gcc/testsuite/gcc.dg/torture/float64-basic.c
new file mode 100644
index 00000000000..decb05f34b2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64-basic.c
@@ -0,0 +1,9 @@
+/* Test _Float64. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64 } */
+/* { dg-require-effective-target float64_runtime } */
+
+#define WIDTH 64
+#define EXT 0
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64-complex.c b/gcc/testsuite/gcc.dg/torture/float64-complex.c
new file mode 100644
index 00000000000..6a832c2a057
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64-complex.c
@@ -0,0 +1,9 @@
+/* Test _Float64 complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64 } */
+/* { dg-require-effective-target float64_runtime } */
+
+#define WIDTH 64
+#define EXT 0
+#include "floatn-complex.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64-floath.c b/gcc/testsuite/gcc.dg/torture/float64-floath.c
new file mode 100644
index 00000000000..a03d2e7dab7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64-floath.c
@@ -0,0 +1,61 @@
+/* Test _Float64 <float.h> macros. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64 } */
+/* { dg-require-effective-target float64_runtime } */
+
+#define WIDTH 64
+#define EXT 0
+#include "floatn-floath.h"
+
+#ifndef FLT64_MANT_DIG
+# error "FLT64_MANT_DIG undefined"
+#endif
+
+#ifndef FLT64_DECIMAL_DIG
+# error "FLT64_DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT64_DIG
+# error "FLT64_DIG undefined"
+#endif
+
+#ifndef FLT64_MIN_EXP
+# error "FLT64_MIN_EXP undefined"
+#endif
+
+#ifndef FLT64_MIN_10_EXP
+# error "FLT64_MIN_10_EXP undefined"
+#endif
+
+#ifndef FLT64_MAX_EXP
+# error "FLT64_MAX_EXP undefined"
+#endif
+
+#ifndef FLT64_MAX_10_EXP
+# error "FLT64_MAX_10_EXP undefined"
+#endif
+
+#ifndef FLT64_MAX
+# error "FLT64_MAX undefined"
+#endif
+
+#ifndef FLT64_EPSILON
+# error "FLT64_EPSILON undefined"
+#endif
+
+#ifndef FLT64_MIN
+# error "FLT64_MIN undefined"
+#endif
+
+#ifndef FLT64_TRUE_MIN
+# error "FLT64_TRUE_MIN undefined"
+#endif
+
+#if FLT64_DECIMAL_DIG > DECIMAL_DIG
+# error "FLT64_DECIMAL_DIG > DECIMAL_DIG"
+#endif
+
+#if FLT64_MANT_DIG != 53 || FLT64_MAX_EXP != 1024 || FLT64_MIN_EXP != -1021
+# error "_Float64 bad format"
+#endif
diff --git a/gcc/testsuite/gcc.dg/torture/float64-tg.c b/gcc/testsuite/gcc.dg/torture/float64-tg.c
new file mode 100644
index 00000000000..c970d53b5ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64-tg.c
@@ -0,0 +1,9 @@
+/* Test _Float64 type-generic built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64 } */
+/* { dg-require-effective-target float64_runtime } */
+
+#define WIDTH 64
+#define EXT 0
+#include "floatn-tg.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64x-basic.c b/gcc/testsuite/gcc.dg/torture/float64x-basic.c
new file mode 100644
index 00000000000..7a140af0bd7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64x-basic.c
@@ -0,0 +1,9 @@
+/* Test _Float64x. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64x } */
+/* { dg-require-effective-target float64x_runtime } */
+
+#define WIDTH 64
+#define EXT 1
+#include "floatn-basic.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64x-complex.c b/gcc/testsuite/gcc.dg/torture/float64x-complex.c
new file mode 100644
index 00000000000..cb573befebb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64x-complex.c
@@ -0,0 +1,9 @@
+/* Test _Float64x complex arithmetic. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64x } */
+/* { dg-require-effective-target float64x_runtime } */
+
+#define WIDTH 64
+#define EXT 1
+#include "floatn-complex.h"
diff --git a/gcc/testsuite/gcc.dg/torture/float64x-floath.c b/gcc/testsuite/gcc.dg/torture/float64x-floath.c
new file mode 100644
index 00000000000..11eddc7036b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64x-floath.c
@@ -0,0 +1,61 @@
+/* Test _Float64x <float.h> macros. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64x } */
+/* { dg-require-effective-target float64x_runtime } */
+
+#define WIDTH 64
+#define EXT 1
+#include "floatn-floath.h"
+
+#ifndef FLT64X_MANT_DIG
+# error "FLT64X_MANT_DIG undefined"
+#endif
+
+#ifndef FLT64X_DECIMAL_DIG
+# error "FLT64X_DECIMAL_DIG undefined"
+#endif
+
+#ifndef FLT64X_DIG
+# error "FLT64X_DIG undefined"
+#endif
+
+#ifndef FLT64X_MIN_EXP
+# error "FLT64X_MIN_EXP undefined"
+#endif
+
+#ifndef FLT64X_MIN_10_EXP
+# error "FLT64X_MIN_10_EXP undefined"
+#endif
+
+#ifndef FLT64X_MAX_EXP
+# error "FLT64X_MAX_EXP undefined"
+#endif
+
+#ifndef FLT64X_MAX_10_EXP
+# error "FLT64X_MAX_10_EXP undefined"
+#endif
+
+#ifndef FLT64X_MAX
+# error "FLT64X_MAX undefined"
+#endif
+
+#ifndef FLT64X_EPSILON
+# error "FLT64X_EPSILON undefined"
+#endif
+
+#ifndef FLT64X_MIN
+# error "FLT64X_MIN undefined"
+#endif
+
+#ifndef FLT64X_TRUE_MIN
+# error "FLT64X_TRUE_MIN undefined"
+#endif
+
+#if FLT64X_DECIMAL_DIG > DECIMAL_DIG
+# error "FLT64X_DECIMAL_DIG > DECIMAL_DIG"
+#endif
+
+#if FLT64X_MANT_DIG < 64 || FLT64X_MAX_EXP < 16384 || FLT64X_MIN_EXP + FLT64X_MAX_EXP != 3
+# error "_Float64x bad format"
+#endif
diff --git a/gcc/testsuite/gcc.dg/torture/float64x-tg.c b/gcc/testsuite/gcc.dg/torture/float64x-tg.c
new file mode 100644
index 00000000000..ac14675a669
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/float64x-tg.c
@@ -0,0 +1,9 @@
+/* Test _Float64x type-generic built-in functions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64x } */
+/* { dg-require-effective-target float64x_runtime } */
+
+#define WIDTH 64
+#define EXT 1
+#include "floatn-tg.h"
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-basic.h b/gcc/testsuite/gcc.dg/torture/floatn-basic.h
new file mode 100644
index 00000000000..9131f46752c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/floatn-basic.h
@@ -0,0 +1,141 @@
+/* Basic tests for _FloatN / _FloatNx types: compile and execution
+ tests for valid code. Before including this file, define WIDTH as
+ the value N; define EXT to 1 for _FloatNx and 0 for _FloatN. */
+
+#include <stdarg.h>
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
+
+#if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define CSTU(C) CONCAT4 (C, F, WIDTH, x)
+#else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define CSTU(C) CONCAT3 (C, F, WIDTH)
+#endif
+
+extern void exit (int);
+extern void abort (void);
+
+volatile TYPE a = CST (1.0), b = CSTU (2.5), c = -CST (2.5);
+volatile TYPE a2 = CST (1.0), z = CST (0.0), nz = -CST (0.0);
+
+/* These types are not subject to default argument promotions. */
+
+TYPE
+vafn (TYPE arg1, ...)
+{
+ va_list ap;
+ TYPE ret;
+ va_start (ap, arg1);
+ ret = arg1 + va_arg (ap, TYPE);
+ va_end (ap);
+ return ret;
+}
+
+TYPE
+krfn (arg)
+ TYPE arg;
+{
+ return arg + 1;
+}
+
+TYPE krprofn (TYPE);
+TYPE
+krprofn (arg)
+ TYPE arg;
+{
+ return arg * 3;
+}
+
+TYPE
+profn (TYPE arg)
+{
+ return arg / 4;
+}
+
+int
+main (void)
+{
+ volatile TYPE r;
+ r = -b;
+ if (r != c)
+ abort ();
+ r = a + b;
+ if (r != CST (3.5))
+ abort ();
+ r = a - b;
+ if (r != -CST (1.5))
+ abort ();
+ r = 2 * c;
+ if (r != -5)
+ abort ();
+ r = b * c;
+ if (r != -CST (6.25))
+ abort ();
+ r = b / (a + a);
+ if (r != CST (1.25))
+ abort ();
+ r = c * 3;
+ if (r != -CST (7.5))
+ abort ();
+ volatile int i = r;
+ if (i != -7)
+ abort ();
+ r = vafn (a, c);
+ if (r != -CST (1.5))
+ abort ();
+ r = krfn (b);
+ if (r != CST (3.5))
+ abort ();
+ r = krprofn (a);
+ if (r != CST (3.0))
+ abort ();
+ r = profn (a);
+ if (r != CST (0.25))
+ abort ();
+ if ((a < b) != 1)
+ abort ();
+ if ((b < a) != 0)
+ abort ();
+ if ((a < a2) != 0)
+ abort ();
+ if ((nz < z) != 0)
+ abort ();
+ if ((a <= b) != 1)
+ abort ();
+ if ((b <= a) != 0)
+ abort ();
+ if ((a <= a2) != 1)
+ abort ();
+ if ((nz <= z) != 1)
+ abort ();
+ if ((a > b) != 0)
+ abort ();
+ if ((b > a) != 1)
+ abort ();
+ if ((a > a2) != 0)
+ abort ();
+ if ((nz > z) != 0)
+ abort ();
+ if ((a >= b) != 0)
+ abort ();
+ if ((b >= a) != 1)
+ abort ();
+ if ((a >= a2) != 1)
+ abort ();
+ if ((nz >= z) != 1)
+ abort ();
+ i = (nz == z);
+ if (i != 1)
+ abort ();
+ i = (a == b);
+ if (i != 0)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-complex.h b/gcc/testsuite/gcc.dg/torture/floatn-complex.h
new file mode 100644
index 00000000000..7e32fafdbcf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/floatn-complex.h
@@ -0,0 +1,76 @@
+/* Tests for _FloatN / _FloatNx types: compile and execution tests for
+ valid code with complex arithmetic. Before including this file,
+ define WIDTH as the value N; define EXT to 1 for _FloatNx and 0 for
+ _FloatN. */
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
+
+#if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define CSTI(C) CONCAT4 (C, if, WIDTH, x)
+# define CSTI2(C) CONCAT4 (C, F, WIDTH, xi)
+#else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define CSTI(C) CONCAT3 (C, if, WIDTH)
+# define CSTI2(C) CONCAT4 (C, F, WIDTH, i)
+#endif
+
+extern void exit (int);
+extern void abort (void);
+
+volatile TYPE a = CST (1.0);
+volatile _Complex TYPE b = CST (2.0) + CSTI (3.0);
+volatile _Complex TYPE c = CST (2.0) + CSTI2 (3.0);
+volatile _Complex TYPE d = __builtin_complex (CST (2.0), CST (3.0));
+
+_Complex TYPE
+fn (_Complex TYPE arg)
+{
+ return arg / 4;
+}
+
+int
+main (void)
+{
+ volatile _Complex TYPE r;
+ if (b != c)
+ abort ();
+ if (b != d)
+ abort ();
+ r = a + b;
+ if (__real__ r != CST (3.0) || __imag__ r != CST (3.0))
+ abort ();
+ r += d;
+ if (__real__ r != CST (5.0) || __imag__ r != CST (6.0))
+ abort ();
+ r -= a;
+ if (__real__ r != CST (4.0) || __imag__ r != CST (6.0))
+ abort ();
+ r /= (a + a);
+ if (__real__ r != CST (2.0) || __imag__ r != CST (3.0))
+ abort ();
+ r *= (a + a);
+ if (__real__ r != CST (4.0) || __imag__ r != CST (6.0))
+ abort ();
+ r -= b;
+ if (__real__ r != CST (2.0) || __imag__ r != CST (3.0))
+ abort ();
+ r *= r;
+ if (__real__ r != -CST (5.0) || __imag__ r != CST (12.0))
+ abort ();
+ /* Division may not be exact, so round result before comparing. */
+ r /= b;
+ r += __builtin_complex (CST (100.0), CST (100.0));
+ r -= __builtin_complex (CST (100.0), CST (100.0));
+ if (r != b)
+ abort ();
+ r = fn (r);
+ if (__real__ r != CST (0.5) || __imag__ r != CST (0.75))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-convert.c b/gcc/testsuite/gcc.dg/torture/floatn-convert.c
new file mode 100644
index 00000000000..741ffc8800f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/floatn-convert.c
@@ -0,0 +1,104 @@
+/* Tests for _FloatN / _FloatNx types: test conversions. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-add-options float32 } */
+/* { dg-add-options float64 } */
+/* { dg-add-options float128 } */
+/* { dg-add-options float32x } */
+/* { dg-add-options float64x } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float32 } */
+/* { dg-require-effective-target floatn_nx_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+
+#ifndef FLT16_MAX
+# define _Float16 _Float32
+# define FLT16_MAX FLT32_MAX
+# define FLT16_MANT_DIG FLT32_MANT_DIG
+# define FLT16_EPSILON FLT32_EPSILON
+#endif
+
+#ifndef FLT64_MAX
+# define _Float64 _Float32
+# define FLT64_MAX FLT32_MAX
+# define FLT64_MANT_DIG FLT32_MANT_DIG
+# define FLT64_EPSILON FLT32_EPSILON
+#endif
+
+#ifndef FLT128_MAX
+# define _Float128 _Float32
+# define FLT128_MAX FLT32_MAX
+# define FLT128_MANT_DIG FLT32_MANT_DIG
+# define FLT128_EPSILON FLT32_EPSILON
+#endif
+
+#ifndef FLT32X_MAX
+# define _Float32x _Float32
+# define FLT32X_MAX FLT32_MAX
+# define FLT32X_MANT_DIG FLT32_MANT_DIG
+# define FLT32X_EPSILON FLT32_EPSILON
+#endif
+
+#ifndef FLT64X_MAX
+# define _Float64x _Float32
+# define FLT64X_MAX FLT32_MAX
+# define FLT64X_MANT_DIG FLT32_MANT_DIG
+# define FLT64X_EPSILON FLT32_EPSILON
+#endif
+
+#ifndef FLT128X_MAX
+# define _Float128x _Float32
+# define FLT128X_MAX FLT32_MAX
+# define FLT128X_MANT_DIG FLT32_MANT_DIG
+# define FLT128X_EPSILON FLT32_EPSILON
+#endif
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+
+extern void exit (int);
+extern void abort (void);
+
+#define DO_TEST(TYPE1, PFX1, TYPE2, PFX2) \
+ do \
+ { \
+ volatile TYPE1 a = (TYPE1) 1 + CONCAT (PFX1, _EPSILON); \
+ volatile TYPE2 b = (TYPE2) a; \
+ volatile TYPE2 expected; \
+ if (CONCAT (PFX2, _MANT_DIG) < CONCAT (PFX1, _MANT_DIG)) \
+ expected = (TYPE2) 1; \
+ else \
+ expected = (TYPE2) 1 + (TYPE2) CONCAT (PFX1, _EPSILON); \
+ if (b != expected) \
+ abort (); \
+ } \
+ while (0)
+
+#define DO_TEST1(TYPE1, PFX1) \
+ do \
+ { \
+ DO_TEST (TYPE1, PFX1, _Float16, FLT16); \
+ DO_TEST (TYPE1, PFX1, _Float32, FLT32); \
+ DO_TEST (TYPE1, PFX1, _Float64, FLT64); \
+ DO_TEST (TYPE1, PFX1, _Float128, FLT128); \
+ DO_TEST (TYPE1, PFX1, _Float32x, FLT32X); \
+ DO_TEST (TYPE1, PFX1, _Float64x, FLT64X); \
+ DO_TEST (TYPE1, PFX1, _Float128x, FLT128X); \
+ } \
+ while (0)
+
+int
+main (void)
+{
+ DO_TEST1 (_Float16, FLT16);
+ DO_TEST1 (_Float32, FLT32);
+ DO_TEST1 (_Float64, FLT64);
+ DO_TEST1 (_Float128, FLT128);
+ DO_TEST1 (_Float32x, FLT32X);
+ DO_TEST1 (_Float64x, FLT64X);
+ DO_TEST1 (_Float128x, FLT128X);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-floath.h b/gcc/testsuite/gcc.dg/torture/floatn-floath.h
new file mode 100644
index 00000000000..a09b59e7551
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/floatn-floath.h
@@ -0,0 +1,52 @@
+/* Tests for _FloatN / _FloatNx types: compile and execution tests for
+ <float.h>. Before including this file, define WIDTH as the value
+ N; define EXT to 1 for _FloatNx and 0 for _FloatN. */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
+
+#if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define FMAC(M) CONCAT4 (FLT, WIDTH, X_, M)
+#else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define FMAC(M) CONCAT4 (FLT, WIDTH, _, M)
+#endif
+
+extern void exit (int);
+extern void abort (void);
+
+int
+main (void)
+{
+ volatile TYPE a = CST (1.0);
+ for (int i = 0; i >= FMAC (MIN_EXP); i--)
+ a *= CST (0.5);
+ if (a != FMAC (MIN))
+ abort ();
+ for (int i = 0; i < FMAC (MANT_DIG) - 1; i++)
+ a *= CST (0.5);
+ if (a != FMAC (TRUE_MIN))
+ abort ();
+ a *= CST (0.5);
+ if (a != CST (0.0))
+ abort ();
+ a = FMAC (EPSILON);
+ for (int i = 0; i < FMAC (MANT_DIG) - 1; i++)
+ a *= CST (2.0);
+ if (a != CST (1.0))
+ abort ();
+ a = FMAC (MAX);
+ for (int i = 0; i < FMAC (MAX_EXP); i++)
+ a *= CST (0.5);
+ if (a != CST (1.0) - FMAC (EPSILON) * CST (0.5))
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/floatn-tg.h b/gcc/testsuite/gcc.dg/torture/floatn-tg.h
new file mode 100644
index 00000000000..822229764ae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/floatn-tg.h
@@ -0,0 +1,113 @@
+/* Tests for _FloatN / _FloatNx types: compile and execution tests for
+ type-generic built-in functions. Before including this file,
+ define WIDTH as the value N; define EXT to 1 for _FloatNx and 0 for
+ _FloatN. */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define CONCAT4(W, X, Y, Z) CONCAT (CONCAT (CONCAT (W, X), Y), Z)
+
+#if EXT
+# define TYPE CONCAT3 (_Float, WIDTH, x)
+# define CST(C) CONCAT4 (C, f, WIDTH, x)
+# define TRUE_MIN CONCAT3 (FLT, WIDTH, X_TRUE_MIN)
+#else
+# define TYPE CONCAT (_Float, WIDTH)
+# define CST(C) CONCAT3 (C, f, WIDTH)
+# define TRUE_MIN CONCAT3 (FLT, WIDTH, _TRUE_MIN)
+#endif
+
+extern void exit (int);
+extern void abort (void);
+
+volatile TYPE inf = __builtin_inf (), nanval = __builtin_nan ("");
+volatile TYPE zero = CST (0.0), negzero = -CST (0.0), one = CST (1.0);
+volatile TYPE true_min = TRUE_MIN;
+
+int
+main (void)
+{
+ if (__builtin_signbit (inf) != 0)
+ abort ();
+ if (__builtin_signbit (zero) != 0)
+ abort ();
+ if (__builtin_signbit (negzero) == 0)
+ abort ();
+ if (__builtin_isfinite (nanval) != 0)
+ abort ();
+ if (__builtin_isfinite (inf) != 0)
+ abort ();
+ if (__builtin_isfinite (one) == 0)
+ abort ();
+ if (__builtin_isinf (nanval) != 0)
+ abort ();
+ if (__builtin_isinf (inf) == 0)
+ abort ();
+ if (__builtin_isnan (nanval) == 0)
+ abort ();
+ if (__builtin_isnan (inf) != 0)
+ abort ();
+ if (__builtin_isnormal (inf) != 0)
+ abort ();
+ if (__builtin_isnormal (one) == 0)
+ abort ();
+ if (__builtin_isnormal (nanval) != 0)
+ abort ();
+ if (__builtin_isnormal (zero) != 0)
+ abort ();
+ if (__builtin_isnormal (true_min) != 0)
+ abort ();
+ if (__builtin_islessequal (zero, one) != 1)
+ abort ();
+ if (__builtin_islessequal (one, zero) != 0)
+ abort ();
+ if (__builtin_islessequal (zero, negzero) != 1)
+ abort ();
+ if (__builtin_islessequal (zero, nanval) != 0)
+ abort ();
+ if (__builtin_isless (zero, one) != 1)
+ abort ();
+ if (__builtin_isless (one, zero) != 0)
+ abort ();
+ if (__builtin_isless (zero, negzero) != 0)
+ abort ();
+ if (__builtin_isless (zero, nanval) != 0)
+ abort ();
+ if (__builtin_isgreaterequal (zero, one) != 0)
+ abort ();
+ if (__builtin_isgreaterequal (one, zero) != 1)
+ abort ();
+ if (__builtin_isgreaterequal (zero, negzero) != 1)
+ abort ();
+ if (__builtin_isgreaterequal (zero, nanval) != 0)
+ abort ();
+ if (__builtin_isgreater (zero, one) != 0)
+ abort ();
+ if (__builtin_isgreater (one, zero) != 1)
+ abort ();
+ if (__builtin_isgreater (zero, negzero) != 0)
+ abort ();
+ if (__builtin_isgreater (zero, nanval) != 0)
+ abort ();
+ if (__builtin_islessgreater (zero, one) != 1)
+ abort ();
+ if (__builtin_islessgreater (one, zero) != 1)
+ abort ();
+ if (__builtin_islessgreater (zero, negzero) != 0)
+ abort ();
+ if (__builtin_islessgreater (zero, nanval) != 0)
+ abort ();
+ if (__builtin_isunordered (zero, one) != 0)
+ abort ();
+ if (__builtin_isunordered (one, zero) != 0)
+ abort ();
+ if (__builtin_isunordered (zero, negzero) != 0)
+ abort ();
+ if (__builtin_isunordered (zero, nanval) != 1)
+ abort ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c
index 39ec3cde110..f2446d7fd5a 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-double.c
@@ -9,10 +9,10 @@
int
main (void)
{
- TEST_I_F(signed char, unsigned char, double, DBL_MANT_DIG);
- TEST_I_F(signed short, unsigned short, double, DBL_MANT_DIG);
- TEST_I_F(signed int, unsigned int, double, DBL_MANT_DIG);
- TEST_I_F(signed long, unsigned long, double, DBL_MANT_DIG);
- TEST_I_F(signed long long, unsigned long long, double, DBL_MANT_DIG);
+ TEST_I_F(signed char, unsigned char, double, DBL_MANT_DIG, DBL_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, double, DBL_MANT_DIG, DBL_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, double, DBL_MANT_DIG, DBL_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, double, DBL_MANT_DIG, DBL_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, double, DBL_MANT_DIG, DBL_MAX_EXP);
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c
index 7fca1df7adf..f0f371bcbc1 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float.c
@@ -9,10 +9,10 @@
int
main (void)
{
- TEST_I_F(signed char, unsigned char, float, FLT_MANT_DIG);
- TEST_I_F(signed short, unsigned short, float, FLT_MANT_DIG);
- TEST_I_F(signed int, unsigned int, float, FLT_MANT_DIG);
- TEST_I_F(signed long, unsigned long, float, FLT_MANT_DIG);
- TEST_I_F(signed long long, unsigned long long, float, FLT_MANT_DIG);
+ TEST_I_F(signed char, unsigned char, float, FLT_MANT_DIG, FLT_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, float, FLT_MANT_DIG, FLT_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, float, FLT_MANT_DIG, FLT_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, float, FLT_MANT_DIG, FLT_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, float, FLT_MANT_DIG, FLT_MAX_EXP);
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee-timode.c
new file mode 100644
index 00000000000..59a7a8c07ca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee-timode.c
@@ -0,0 +1,16 @@
+/* Test floating-point conversions. _Float128 type with TImode. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(TItype, UTItype, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee.c
new file mode 100644
index 00000000000..e1aeab0581a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-ieee.c
@@ -0,0 +1,20 @@
+/* Test floating-point conversions. Standard types and _Float128. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128 } */
+/* { dg-require-effective-target float128_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(signed char, unsigned char, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, _Float128, FLT128_MANT_DIG, FLT128_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c
index 493dee892b0..ddeef869581 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128-timode.c
@@ -9,10 +9,11 @@
#include "fp-int-convert.h"
#define FLOAT128_MANT_DIG 113
+#define FLOAT128_MAX_EXP 16384
int
main (void)
{
- TEST_I_F(TItype, UTItype, __float128, FLOAT128_MANT_DIG);
+ TEST_I_F(TItype, UTItype, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP);
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c
index bc5e5adebc1..4adff79078d 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128.c
@@ -6,14 +6,15 @@
#include "fp-int-convert.h"
#define FLOAT128_MANT_DIG 113
+#define FLOAT128_MAX_EXP 16384
int
main (void)
{
- TEST_I_F(signed char, unsigned char, __float128, FLOAT128_MANT_DIG);
- TEST_I_F(signed short, unsigned short, __float128, FLOAT128_MANT_DIG);
- TEST_I_F(signed int, unsigned int, __float128, FLOAT128_MANT_DIG);
- TEST_I_F(signed long, unsigned long, __float128, FLOAT128_MANT_DIG);
- TEST_I_F(signed long long, unsigned long long, __float128, FLOAT128_MANT_DIG);
+ TEST_I_F(signed char, unsigned char, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, __float128, FLOAT128_MANT_DIG, FLOAT128_MAX_EXP);
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x-timode.c
new file mode 100644
index 00000000000..682dcdc82f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x-timode.c
@@ -0,0 +1,16 @@
+/* Test floating-point conversions. _Float128x type with TImode. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float128x_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(TItype, UTItype, _Float128, FLT128X_MANT_DIG, FLT128X_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x.c
new file mode 100644
index 00000000000..a09ed5d545e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float128x.c
@@ -0,0 +1,20 @@
+/* Test floating-point conversions. Standard types and _Float128x. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float128x } */
+/* { dg-require-effective-target float128x_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(signed char, unsigned char, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, _Float128x, FLT128X_MANT_DIG, FLT128X_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16-timode.c
new file mode 100644
index 00000000000..f64f1d2ed6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16-timode.c
@@ -0,0 +1,16 @@
+/* Test floating-point conversions. _Float16 type with TImode. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-require-effective-target float16_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(TItype, UTItype, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16.c
new file mode 100644
index 00000000000..92e976f6ac1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float16.c
@@ -0,0 +1,20 @@
+/* Test floating-point conversions. Standard types and _Float16. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float16 } */
+/* { dg-require-effective-target float16_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(signed char, unsigned char, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, _Float16, FLT16_MANT_DIG, FLT16_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32-timode.c
new file mode 100644
index 00000000000..c248497d7dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32-timode.c
@@ -0,0 +1,16 @@
+/* Test floating-point conversions. _Float32 type with TImode. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-require-effective-target float32_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(TItype, UTItype, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32.c
new file mode 100644
index 00000000000..09847d82a3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32.c
@@ -0,0 +1,20 @@
+/* Test floating-point conversions. Standard types and _Float32. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32 } */
+/* { dg-require-effective-target float32_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(signed char, unsigned char, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, _Float32, FLT32_MANT_DIG, FLT32_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x-timode.c
new file mode 100644
index 00000000000..f08bd0073b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x-timode.c
@@ -0,0 +1,16 @@
+/* Test floating-point conversions. _Float32x type with TImode. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32x_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(TItype, UTItype, _Float32, FLT32X_MANT_DIG, FLT32X_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x.c
new file mode 100644
index 00000000000..8ea2eafe2f3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float32x.c
@@ -0,0 +1,20 @@
+/* Test floating-point conversions. Standard types and _Float32x. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float32x } */
+/* { dg-require-effective-target float32x_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(signed char, unsigned char, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, _Float32x, FLT32X_MANT_DIG, FLT32X_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64-timode.c
new file mode 100644
index 00000000000..ecefa8120b8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64-timode.c
@@ -0,0 +1,16 @@
+/* Test floating-point conversions. _Float64 type with TImode. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64 } */
+/* { dg-require-effective-target float64_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(TItype, UTItype, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64.c
new file mode 100644
index 00000000000..196d611493f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64.c
@@ -0,0 +1,20 @@
+/* Test floating-point conversions. Standard types and _Float64. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64 } */
+/* { dg-require-effective-target float64_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(signed char, unsigned char, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, _Float64, FLT64_MANT_DIG, FLT64_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x-timode.c
new file mode 100644
index 00000000000..7b06a804226
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x-timode.c
@@ -0,0 +1,16 @@
+/* Test floating-point conversions. _Float64x type with TImode. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64x } */
+/* { dg-require-effective-target float64x_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(TItype, UTItype, _Float64, FLT64X_MANT_DIG, FLT64X_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x.c
new file mode 100644
index 00000000000..e103a5e6d0d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float64x.c
@@ -0,0 +1,20 @@
+/* Test floating-point conversions. Standard types and _Float64x. */
+/* { dg-do run } */
+/* { dg-options "" } */
+/* { dg-add-options float64x } */
+/* { dg-require-effective-target float64x_runtime } */
+
+#define __STDC_WANT_IEC_60559_TYPES_EXT__
+#include <float.h>
+#include "fp-int-convert.h"
+
+int
+main (void)
+{
+ TEST_I_F(signed char, unsigned char, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, _Float64x, FLT64X_MANT_DIG, FLT64X_MAX_EXP);
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c
index 7600994b4bd..9c94438b56e 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80-timode.c
@@ -7,10 +7,11 @@
#include "fp-int-convert.h"
#define FLOAT80_MANT_DIG 64
+#define FLOAT80_MAX_EXP 16384
int
main (void)
{
- TEST_I_F(TItype, UTItype, __float80, FLOAT80_MANT_DIG);
+ TEST_I_F(TItype, UTItype, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP);
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c
index 3e25f904dbe..e545613beed 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-float80.c
@@ -6,14 +6,15 @@
#include "fp-int-convert.h"
#define FLOAT80_MANT_DIG 64
+#define FLOAT80_MAX_EXP 16384
int
main (void)
{
- TEST_I_F(signed char, unsigned char, __float80, FLOAT80_MANT_DIG);
- TEST_I_F(signed short, unsigned short, __float80, FLOAT80_MANT_DIG);
- TEST_I_F(signed int, unsigned int, __float80, FLOAT80_MANT_DIG);
- TEST_I_F(signed long, unsigned long, __float80, FLOAT80_MANT_DIG);
- TEST_I_F(signed long long, unsigned long long, __float80, FLOAT80_MANT_DIG);
+ TEST_I_F(signed char, unsigned char, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, __float80, FLOAT80_MANT_DIG, FLOAT80_MAX_EXP);
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c
index bb189a34c32..d8e5197f1d3 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-long-double.c
@@ -9,10 +9,10 @@
int
main (void)
{
- TEST_I_F(signed char, unsigned char, long double, LDBL_MANT_DIG);
- TEST_I_F(signed short, unsigned short, long double, LDBL_MANT_DIG);
- TEST_I_F(signed int, unsigned int, long double, LDBL_MANT_DIG);
- TEST_I_F(signed long, unsigned long, long double, LDBL_MANT_DIG);
- TEST_I_F(signed long long, unsigned long long, long double, LDBL_MANT_DIG);
+ TEST_I_F(signed char, unsigned char, long double, LDBL_MANT_DIG, LDBL_MAX_EXP);
+ TEST_I_F(signed short, unsigned short, long double, LDBL_MANT_DIG, LDBL_MAX_EXP);
+ TEST_I_F(signed int, unsigned int, long double, LDBL_MANT_DIG, LDBL_MAX_EXP);
+ TEST_I_F(signed long, unsigned long, long double, LDBL_MANT_DIG, LDBL_MAX_EXP);
+ TEST_I_F(signed long long, unsigned long long, long double, LDBL_MANT_DIG, LDBL_MAX_EXP);
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c
index 3a60d01ffa5..0ef3e545465 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c
@@ -9,13 +9,13 @@
int
main (void)
{
- TEST_I_F(TItype, UTItype, float, FLT_MANT_DIG);
- TEST_I_F(TItype, UTItype, double, DBL_MANT_DIG);
+ TEST_I_F(TItype, UTItype, float, FLT_MANT_DIG, FLT_MAX_EXP);
+ TEST_I_F(TItype, UTItype, double, DBL_MANT_DIG, DBL_MAX_EXP);
/* Disable the long double tests when using IBM Extended Doubles.
They have variable precision, but constants calculated by gcc's
real.c assume fixed precision. */
#if DBL_MANT_DIG != LDBL_MANT_DIG && LDBL_MANT_DIG != 106
- TEST_I_F(TItype, UTItype, long double, LDBL_MANT_DIG);
+ TEST_I_F(TItype, UTItype, long double, LDBL_MANT_DIG, LDBL_MAX_EXP);
#endif
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert.h b/gcc/testsuite/gcc.dg/torture/fp-int-convert.h
index 8ac9c3de1ac..59773e34fa8 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert.h
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert.h
@@ -15,20 +15,21 @@ typedef long TItype;
typedef unsigned long UTItype;
#endif
-/* TEST_I_F(I, U, F, P) tests conversions between the pair of signed
- and unsigned integer types I and U and the floating-point type F,
- where P is the binary precision of the floating point type. We
- test conversions of the values 0, 1, 0x7...f, 0x8...0, 0xf...f. We
- also test conversions of values half way between two
- representable values (rounding both ways), just above half way, and
- just below half way. */
-#define TEST_I_F(I, U, F, P) \
+/* TEST_I_F(I, U, F, P, M) tests conversions between the pair of
+ signed and unsigned integer types I and U and the floating-point
+ type F, where P is the binary precision of the floating point type
+ and M is the MAX_EXP value for that type (so 2^M overflows, 2^(M-1)
+ does not). We test conversions of the values 0, 1, 0x7...f,
+ 0x8...0, 0xf...f. We also test conversions of values half way
+ between two representable values (rounding both ways), just above
+ half way, and just below half way. */
+#define TEST_I_F(I, U, F, P, M) \
do { \
TEST_I_F_VAL (I, F, (I)0, 1); \
TEST_I_F_VAL (I, F, (I)1, 1); \
TEST_I_F_VAL (I, F, (I)(((U)~(U)0) >> 1), P_OK1 (P, I)); \
- TEST_I_F_VAL (I, F, (I)(U)~(((U)~(U)0) >> 1), 1); \
- TEST_I_F_VAL (I, F, (I)(U)~(U)0, P_OK (P, I)); \
+ TEST_I_F_VAL (I, F, (I)(U)~(((U)~(U)0) >> 1), M_OK1 (M, I)); \
+ TEST_I_F_VAL (I, F, (I)(U)~(U)0, 1); \
TEST_I_F_VAL (I, F, HVAL0S (P, I), P_OK (P, I)); \
TEST_I_F_VAL (I, F, HVAL0S (P, I) + 1, P_OK (P, I)); \
TEST_I_F_VAL (I, F, HVAL0S (P, I) - 1, P_OK (P, I)); \
@@ -44,7 +45,7 @@ do { \
TEST_I_F_VAL (U, F, (U)0, 1); \
TEST_I_F_VAL (U, F, (U)1, 1); \
TEST_I_F_VAL (U, F, (U)(((U)~(U)0) >> 1), P_OK1 (P, U)); \
- TEST_I_F_VAL (U, F, (U)~(((U)~(U)0) >> 1), 1); \
+ TEST_I_F_VAL (U, F, (U)~(((U)~(U)0) >> 1), M_OK1 (M, U)); \
TEST_I_F_VAL (U, F, (U)~(U)0, P_OK (P, U)); \
TEST_I_F_VAL (U, F, HVAL0U (P, U), P_OK (P, U)); \
TEST_I_F_VAL (U, F, HVAL0U (P, U) + 1, P_OK (P, U)); \
@@ -56,6 +57,7 @@ do { \
#define P_OK(P, T) ((P) >= sizeof(T) * CHAR_BIT)
#define P_OK1(P, T) ((P) >= sizeof(T) * CHAR_BIT - 1)
+#define M_OK1(M, T) ((M) > sizeof(T) * CHAR_BIT - 1)
#define HVAL0U(P, U) (U)(P_OK (P, U) \
? (U)1 \
: (((U)1 << (sizeof(U) * CHAR_BIT - 1)) \
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index fc386b62f2a..b264686324a 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2433,6 +2433,135 @@ proc check_effective_target_has_q_floating_suffix { } {
} "$opts"]
}
+# Return 1 if the target supports the _FloatN / _FloatNx type
+# indicated in the function name, 0 otherwise.
+
+proc check_effective_target_float16 {} {
+ return [check_no_compiler_messages_nocache float16 object {
+ _Float16 x;
+ }]
+}
+
+proc check_effective_target_float32 {} {
+ return [check_no_compiler_messages_nocache float32 object {
+ _Float32 x;
+ }]
+}
+
+proc check_effective_target_float64 {} {
+ return [check_no_compiler_messages_nocache float64 object {
+ _Float64 x;
+ }]
+}
+
+proc check_effective_target_float128 {} {
+ return [check_no_compiler_messages_nocache float128 object {
+ _Float128 x;
+ }]
+}
+
+proc check_effective_target_float32x {} {
+ return [check_no_compiler_messages_nocache float32x object {
+ _Float32x x;
+ }]
+}
+
+proc check_effective_target_float64x {} {
+ return [check_no_compiler_messages_nocache float64x object {
+ _Float64x x;
+ }]
+}
+
+proc check_effective_target_float128x {} {
+ return [check_no_compiler_messages_nocache float128x object {
+ _Float128x x;
+ }]
+}
+
+# Likewise, but runtime support for any special options used as well
+# as compile-time support is required.
+
+proc check_effective_target_float16_runtime {} {
+ return [check_effective_target_float16]
+}
+
+proc check_effective_target_float32_runtime {} {
+ return [check_effective_target_float32]
+}
+
+proc check_effective_target_float64_runtime {} {
+ return [check_effective_target_float64]
+}
+
+proc check_effective_target_float128_runtime {} {
+ if { ![check_effective_target_float128] } {
+ return 0
+ }
+ if { [istarget powerpc*-*-*] } {
+ return [check_effective_target_base_quadfloat_support]
+ }
+ return 1
+}
+
+proc check_effective_target_float32x_runtime {} {
+ return [check_effective_target_float32x]
+}
+
+proc check_effective_target_float64x_runtime {} {
+ if { ![check_effective_target_float64x] } {
+ return 0
+ }
+ if { [istarget powerpc*-*-*] } {
+ return [check_effective_target_base_quadfloat_support]
+ }
+ return 1
+}
+
+proc check_effective_target_float128x_runtime {} {
+ return [check_effective_target_float128x]
+}
+
+# Return 1 if the target hardware supports any options added for
+# _FloatN and _FloatNx types, 0 otherwise.
+
+proc check_effective_target_floatn_nx_runtime {} {
+ if { [istarget powerpc*-*-*] } {
+ return [check_effective_target_base_quadfloat_support]
+ }
+ return 1
+}
+
+# Add options needed to use the _FloatN / _FloatNx type indicated in
+# the function name.
+
+proc add_options_for_float16 { flags } {
+ return "$flags"
+}
+
+proc add_options_for_float32 { flags } {
+ return "$flags"
+}
+
+proc add_options_for_float64 { flags } {
+ return "$flags"
+}
+
+proc add_options_for_float128 { flags } {
+ return [add_options_for___float128 "$flags"]
+}
+
+proc add_options_for_float32x { flags } {
+ return "$flags"
+}
+
+proc add_options_for_float64x { flags } {
+ return [add_options_for___float128 "$flags"]
+}
+
+proc add_options_for_float128x { flags } {
+ return "$flags"
+}
+
# Return 1 if the target supports __float128,
# 0 otherwise.
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 6e8595c3855..8b3e5cc75a4 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -558,10 +558,44 @@ enum tree_index {
TI_COMPLEX_DOUBLE_TYPE,
TI_COMPLEX_LONG_DOUBLE_TYPE,
+ TI_COMPLEX_FLOAT16_TYPE,
+ TI_COMPLEX_FLOATN_NX_TYPE_FIRST = TI_COMPLEX_FLOAT16_TYPE,
+ TI_COMPLEX_FLOAT32_TYPE,
+ TI_COMPLEX_FLOAT64_TYPE,
+ TI_COMPLEX_FLOAT128_TYPE,
+ TI_COMPLEX_FLOAT32X_TYPE,
+ TI_COMPLEX_FLOAT64X_TYPE,
+ TI_COMPLEX_FLOAT128X_TYPE,
+
TI_FLOAT_TYPE,
TI_DOUBLE_TYPE,
TI_LONG_DOUBLE_TYPE,
+ /* The _FloatN and _FloatNx types must be consecutive, and in the
+ same sequence as the corresponding complex types, which must also
+ be consecutive; _FloatN must come before _FloatNx; the order must
+ also be the same as in the floatn_nx_types array and the RID_*
+ values in c-common.h. This is so that iterations over these
+ types work as intended. */
+ TI_FLOAT16_TYPE,
+ TI_FLOATN_TYPE_FIRST = TI_FLOAT16_TYPE,
+ TI_FLOATN_NX_TYPE_FIRST = TI_FLOAT16_TYPE,
+ TI_FLOAT32_TYPE,
+ TI_FLOAT64_TYPE,
+ TI_FLOAT128_TYPE,
+ TI_FLOATN_TYPE_LAST = TI_FLOAT128_TYPE,
+#define NUM_FLOATN_TYPES (TI_FLOATN_TYPE_LAST - TI_FLOATN_TYPE_FIRST + 1)
+ TI_FLOAT32X_TYPE,
+ TI_FLOATNX_TYPE_FIRST = TI_FLOAT32X_TYPE,
+ TI_FLOAT64X_TYPE,
+ TI_FLOAT128X_TYPE,
+ TI_FLOATNX_TYPE_LAST = TI_FLOAT128X_TYPE,
+ TI_FLOATN_NX_TYPE_LAST = TI_FLOAT128X_TYPE,
+#define NUM_FLOATNX_TYPES (TI_FLOATNX_TYPE_LAST - TI_FLOATNX_TYPE_FIRST + 1)
+#define NUM_FLOATN_NX_TYPES (TI_FLOATN_NX_TYPE_LAST \
+ - TI_FLOATN_NX_TYPE_FIRST \
+ + 1)
+
TI_FLOAT_PTR_TYPE,
TI_DOUBLE_PTR_TYPE,
TI_LONG_DOUBLE_PTR_TYPE,
@@ -1959,6 +1993,16 @@ struct GTY(()) builtin_info_type {
unsigned declared_p : 1;
};
+/* Information about a _FloatN or _FloatNx type that may be
+ supported. */
+struct floatn_type_info {
+ /* The number N in the type name. */
+ int n;
+ /* Whether it is an extended type _FloatNx (true) or an interchange
+ type (false). */
+ bool extended;
+};
+
/*---------------------------------------------------------------------------
Global variables
@@ -2023,4 +2067,7 @@ extern GTY(()) tree current_function_decl;
/* Nonzero means a FUNC_BEGIN label was emitted. */
extern GTY(()) const char * current_function_func_begin_label;
+/* Information about the _FloatN and _FloatNx types. */
+extern const floatn_type_info floatn_nx_types[NUM_FLOATN_NX_TYPES];
+
#endif // GCC_TREE_CORE_H
diff --git a/gcc/tree.c b/gcc/tree.c
index 6efc30ce5c8..33e6f979b55 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10140,6 +10140,20 @@ build_atomic_base (tree type, unsigned int align)
return t;
}
+/* Information about the _FloatN and _FloatNx types. This must be in
+ the same order as the corresponding TI_* enum values. */
+const floatn_type_info floatn_nx_types[NUM_FLOATN_NX_TYPES] =
+ {
+ { 16, false },
+ { 32, false },
+ { 64, false },
+ { 128, false },
+ { 32, true },
+ { 64, true },
+ { 128, true },
+ };
+
+
/* Create nodes for all integer types (and error_mark_node) using the sizes
of C datatypes. SIGNED_CHAR specifies whether char is signed. */
@@ -10312,6 +10326,29 @@ build_common_tree_nodes (bool signed_char)
TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
layout_type (long_double_type_node);
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ {
+ int n = floatn_nx_types[i].n;
+ bool extended = floatn_nx_types[i].extended;
+ machine_mode mode = targetm.floatn_mode (n, extended);
+ if (mode == VOIDmode)
+ continue;
+ int precision = GET_MODE_PRECISION (mode);
+ /* Work around the rs6000 KFmode having precision 113 not
+ 128. */
+ const struct real_format *fmt = REAL_MODE_FORMAT (mode);
+ gcc_assert (fmt->b == 2 && fmt->emin + fmt->emax == 3);
+ int min_precision = fmt->p + ceil_log2 (fmt->emax - fmt->emin);
+ if (!extended)
+ gcc_assert (min_precision == n);
+ if (precision < min_precision)
+ precision = min_precision;
+ FLOATN_NX_TYPE_NODE (i) = make_node (REAL_TYPE);
+ TYPE_PRECISION (FLOATN_NX_TYPE_NODE (i)) = precision;
+ layout_type (FLOATN_NX_TYPE_NODE (i));
+ SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode);
+ }
+
float_ptr_type_node = build_pointer_type (float_type_node);
double_ptr_type_node = build_pointer_type (double_type_node);
long_double_ptr_type_node = build_pointer_type (long_double_type_node);
@@ -10346,6 +10383,13 @@ build_common_tree_nodes (bool signed_char)
complex_double_type_node = build_complex_type (double_type_node);
complex_long_double_type_node = build_complex_type (long_double_type_node);
+ for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+ {
+ if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
+ COMPLEX_FLOATN_NX_TYPE_NODE (i)
+ = build_complex_type (FLOATN_NX_TYPE_NODE (i));
+ }
+
/* Make fixed-point nodes based on sat/non-sat and signed/unsigned. */
#define MAKE_FIXED_TYPE_NODE(KIND,SIZE) \
sat_ ## KIND ## _type_node = \
diff --git a/gcc/tree.h b/gcc/tree.h
index fff65d6c809..16d13f3266b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3605,6 +3605,17 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
#define double_type_node global_trees[TI_DOUBLE_TYPE]
#define long_double_type_node global_trees[TI_LONG_DOUBLE_TYPE]
+/* Nodes for particular _FloatN and _FloatNx types in sequence. */
+#define FLOATN_TYPE_NODE(IDX) global_trees[TI_FLOATN_TYPE_FIRST + (IDX)]
+#define FLOATN_NX_TYPE_NODE(IDX) global_trees[TI_FLOATN_NX_TYPE_FIRST + (IDX)]
+#define FLOATNX_TYPE_NODE(IDX) global_trees[TI_FLOATNX_TYPE_FIRST + (IDX)]
+
+/* Names for individual types, where required by back ends
+ (architecture-independent code should always iterate over all such
+ types). */
+#define float128_type_node global_trees[TI_FLOAT128_TYPE]
+#define float64x_type_node global_trees[TI_FLOAT64X_TYPE]
+
#define float_ptr_type_node global_trees[TI_FLOAT_PTR_TYPE]
#define double_ptr_type_node global_trees[TI_DOUBLE_PTR_TYPE]
#define long_double_ptr_type_node global_trees[TI_LONG_DOUBLE_PTR_TYPE]
@@ -3615,6 +3626,8 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
#define complex_double_type_node global_trees[TI_COMPLEX_DOUBLE_TYPE]
#define complex_long_double_type_node global_trees[TI_COMPLEX_LONG_DOUBLE_TYPE]
+#define COMPLEX_FLOATN_NX_TYPE_NODE(IDX) global_trees[TI_COMPLEX_FLOATN_NX_TYPE_FIRST + (IDX)]
+
#define pointer_bounds_type_node global_trees[TI_POINTER_BOUNDS_TYPE]
#define void_type_node global_trees[TI_VOID_TYPE]
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index e8e43f7285b..f680f8bc899 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,12 @@
+2016-08-19 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/32187
+ * include/cpplib.h (CPP_N_FLOATN, CPP_N_FLOATNX)
+ (CPP_N_WIDTH_FLOATN_NX, CPP_FLOATN_SHIFT, CPP_FLOATN_MAX): New
+ macros.
+ * expr.c (interpret_float_suffix): Handle fN, fNx, FN and FNx
+ suffixes.
+
2016-08-19 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
* expr.c (eval_token): Append "evaluates to 0" to Wundef diagnostic.
diff --git a/libcpp/expr.c b/libcpp/expr.c
index d32f5a97189..61bc1b21af1 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -86,15 +86,52 @@ static cpp_num parse_has_include (cpp_reader *, enum include_type);
/* Subroutine of cpp_classify_number. S points to a float suffix of
length LEN, possibly zero. Returns 0 for an invalid suffix, or a
- flag vector describing the suffix. */
+ flag vector (of CPP_N_* bits) describing the suffix. */
static unsigned int
interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
{
size_t flags;
- size_t f, d, l, w, q, i;
+ size_t f, d, l, w, q, i, fn, fnx, fn_bits;
flags = 0;
- f = d = l = w = q = i = 0;
+ f = d = l = w = q = i = fn = fnx = fn_bits = 0;
+
+ /* The following decimal float suffixes, from TR 24732:2009 and TS
+ 18661-2:2015, are supported:
+
+ df, DF - _Decimal32.
+ dd, DD - _Decimal64.
+ dl, DL - _Decimal128.
+
+ The dN and DN suffixes for _DecimalN, and dNx and DNx for
+ _DecimalNx, defined in TS 18661-3:2015, are not supported.
+
+ Fixed-point suffixes, from TR 18037:2008, are supported. They
+ consist of three parts, in order:
+
+ (i) An optional u or U, for unsigned types.
+
+ (ii) An optional h or H, for short types, or l or L, for long
+ types, or ll or LL, for long long types. Use of ll or LL is a
+ GNU extension.
+
+ (iii) r or R, for _Fract types, or k or K, for _Accum types.
+
+ Otherwise the suffix is for a binary or standard floating-point
+ type. Such a suffix, or the absence of a suffix, may be preceded
+ or followed by i, I, j or J, to indicate an imaginary number with
+ the corresponding complex type. The following suffixes for
+ binary or standard floating-point types are supported:
+
+ f, F - float (ISO C and C++).
+ l, L - long double (ISO C and C++).
+ d, D - double, even with the FLOAT_CONST_DECIMAL64 pragma in
+ operation (from TR 24732:2009; the pragma and the suffix
+ are not included in TS 18661-2:2015).
+ w, W - machine-specific type such as __float80 (GNU extension).
+ q, Q - machine-specific type such as __float128 (GNU extension).
+ fN, FN - _FloatN (TS 18661-3:2015).
+ fNx, FNx - _FloatNx (TS 18661-3:2015). */
/* Process decimal float suffixes, which are two letters starting
with d or D. Order and case are significant. */
@@ -172,20 +209,64 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
/* In any remaining valid suffix, the case and order don't matter. */
while (len--)
- switch (s[len])
- {
- case 'f': case 'F': f++; break;
- case 'd': case 'D': d++; break;
- case 'l': case 'L': l++; break;
- case 'w': case 'W': w++; break;
- case 'q': case 'Q': q++; break;
- case 'i': case 'I':
- case 'j': case 'J': i++; break;
- default:
- return 0;
- }
+ {
+ switch (s[0])
+ {
+ case 'f': case 'F':
+ f++;
+ if (len > 0
+ && !CPP_OPTION (pfile, cplusplus)
+ && s[1] >= '1'
+ && s[1] <= '9'
+ && fn_bits == 0)
+ {
+ f--;
+ while (len > 0
+ && s[1] >= '0'
+ && s[1] <= '9'
+ && fn_bits < CPP_FLOATN_MAX)
+ {
+ fn_bits = fn_bits * 10 + (s[1] - '0');
+ len--;
+ s++;
+ }
+ if (len > 0 && s[1] == 'x')
+ {
+ fnx++;
+ len--;
+ s++;
+ }
+ else
+ fn++;
+ }
+ break;
+ case 'd': case 'D': d++; break;
+ case 'l': case 'L': l++; break;
+ case 'w': case 'W': w++; break;
+ case 'q': case 'Q': q++; break;
+ case 'i': case 'I':
+ case 'j': case 'J': i++; break;
+ default:
+ return 0;
+ }
+ s++;
+ }
- if (f + d + l + w + q > 1 || i > 1)
+ /* Reject any case of multiple suffixes specifying types, multiple
+ suffixes specifying an imaginary constant, _FloatN or _FloatNx
+ suffixes for invalid values of N, and _FloatN suffixes for values
+ of N larger than can be represented in the return value. The
+ caller is responsible for rejecting _FloatN suffixes where
+ _FloatN is not supported on the chosen target. */
+ if (f + d + l + w + q + fn + fnx > 1 || i > 1)
+ return 0;
+ if (fn_bits > CPP_FLOATN_MAX)
+ return 0;
+ if (fnx && fn_bits != 32 && fn_bits != 64 && fn_bits != 128)
+ return 0;
+ if (fn && fn_bits != 16 && fn_bits % 32 != 0)
+ return 0;
+ if (fn && fn_bits == 96)
return 0;
if (i && !CPP_OPTION (pfile, ext_numeric_literals))
@@ -199,7 +280,10 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
d ? CPP_N_MEDIUM :
l ? CPP_N_LARGE :
w ? CPP_N_MD_W :
- q ? CPP_N_MD_Q : CPP_N_DEFAULT));
+ q ? CPP_N_MD_Q :
+ fn ? CPP_N_FLOATN | (fn_bits << CPP_FLOATN_SHIFT) :
+ fnx ? CPP_N_FLOATNX | (fn_bits << CPP_FLOATN_SHIFT) :
+ CPP_N_DEFAULT));
}
/* Return the classification flags for a float suffix. */
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index a497811eec0..cfc6ccd1a90 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -956,9 +956,16 @@ struct cpp_num
#define CPP_N_FRACT 0x100000 /* Fract types. */
#define CPP_N_ACCUM 0x200000 /* Accum types. */
+#define CPP_N_FLOATN 0x400000 /* _FloatN types. */
+#define CPP_N_FLOATNX 0x800000 /* _FloatNx types. */
#define CPP_N_USERDEF 0x1000000 /* C++0x user-defined literal. */
+#define CPP_N_WIDTH_FLOATN_NX 0xF0000000 /* _FloatN / _FloatNx value
+ of N, divided by 16. */
+#define CPP_FLOATN_SHIFT 24
+#define CPP_FLOATN_MAX 0xF0
+
/* Classify a CPP_NUMBER token. The return value is a combination of
the flags from the above sets. */
extern unsigned cpp_classify_number (cpp_reader *, const cpp_token *,