PR 23572 warnings for out of range floating-point constants

Manuel López-Ibáñez lopezibanez@gmail.com
Thu Mar 22 00:16:00 GMT 2007


On 20/03/07, Richard Henderson <rth@redhat.com> wrote:
>
> Your subsequent suggestion to use "truncated to zero" is good.
>
> > Are you suggesting that we emit a warning from the string parser? Do
> > we do this  for any other cases? I can give it a try.
>
> No, I suggest that the string parser return an indication of whether
> it underflowed.  Node that, currently, the underflow label is used
> for both underflow and true zeros.
>

You want it. You have it. :-)

:ADDPATCH C:

See http://gcc.gnu.org/ml/gcc-patches/2007-03/msg00943.html for more details.

Another difference is that I use REAL_VALUES_EQUAL rather than
REAL_VALUES_IDENTICAL.

The testcases are still a bit weak. I am not sure how to check that the
target supports or doesn't support infinities. Do we have a
'check_effective_target_support_inf' ? How can I add one?

Bootstrapped and regression tested.

Cheers,

Manuel.

2007-03-14  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

 PR other/23572
 * c-lex.c (interpret_float): On overflow, emit pedantic warning if
infinities not supported, otherwise emit warning if -Woverflow. On
underflow, emit warning if -Woverflow.
 * real.c (real_from_string): Return -1 if underflow, +1 if overflow
and 0 otherwise.
 * real.h (real_from_string): Update declaration.

testsuite/
 * gcc.dg/float-range-4.c: New.
 * gcc.dg/float-range-1.c: Update. Test for a warning.
 * gcc.dg/float-range-3.c: New.
 * gcc.dg/float-range-5.c: New.
-------------- next part --------------
Index: gcc/c-lex.c
===================================================================
--- gcc/c-lex.c	(revision 122985)
+++ gcc/c-lex.c	(working copy)
@@ -679,15 +679,27 @@ interpret_float (const cpp_token *token,
 
   real_from_string3 (&real, copy, TYPE_MODE (type));
 
   /* Both C and C++ require a diagnostic for a floating constant
      outside the range of representable values of its type.  Since we
-     have __builtin_inf* to produce an infinity, it might now be
-     appropriate for this to be a mandatory pedwarn rather than
-     conditioned on -pedantic.  */
-  if (REAL_VALUE_ISINF (real) && pedantic)
-    pedwarn ("floating constant exceeds range of %qT", type);
+     have __builtin_inf* to produce an infinity, this is now a
+     mandatory pedwarn if the target does not support infinities.  */
+  if (REAL_VALUE_ISINF (real)) 
+    {
+      if (!MODE_HAS_INFINITIES (TYPE_MODE (type)))
+	pedwarn ("floating constant exceeds range of %qT", type);
+      else
+	warning (OPT_Woverflow, "floating constant exceeds range of %qT", type);
+    }
+  /* We also give a warning if the value underflows.  */
+  else if (REAL_VALUES_EQUAL (real, dconst0))
+    {
+      REAL_VALUE_TYPE realvoidmode;
+      int overflow = real_from_string (&realvoidmode, copy);
+      if (overflow < 0 || !REAL_VALUES_EQUAL (realvoidmode, dconst0)) 
+	warning (OPT_Woverflow, "floating constant truncated to zero");
+    }
 
   /* Create a node with determined type and value.  */
   value = build_real (type, real);
   if (flags & CPP_N_IMAGINARY)
     value = build_complex (NULL_TREE, convert (type, integer_zero_node), value);
Index: gcc/real.c
===================================================================
--- gcc/real.c	(revision 122985)
+++ gcc/real.c	(working copy)
@@ -1789,13 +1789,14 @@ real_to_hexadecimal (char *str, const RE
 
   sprintf (p, "p%+d", exp);
 }
 
 /* Initialize R from a decimal or hexadecimal string.  The string is
-   assumed to have been syntax checked already.  */
+   assumed to have been syntax checked already.  Return -1 if the
+   value underflows, +1 if overflows, and 0 otherwise. */
 
-void
+int
 real_from_string (REAL_VALUE_TYPE *r, const char *str)
 {
   int exp = 0;
   bool sign = false;
 
@@ -1863,11 +1864,11 @@ real_from_string (REAL_VALUE_TYPE *r, co
 	    }
 	}
 
       /* If the mantissa is zero, ignore the exponent.  */
       if (!cmp_significand_0 (r))
-	goto underflow;
+	goto is_a_zero;
 
       if (*str == 'p' || *str == 'P')
 	{
 	  bool exp_neg = false;
 
@@ -1939,11 +1940,11 @@ real_from_string (REAL_VALUE_TYPE *r, co
 	    }
 	}
 
       /* If the mantissa is zero, ignore the exponent.  */
       if (r->cl == rvc_zero)
-	goto underflow;
+	goto is_a_zero;
 
       if (*str == 'e' || *str == 'E')
 	{
 	  bool exp_neg = false;
 
@@ -1979,19 +1980,23 @@ real_from_string (REAL_VALUE_TYPE *r, co
       if (exp)
 	times_pten (r, exp);
     }
 
   r->sign = sign;
-  return;
+  return 0;
+
+ is_a_zero:
+  get_zero (r, sign);
+  return 0;
 
  underflow:
   get_zero (r, sign);
-  return;
+  return -1;
 
  overflow:
   get_inf (r, sign);
-  return;
+  return 1;
 }
 
 /* Legacy.  Similar, but return the result directly.  */
 
 REAL_VALUE_TYPE
Index: gcc/real.h
===================================================================
--- gcc/real.h	(revision 122985)
+++ gcc/real.h	(working copy)
@@ -222,12 +222,13 @@ extern void real_to_hexadecimal (char *,
 /* Render R as an integer.  */
 extern HOST_WIDE_INT real_to_integer (const REAL_VALUE_TYPE *);
 extern void real_to_integer2 (HOST_WIDE_INT *, HOST_WIDE_INT *,
 			      const REAL_VALUE_TYPE *);
 
-/* Initialize R from a decimal or hexadecimal string.  */
-extern void real_from_string (REAL_VALUE_TYPE *, const char *);
+/* Initialize R from a decimal or hexadecimal string.  Return -1 if
+   the value underflows, +1 if overflows, and 0 otherwise.  */
+extern int real_from_string (REAL_VALUE_TYPE *, const char *);
 /* Wrapper to allow different internal representation for decimal floats. */
 extern void real_from_string3 (REAL_VALUE_TYPE *, const char *, enum machine_mode);
 
 /* Initialize R from an integer pair HIGH/LOW.  */
 extern void real_from_integer (REAL_VALUE_TYPE *, enum machine_mode,
Index: gcc/testsuite/gcc.dg/float-range-4.c
===================================================================
--- gcc/testsuite/gcc.dg/float-range-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/float-range-4.c	(revision 0)
@@ -0,0 +1,38 @@
+/* PR 23572 : warnings for out of range floating-point constants.  */
+/* { dg-compile } */
+/* { dg-options "-Wno-overflow -std=c99" } */
+#include <math.h>
+
+void overflow(void)
+{
+  float f1 = 3.5E+38f;  
+  float f2 = -3.5E+38f; 
+  float f3 = FP_INFINITE;
+  float f4 = -FP_INFINITE;
+
+  double d1 = 1.9E+308; 
+  double d2 = -1.9E+308;
+  double d3 = FP_INFINITE;
+  double d4 = -FP_INFINITE;
+}
+
+void underflow(void)
+{
+  float f11 = 3.3E-10000000000000000000f;
+  float f22 = -3.3E-10000000000000000000f;
+  float f1 = 3.3E-46f;  
+  float f2 = -3.3E-46f; 
+  float f3 = 0;
+  float f4 = -0;
+  float f5 = 0.0;
+  float f6 = -0.0;
+
+  double d11 = 3.3E-10000000000000000000;
+  double d22 = -3.3E-10000000000000000000;
+  double d1 = 1.4E-325; 
+  double d2 = -1.4E-325;
+  double d3 = 0;
+  double d4 = -0;
+  double d5 = 0.0;
+  double d6 = -0.0;
+}
Index: gcc/testsuite/gcc.dg/float-range-1.c
===================================================================
--- gcc/testsuite/gcc.dg/float-range-1.c	(revision 122985)
+++ gcc/testsuite/gcc.dg/float-range-1.c	(working copy)
@@ -1,13 +1,14 @@
 /* Floating constants outside the range of their type should receive a
-   pedwarn, not a warning.  */
+   just a warning if the target supports infinities. Otherwise, a
+   pedwarn should be produced.  */
 /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
 /* { dg-do compile } */
-/* { dg-options "-ansi -pedantic-errors" } */
+/* { dg-options "-ansi -pedantic-errors -Woverflow" } */
 
 void
 f (void)
 {
-  float a = 1e+100000000f; /* { dg-error "error: floating constant exceeds range of 'float'" } */
-  double b = 1e+100000000; /* { dg-error "error: floating constant exceeds range of 'double'" } */
-  long double c = 1e+100000000l; /* { dg-error "error: floating constant exceeds range of 'long double'" } */
+  float a = 1e+100000000f; /* { dg-warning "warning: floating constant exceeds range of 'float'" "" } */
+  double b = 1e+100000000; /* { dg-warning "warning: floating constant exceeds range of 'double'" } */
+  long double c = 1e+100000000l; /* { dg-warning "warning: floating constant exceeds range of 'long double'" } */
 }
Index: gcc/testsuite/gcc.dg/float-range-3.c
===================================================================
--- gcc/testsuite/gcc.dg/float-range-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/float-range-3.c	(revision 0)
@@ -0,0 +1,38 @@
+/* PR 23572 : warnings for out of range floating-point constants.  */
+/* { dg-compile } */
+/* { dg-options "-std=c99" } */
+#include <math.h>
+
+void overflow(void)
+{
+  float f1 = 3.5E+38f;  /* { dg-warning "warning: floating constant exceeds range" } */
+  float f2 = -3.5E+38f; /* { dg-warning "warning: floating constant exceeds range" } */
+  float f3 = FP_INFINITE;
+  float f4 = -FP_INFINITE;
+
+  double d1 = 1.9E+308;  /* { dg-warning "warning: floating constant exceeds range" } */
+  double d2 = -1.9E+308; /* { dg-warning "warning: floating constant exceeds range" } */
+  double d3 = FP_INFINITE;
+  double d4 = -FP_INFINITE;
+}
+
+void underflow(void)
+{
+  float f11 = 3.3E-10000000000000000000f;  /* { dg-warning "warning: floating constant truncated to zero" } */
+  float f22 = -3.3E-10000000000000000000f; /* { dg-warning "warning: floating constant truncated to zero" } */
+  float f1 = 3.3E-46f;  /* { dg-warning "warning: floating constant truncated to zero" } */
+  float f2 = -3.3E-46f; /* { dg-warning "warning: floating constant truncated to zero" } */
+  float f3 = 0;
+  float f4 = -0;
+  float f5 = 0.0;
+  float f6 = -0.0;
+
+  double d11 = 3.3E-10000000000000000000;  /* { dg-warning "warning: floating constant truncated to zero" } */
+  double d22 = -3.3E-10000000000000000000; /* { dg-warning "warning: floating constant truncated to zero" } */
+  double d1 = 1.4E-325;  /* { dg-warning "warning: floating constant truncated to zero" } */
+  double d2 = -1.4E-325; /* { dg-warning "warning: floating constant truncated to zero" } */
+  double d3 = 0;
+  double d4 = -0;
+  double d5 = 0.0;
+  double d6 = -0.0;
+}
Index: gcc/testsuite/gcc.dg/float-range-5.c
===================================================================
--- gcc/testsuite/gcc.dg/float-range-5.c	(revision 0)
+++ gcc/testsuite/gcc.dg/float-range-5.c	(revision 0)
@@ -0,0 +1,39 @@
+/* PR 23572 : warnings for out of range floating-point constants 
+   Test that they are NOT pedantic warnings.  */
+/* { dg-compile } */
+/* { dg-options "-pedantic-errors -std=c99" } */
+#include <math.h>
+
+void overflow(void)
+{
+  float f1 = 3.5E+38f;  /* { dg-warning "warning: floating constant exceeds range" } */
+  float f2 = -3.5E+38f; /* { dg-warning "warning: floating constant exceeds range" } */
+  float f3 = FP_INFINITE;
+  float f4 = -FP_INFINITE;
+
+  double d1 = 1.9E+308;  /* { dg-warning "warning: floating constant exceeds range" } */
+  double d2 = -1.9E+308; /* { dg-warning "warning: floating constant exceeds range" } */
+  double d3 = FP_INFINITE;
+  double d4 = -FP_INFINITE;
+}
+
+void underflow(void)
+{
+  float f11 = 3.3E-10000000000000000000f;  /* { dg-warning "warning: floating constant truncated to zero" } */
+  float f22 = -3.3E-10000000000000000000f; /* { dg-warning "warning: floating constant truncated to zero" } */
+  float f1 = 3.3E-46f;  /* { dg-warning "warning: floating constant truncated to zero" } */
+  float f2 = -3.3E-46f; /* { dg-warning "warning: floating constant truncated to zero" } */
+  float f3 = 0;
+  float f4 = -0;
+  float f5 = 0.0;
+  float f6 = -0.0;
+
+  double d11 = 3.3E-10000000000000000000;  /* { dg-warning "warning: floating constant truncated to zero" } */
+  double d22 = -3.3E-10000000000000000000; /* { dg-warning "warning: floating constant truncated to zero" } */
+  double d1 = 1.4E-325;  /* { dg-warning "warning: floating constant truncated to zero" } */
+  double d2 = -1.4E-325; /* { dg-warning "warning: floating constant truncated to zero" } */
+  double d3 = 0;
+  double d4 = -0;
+  double d5 = 0.0;
+  double d6 = -0.0;
+}


More information about the Gcc-patches mailing list