From: Joseph Myers Date: Fri, 15 Sep 2017 20:49:02 +0000 (+0100) Subject: Implement C11 excess precision semantics for conversions (PR c/82071). X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bb75facd248a5030b5acd533ba4092e2d7fcd90b;p=gcc.git Implement C11 excess precision semantics for conversions (PR c/82071). C11 semantics for excess precision (from N1531) are that an implicit conversion (from the usual arithmetic conversions, not by assignment) from integer to floating point has a result in the corresponding evaluation format of that floating-point type, so possibly with excess precision (whereas a cast or conversion by assignment from integer to floating point must produce a value without excess range or precision, as always). This patch makes GCC support those semantics if flag_isoc11 (which in turn means that conditional expressions need to support generating a result with excess precision even if neither operand had excess precision). C99 is less than entirely clear in this regard, but my reading as outlined at is that the results of conversions from integer to floating-point types are always expected to be representable in the target type without excess precision, and this patch conservatively keeps these semantics for pre-C11 (i.e. if an older standard is explicitly selected). Bootstrapped with no regressions on x86_64-pc-linux-gnu. PR c/82071 gcc/c: * c-typeck.c (ep_convert_and_check): Just call convert_and_check for C11. (build_conditional_expr): For C11, generate result with excess precision when one argument is an integer and the other is of a type using excess precision. gcc/testsuite: * gcc.target/i386/excess-precision-8.c: New test. From-SVN: r252847 --- diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index e8e0fb087d3..742867a6ad9 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,12 @@ +2017-09-15 Joseph Myers + + PR c/82071 + * c-typeck.c (ep_convert_and_check): Just call convert_and_check + for C11. + (build_conditional_expr): For C11, generate result with excess + precision when one argument is an integer and the other is of a + type using excess precision. + 2017-09-15 Bernd Edlinger * c-typeck.c (build_c_cast): Implement -Wcast-align=strict. diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 1956d45e251..73e74602f59 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -4866,7 +4866,9 @@ ep_convert_and_check (location_t loc, tree type, tree expr, if (TREE_TYPE (expr) == type) return expr; - if (!semantic_type) + /* For C11, integer conversions may have results with excess + precision. */ + if (flag_isoc11 || !semantic_type) return convert_and_check (loc, type, expr); if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE @@ -4994,7 +4996,31 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, && (code2 == INTEGER_TYPE || code2 == REAL_TYPE || code2 == COMPLEX_TYPE)) { - result_type = c_common_type (type1, type2); + /* In C11, a conditional expression between a floating-point + type and an integer type should convert the integer type to + the evaluation format of the floating-point type, with + possible excess precision. */ + tree eptype1 = type1; + tree eptype2 = type2; + if (flag_isoc11) + { + tree eptype; + if (ANY_INTEGRAL_TYPE_P (type1) + && (eptype = excess_precision_type (type2)) != NULL_TREE) + { + eptype2 = eptype; + if (!semantic_result_type) + semantic_result_type = c_common_type (type1, type2); + } + else if (ANY_INTEGRAL_TYPE_P (type2) + && (eptype = excess_precision_type (type1)) != NULL_TREE) + { + eptype1 = eptype; + if (!semantic_result_type) + semantic_result_type = c_common_type (type1, type2); + } + } + result_type = c_common_type (eptype1, eptype2); if (result_type == error_mark_node) return error_mark_node; do_warn_double_promotion (result_type, type1, type2, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 574251590f9..b9bb9c62a8e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-09-15 Joseph Myers + + PR c/82071 + * gcc.target/i386/excess-precision-8.c: New test. + 2017-09-15 Manuel Lopez-Ibanez Paolo Carlini diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-8.c b/gcc/testsuite/gcc.target/i386/excess-precision-8.c new file mode 100644 index 00000000000..c0a31ed5f4e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/excess-precision-8.c @@ -0,0 +1,61 @@ +/* Excess precision tests. Test C11 semantics for conversions from + integers to floating point: no excess precision for either explicit + conversions, but excess precision for implicit conversions. */ +/* { dg-do run } */ +/* { dg-options "-std=c11 -mfpmath=387 -fexcess-precision=standard" } */ + +extern void abort (void); +extern void exit (int); + +int +main (void) +{ + float f = 1.0f; + int i; + + i = 0x10001234; + if ((float) i != 0x10001240) + abort (); + + i = 0x10001234; + i += f; + if (i != 0x10001235) + abort (); + + i = 0x10001234; + i += 1.0f; + if (i != 0x10001235) + abort (); + + i = 0x10001234; + i = i + f; + if (i != 0x10001235) + abort (); + + i = 0x10001234; + i = i + 1.0f; + if (i != 0x10001235) + abort (); + + i = 0x10001235; + i = (1 ? i : 1.0f); + if (i != 0x10001235) + abort (); + + i = 0x10001235; + i = (1 ? i : f); + if (i != 0x10001235) + abort (); + + i = 0x10001235; + i = (0 ? 1.0f :i); + if (i != 0x10001235) + abort (); + + i = 0x10001235; + i = (0 ? f : i); + if (i != 0x10001235) + abort (); + + exit (0); +}