Support excess precision for integer / floating-point comparisons (PR c/87390).
authorJoseph Myers <joseph@codesourcery.com>
Wed, 26 Sep 2018 21:14:16 +0000 (22:14 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Wed, 26 Sep 2018 21:14:16 +0000 (22:14 +0100)
In C11, implicit conversions from integer to floating-point types
produce results with the range and precision of the corresponding
evaluation format rather than only those of the type implicitly
converted to.  This patch implements that case of C11 excess precision
semantics in the case of a comparison between integer and
floating-point types, previously missed when implementing other cases
of excess precision for such implicit conversions.  As with other such
fixes, this patch conservatively follows the reading of C99 where
conversions from integer to floating-point do not produce results with
excess precision and so the change is made for C11 mode only.

Bootstrapped with no regressions on x86_64-pc-linux-gnu.

gcc/c:
PR c/87390
* c-typeck.c (build_binary_op): Use excess precision for
comparisons of integers and floating-point for C11 and later.

gcc/testsuite:
PR c/87390
* gcc.target/i386/excess-precision-9.c,
gcc.target/i386/excess-precision-10.c: New tests.

From-SVN: r264656

gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/excess-precision-10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/excess-precision-9.c [new file with mode: 0644]

index 1ea87b95a52375b660e8de3fe5c67f6825c56d5b..a8e235c9f9b553d8a7553534295e75e952a6bef2 100644 (file)
@@ -1,3 +1,9 @@
+2018-09-26  Joseph Myers  <joseph@codesourcery.com>
+
+       PR c/87390
+       * c-typeck.c (build_binary_op): Use excess precision for
+       comparisons of integers and floating-point for C11 and later.
+
 2018-09-26  Martin Jambor  <mjambor@suse.cz>
 
        PR c/87347
index a5a7da0084c72793e71b072dd0a0919decd852bc..9d09b8d65fd1d07d5bbeb8fa3fa5ec33b29b251f 100644 (file)
@@ -11249,6 +11249,20 @@ build_binary_op (location_t location, enum tree_code code,
     case EXACT_DIV_EXPR:
       may_need_excess_precision = true;
       break;
+
+    case EQ_EXPR:
+    case NE_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+      /* Excess precision for implicit conversions of integers to
+        floating point in C11 and later.  */
+      may_need_excess_precision = (flag_isoc11
+                                  && (ANY_INTEGRAL_TYPE_P (type0)
+                                      || ANY_INTEGRAL_TYPE_P (type1)));
+      break;
+
     default:
       may_need_excess_precision = false;
       break;
index aa005e71441722601bd4618bfe094ddd49afef9d..16407e5244c7984f725f52b3dfc11a4925d382e9 100644 (file)
@@ -1,3 +1,9 @@
+2018-09-26  Joseph Myers  <joseph@codesourcery.com>
+
+       PR c/87390
+       * gcc.target/i386/excess-precision-9.c,
+       gcc.target/i386/excess-precision-10.c: New tests.
+
 2018-09-26  Richard Biener  <rguenther@suse.de>
 
        PR debug/87443
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-10.c b/gcc/testsuite/gcc.target/i386/excess-precision-10.c
new file mode 100644 (file)
index 0000000..f1b9b7e
--- /dev/null
@@ -0,0 +1,52 @@
+/* Excess precision tests.  Test implicit conversions in comparisons:
+   excess precision in C11 mode.  */
+/* { 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 = 0x1p63f;
+  unsigned long long int u = (1ULL << 63) + 1;
+
+  if ((f == u) != 0)
+    abort ();
+
+  if ((u == f) != 0)
+    abort ();
+
+  if ((f != u) != 1)
+    abort ();
+
+  if ((u != f) != 1)
+    abort ();
+
+  if ((f < u) != 1)
+    abort ();
+
+  if ((u < f) != 0)
+    abort ();
+
+  if ((f <= u) != 1)
+    abort ();
+
+  if ((u <= f) != 0)
+    abort ();
+
+  if ((f > u) != 0)
+    abort ();
+
+  if ((u > f) != 1)
+    abort ();
+
+  if ((f >= u) != 0)
+    abort ();
+
+  if ((u >= f) != 1)
+    abort ();
+
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/excess-precision-9.c b/gcc/testsuite/gcc.target/i386/excess-precision-9.c
new file mode 100644 (file)
index 0000000..61e5fc1
--- /dev/null
@@ -0,0 +1,52 @@
+/* Excess precision tests.  Test implicit conversions in comparisons:
+   no excess precision in C99 mode.  */
+/* { dg-do run } */
+/* { dg-options "-std=c99 -mfpmath=387 -fexcess-precision=standard" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+  float f = 0x1p63f;
+  unsigned long long int u = (1ULL << 63) + 1;
+
+  if ((f == u) != 1)
+    abort ();
+
+  if ((u == f) != 1)
+    abort ();
+
+  if ((f != u) != 0)
+    abort ();
+
+  if ((u != f) != 0)
+    abort ();
+
+  if ((f < u) != 0)
+    abort ();
+
+  if ((u < f) != 0)
+    abort ();
+
+  if ((f <= u) != 1)
+    abort ();
+
+  if ((u <= f) != 1)
+    abort ();
+
+  if ((f > u) != 0)
+    abort ();
+
+  if ((u > f) != 0)
+    abort ();
+
+  if ((f >= u) != 1)
+    abort ();
+
+  if ((u >= f) != 1)
+    abort ();
+
+  exit (0);
+}