summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/c-lex.c22
-rw-r--r--gcc/real.c19
-rw-r--r--gcc/real.h5
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.dg/float-range-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/float-range-3.c38
-rw-r--r--gcc/testsuite/gcc.dg/float-range-4.c38
-rw-r--r--gcc/testsuite/gcc.dg/float-range-5.c39
9 files changed, 171 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 576cba8122c..0ce3c385cf7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2007-03-22 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
+
2007-03-22 Kai Tietz <kai.tietz@onevision.com>
Richard Henderson <rth@redhat.com>
diff --git a/gcc/c-lex.c b/gcc/c-lex.c
index 108bc5cff17..a89643c6046 100644
--- a/gcc/c-lex.c
+++ b/gcc/c-lex.c
@@ -681,11 +681,23 @@ interpret_float (const cpp_token *token, unsigned int flags)
/* 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);
diff --git a/gcc/real.c b/gcc/real.c
index b966917ae8f..2e288187b77 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -1791,9 +1791,10 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
}
/* 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;
@@ -1865,7 +1866,7 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
/* If the mantissa is zero, ignore the exponent. */
if (!cmp_significand_0 (r))
- goto underflow;
+ goto is_a_zero;
if (*str == 'p' || *str == 'P')
{
@@ -1941,7 +1942,7 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
/* If the mantissa is zero, ignore the exponent. */
if (r->cl == rvc_zero)
- goto underflow;
+ goto is_a_zero;
if (*str == 'e' || *str == 'E')
{
@@ -1981,15 +1982,19 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
}
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. */
diff --git a/gcc/real.h b/gcc/real.h
index fda1095b1bc..eab53d7dadf 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -224,8 +224,9 @@ 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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 936cebc8237..a5f2623e291 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2007-03-22 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
+ PR other/23572
+ * 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.
+
2007-03-22 Francois-Xavier Coudert <coudert@clipper.ens.fr>
PR fortran/31262
diff --git a/gcc/testsuite/gcc.dg/float-range-1.c b/gcc/testsuite/gcc.dg/float-range-1.c
index e14e345aba3..386d75dccd4 100644
--- a/gcc/testsuite/gcc.dg/float-range-1.c
+++ b/gcc/testsuite/gcc.dg/float-range-1.c
@@ -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'" } */
}
diff --git a/gcc/testsuite/gcc.dg/float-range-3.c b/gcc/testsuite/gcc.dg/float-range-3.c
new file mode 100644
index 00000000000..c737d8a9724
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float-range-3.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/float-range-4.c b/gcc/testsuite/gcc.dg/float-range-4.c
new file mode 100644
index 00000000000..5607719ac99
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float-range-4.c
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.dg/float-range-5.c b/gcc/testsuite/gcc.dg/float-range-5.c
new file mode 100644
index 00000000000..a19bd5fa3ad
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/float-range-5.c
@@ -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;
+}