re PR fortran/47359 (Recursive functions of intrinsic names generates invalid assembler)
authorThomas Koenig <tkoenig@netcologne.de>
Sat, 6 Jun 2015 16:12:39 +0000 (16:12 +0000)
committerThomas Koenig <tkoenig@gcc.gnu.org>
Sat, 6 Jun 2015 16:12:39 +0000 (16:12 +0000)
2015-06-06  Thomas Koenig  <tkoenig@netcologne.de>

PR fortran/47359
* arith.c (eval_intrinsic_op): Set warn flag for
gfc_type_convert_binary if -Wconversion or -Wconversion-extra
are set.
(wprecision_real_real): New function.
(wprecision_int_real): New function.
(gfc_int2int): If -fno-range-check and -Wconversion are specified
and it is a narrowing conversion, warn.
(gfc_int2real): If there is a change in value for the conversion,
warn.
(gfc_int2complex):  Likewise.
(gfc_real2int): If there is a fractional part to the real number,
warn with -Wconversion, otherwise warn with -Wconversion-extra.
(gfc_real2real): Emit warning if the constant was changed by
conversion with either -Wconversion or -Wconversion-extra.  With
-Wconversion-extra, warn if no warning was issued earlier.
(gfc_real2complex):  Likewise.
(gfc_complex2int): For -Wconversion or -Wconversion-extra, if
there was an imaginary part, warn; otherwise, warn for change in
value.  Warn with -Wconversion-extra if no other warning was
issued.
(gfc_complex2real): For -Wconversion or -Wconversion-extra, if
there was an imaginary part, warn; otherwise, warn for change in
value. Warn with -Wconversion-extra if no other warning was
issued.
(gfc_complex2complex):  For -Wconversion, warn if the value of
either the real or the imaginary part was changed.  Warn for
-Wconversion-extra if no prior warning was issued.
* expr.c (gfc_check_assign):  Remove check for change in value.
* primary.c (match_real_constant): For -Wconversion-extra, check
against a number in which the last non-zero digit has been
replaced with a zero.  If the number compares equal, warn.
* intrinsic.c (gfc_convert_type_warn):  Do not warn about constant
conversions.

2015-06-06  Thomas Koenig  <tkoenig@netcologne.de>

PR fortran/47359
* gfortran.dg/array_constructor_type_17.f03: Adjust error message.
* gfortran.dg/warn_conversion.f90: Add warning for change in value
for assignment.
* gfortran.dg/warn_conversion_3.f90: Add warnings.
* gfortran.dg/warn_conversion_5.f90: New test.
* gfortran.dg/warn_conversion_6.f90: New test.
* gfortran.dg/warn_conversion_7.f90: New test.

From-SVN: r224190

12 files changed:
gcc/fortran/ChangeLog
gcc/fortran/arith.c
gcc/fortran/expr.c
gcc/fortran/intrinsic.c
gcc/fortran/primary.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/array_constructor_type_17.f03
gcc/testsuite/gfortran.dg/warn_conversion.f90
gcc/testsuite/gfortran.dg/warn_conversion_3.f90
gcc/testsuite/gfortran.dg/warn_conversion_5.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/warn_conversion_6.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/warn_conversion_7.f90 [new file with mode: 0644]

index 6b5a1e57862754c4abfe7b71989ee8dbb5631eea..e32595b66cbcada1941b1e5a1b05e597ef8f3e63 100644 (file)
@@ -1,3 +1,40 @@
+2015-06-06  Thomas Koenig  <tkoenig@netcologne.de>
+
+       PR fortran/47359
+       * arith.c (eval_intrinsic_op): Set warn flag for
+       gfc_type_convert_binary if -Wconversion or -Wconversion-extra
+       are set.
+       (wprecision_real_real): New function.
+       (wprecision_int_real): New function.
+       (gfc_int2int): If -fno-range-check and -Wconversion are specified
+       and it is a narrowing conversion, warn.
+       (gfc_int2real): If there is a change in value for the conversion,
+       warn.
+       (gfc_int2complex):  Likewise.
+       (gfc_real2int): If there is a fractional part to the real number,
+       warn with -Wconversion, otherwise warn with -Wconversion-extra.
+       (gfc_real2real): Emit warning if the constant was changed by
+       conversion with either -Wconversion or -Wconversion-extra.  With
+       -Wconversion-extra, warn if no warning was issued earlier.
+       (gfc_real2complex):  Likewise.
+       (gfc_complex2int): For -Wconversion or -Wconversion-extra, if
+       there was an imaginary part, warn; otherwise, warn for change in
+       value.  Warn with -Wconversion-extra if no other warning was
+       issued.
+       (gfc_complex2real): For -Wconversion or -Wconversion-extra, if
+       there was an imaginary part, warn; otherwise, warn for change in
+       value. Warn with -Wconversion-extra if no other warning was
+       issued.
+       (gfc_complex2complex):  For -Wconversion, warn if the value of
+       either the real or the imaginary part was changed.  Warn for
+       -Wconversion-extra if no prior warning was issued.
+       * expr.c (gfc_check_assign):  Remove check for change in value.
+       * primary.c (match_real_constant): For -Wconversion-extra, check
+       against a number in which the last non-zero digit has been
+       replaced with a zero.  If the number compares equal, warn.
+       * intrinsic.c (gfc_convert_type_warn):  Do not warn about constant
+       conversions.
+
 2015-06-05  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/66347
index b9c25c10e8915a36192a9b616cd38014bcab44e1..d51fbc26be48fe75051df422c2fc9fba700ebca8 100644 (file)
@@ -1521,7 +1521,7 @@ eval_intrinsic (gfc_intrinsic_op op,
       temp.value.op.op1 = op1;
       temp.value.op.op2 = op2;
 
-      gfc_type_convert_binary (&temp, 0);
+      gfc_type_convert_binary (&temp, warn_conversion || warn_conversion_extra);
 
       if (op == INTRINSIC_EQ || op == INTRINSIC_NE
          || op == INTRINSIC_GE || op == INTRINSIC_GT
@@ -1949,6 +1949,42 @@ arith_error (arith rc, gfc_typespec *from, gfc_typespec *to, locus *where)
      NaN, etc.  */
 }
 
+/* Returns true if significant bits were lost when converting real
+   constant r from from_kind to to_kind.  */
+
+static bool
+wprecision_real_real (mpfr_t r, int from_kind, int to_kind)
+{
+  mpfr_t rv, diff;
+  bool ret;
+
+  gfc_set_model_kind (to_kind);
+  mpfr_init (rv);
+  gfc_set_model_kind (from_kind);
+  mpfr_init (diff);
+
+  mpfr_set (rv, r, GFC_RND_MODE);
+  mpfr_sub (diff, rv, r, GFC_RND_MODE);
+
+  ret = ! mpfr_zero_p (diff);
+  mpfr_clear (rv);
+  mpfr_clear (diff);
+  return ret;
+}
+
+/* Return true if conversion from an integer to a real loses precision.  */
+
+static bool
+wprecision_int_real (mpz_t n, mpfr_t r)
+{
+  mpz_t i;
+  mpz_init (i);
+  mpfr_get_z (i, r, GFC_RND_MODE);
+  mpz_sub (i, i, n);
+  return mpz_cmp_si (i, 0) != 0;
+  mpz_clear (i);
+
+}
 
 /* Convert integers to integers.  */
 
@@ -1985,8 +2021,12 @@ gfc_int2int (gfc_expr *src, int kind)
       k = gfc_validate_kind (BT_INTEGER, kind, false);
       gfc_convert_mpz_to_signed (result->value.integer,
                                 gfc_integer_kinds[k].bit_size);
-    }
 
+      if (warn_conversion && kind < src->ts.kind)
+       gfc_warning_now (OPT_Wconversion, "Conversion from %qs to %qs at %L",
+                        gfc_typename (&src->ts), gfc_typename (&result->ts),
+                        &src->where);
+    }
   return result;
 }
 
@@ -2010,6 +2050,14 @@ gfc_int2real (gfc_expr *src, int kind)
       return NULL;
     }
 
+  if (warn_conversion
+      && wprecision_int_real (src->value.integer, result->value.real))
+    gfc_warning_now (OPT_Wconversion, "Change of value in conversion "
+                    "from %qs to %qs at %L",
+                    gfc_typename (&src->ts),
+                    gfc_typename (&result->ts),
+                    &src->where);
+
   return result;
 }
 
@@ -2034,6 +2082,15 @@ gfc_int2complex (gfc_expr *src, int kind)
       return NULL;
     }
 
+  if (warn_conversion
+      && wprecision_int_real (src->value.integer,
+                             mpc_realref (result->value.complex)))
+      gfc_warning_now (OPT_Wconversion, "Change of value in conversion "
+                      "from %qs to %qs at %L",
+                      gfc_typename (&src->ts),
+                      gfc_typename (&result->ts),
+                      &src->where);
+
   return result;
 }
 
@@ -2045,6 +2102,7 @@ gfc_real2int (gfc_expr *src, int kind)
 {
   gfc_expr *result;
   arith rc;
+  bool did_warn = false;
 
   result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
 
@@ -2057,6 +2115,28 @@ gfc_real2int (gfc_expr *src, int kind)
       return NULL;
     }
 
+  /* If there was a fractional part, warn about this.  */
+
+  if (warn_conversion)
+    {
+      mpfr_t f;
+      mpfr_init (f);
+      mpfr_frac (f, src->value.real, GFC_RND_MODE);
+      if (mpfr_cmp_si (f, 0) != 0)
+       {
+         gfc_warning_now (OPT_Wconversion, "Change of value in conversion "
+                          "from %qs to %qs at %L", gfc_typename (&src->ts),
+                          gfc_typename (&result->ts), &src->where);
+         did_warn = true;
+       }
+    }
+  if (!did_warn && warn_conversion_extra)
+    {
+      gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
+                      "at %L", gfc_typename (&src->ts),
+                      gfc_typename (&result->ts), &src->where);
+    }
+
   return result;
 }
 
@@ -2068,6 +2148,7 @@ gfc_real2real (gfc_expr *src, int kind)
 {
   gfc_expr *result;
   arith rc;
+  bool did_warn = false;
 
   result = gfc_get_constant_expr (BT_REAL, kind, &src->where);
 
@@ -2088,6 +2169,33 @@ gfc_real2real (gfc_expr *src, int kind)
       return NULL;
     }
 
+  /* As a special bonus, don't warn about REAL values which are not changed by
+     the conversion if -Wconversion is specified and -Wconversion-extra is
+     not.  */
+
+  if ((warn_conversion || warn_conversion_extra) && src->ts.kind > kind)
+    {
+      int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
+      
+      /* Calculate the difference between the constant and the rounded
+        value and check it against zero.  */
+
+      if (wprecision_real_real (src->value.real, src->ts.kind, kind))
+       {
+         gfc_warning_now (w, "Change of value in conversion from "
+                          "%qs to %qs at %L",
+                          gfc_typename (&src->ts), gfc_typename (&result->ts),
+                          &src->where);
+         /* Make sure the conversion warning is not emitted again.  */
+         did_warn = true;
+       }
+    }
+
+    if (!did_warn && warn_conversion_extra)
+      gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
+                      "at %L", gfc_typename(&src->ts),
+                      gfc_typename(&result->ts), &src->where);
+
   return result;
 }
 
@@ -2099,6 +2207,7 @@ gfc_real2complex (gfc_expr *src, int kind)
 {
   gfc_expr *result;
   arith rc;
+  bool did_warn = false;
 
   result = gfc_get_constant_expr (BT_COMPLEX, kind, &src->where);
 
@@ -2119,6 +2228,26 @@ gfc_real2complex (gfc_expr *src, int kind)
       return NULL;
     }
 
+  if ((warn_conversion || warn_conversion_extra) && src->ts.kind > kind)
+    {
+      int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
+
+      if (wprecision_real_real (src->value.real, src->ts.kind, kind))
+       {
+         gfc_warning_now (w, "Change of value in conversion from "
+                          "%qs to %qs at %L",
+                          gfc_typename (&src->ts), gfc_typename (&result->ts),
+                          &src->where);
+         /* Make sure the conversion warning is not emitted again.  */
+         did_warn = true;
+       }
+    }
+
+  if (!did_warn && warn_conversion_extra)
+    gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
+                    "at %L", gfc_typename(&src->ts),
+                    gfc_typename(&result->ts), &src->where);
+
   return result;
 }
 
@@ -2130,6 +2259,7 @@ gfc_complex2int (gfc_expr *src, int kind)
 {
   gfc_expr *result;
   arith rc;
+  bool did_warn = false;
 
   result = gfc_get_constant_expr (BT_INTEGER, kind, &src->where);
 
@@ -2143,6 +2273,43 @@ gfc_complex2int (gfc_expr *src, int kind)
       return NULL;
     }
 
+  if (warn_conversion || warn_conversion_extra)
+    {
+      int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
+
+      /* See if we discarded an imaginary part.  */
+      if (mpfr_cmp_si (mpc_imagref (src->value.complex), 0) != 0)
+       {
+         gfc_warning_now (w, "Non-zero imaginary part discarded "
+                          "in conversion from %qs to %qs at %L",
+                          gfc_typename(&src->ts), gfc_typename (&result->ts),
+                          &src->where);
+         did_warn = true;
+       }
+
+      else {
+       mpfr_t f;
+
+       mpfr_init (f);
+       mpfr_frac (f, src->value.real, GFC_RND_MODE);
+       if (mpfr_cmp_si (f, 0) != 0)
+         {
+           gfc_warning_now (w, "Change of value in conversion from "
+                            "%qs to %qs at %L", gfc_typename (&src->ts),
+                            gfc_typename (&result->ts), &src->where);
+           did_warn = true;
+         }
+       mpfr_clear (f);
+      }
+
+      if (!did_warn && warn_conversion_extra)
+       {
+         gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
+                          "at %L", gfc_typename (&src->ts),
+                          gfc_typename (&result->ts), &src->where);
+       }
+    }
+
   return result;
 }
 
@@ -2154,6 +2321,7 @@ gfc_complex2real (gfc_expr *src, int kind)
 {
   gfc_expr *result;
   arith rc;
+  bool did_warn = false;
 
   result = gfc_get_constant_expr (BT_REAL, kind, &src->where);
 
@@ -2174,6 +2342,41 @@ gfc_complex2real (gfc_expr *src, int kind)
       return NULL;
     }
 
+  if (warn_conversion || warn_conversion_extra)
+    {
+      int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
+
+      /* See if we discarded an imaginary part.  */
+      if (mpfr_cmp_si (mpc_imagref (src->value.complex), 0) != 0)
+       {
+         gfc_warning_now (w, "Non-zero imaginary part discarded "
+                          "in conversion from %qs to %qs at %L",
+                          gfc_typename(&src->ts), gfc_typename (&result->ts),
+                          &src->where);
+         did_warn = true;
+       }
+
+      /* Calculate the difference between the real constant and the rounded
+        value and check it against zero.  */
+      
+      if (kind > src->ts.kind
+         && wprecision_real_real (mpc_realref (src->value.complex),
+                                  src->ts.kind, kind))
+       {
+         gfc_warning_now (w, "Change of value in conversion from "
+                          "%qs to %qs at %L",
+                          gfc_typename (&src->ts), gfc_typename (&result->ts),
+                          &src->where);
+         /* Make sure the conversion warning is not emitted again.  */
+         did_warn = true;
+       }
+    }
+
+  if (!did_warn && warn_conversion_extra)
+    gfc_warning_now (OPT_Wconversion, "Conversion from %qs to %qs at %L",
+                    gfc_typename(&src->ts), gfc_typename (&result->ts),
+                    &src->where);
+
   return result;
 }
 
@@ -2185,6 +2388,7 @@ gfc_complex2complex (gfc_expr *src, int kind)
 {
   gfc_expr *result;
   arith rc;
+  bool did_warn = false;
 
   result = gfc_get_constant_expr (BT_COMPLEX, kind, &src->where);
 
@@ -2220,6 +2424,26 @@ gfc_complex2complex (gfc_expr *src, int kind)
       return NULL;
     }
 
+  if ((warn_conversion || warn_conversion_extra) && src->ts.kind > kind
+      && (wprecision_real_real (mpc_realref (src->value.complex),
+                               src->ts.kind, kind)
+         || wprecision_real_real (mpc_imagref (src->value.complex),
+                                  src->ts.kind, kind)))
+    {
+      int w = warn_conversion ? OPT_Wconversion : OPT_Wconversion_extra;
+
+      gfc_warning_now (w, "Change of value in conversion from "
+                      " %qs to %qs at %L",
+                      gfc_typename (&src->ts), gfc_typename (&result->ts),
+                      &src->where);
+      did_warn = true;
+    }
+
+  if (!did_warn && warn_conversion_extra && src->ts.kind != kind)
+    gfc_warning_now (OPT_Wconversion_extra, "Conversion from %qs to %qs "
+                    "at %L", gfc_typename(&src->ts),
+                    gfc_typename (&result->ts), &src->where);
+
   return result;
 }
 
index b569e0ccb4cd3d24e370cfd46b44d95407729f0e..d7a90c442444b0ad5443bf77ce734bf8caec14cc 100644 (file)
@@ -3247,55 +3247,6 @@ gfc_check_assign (gfc_expr *lvalue, gfc_expr *rvalue, int conform)
        }
     }
 
-  /*  Warn about type-changing conversions for REAL or COMPLEX constants.
-      If lvalue and rvalue are mixed REAL and complex, gfc_compare_types
-      will warn anyway, so there is no need to to so here.  */
-
-  if (rvalue->expr_type == EXPR_CONSTANT && lvalue->ts.type == rvalue->ts.type
-      && (lvalue->ts.type == BT_REAL || lvalue->ts.type == BT_COMPLEX))
-    {
-      if (lvalue->ts.kind < rvalue->ts.kind && warn_conversion)
-       {
-         /* As a special bonus, don't warn about REAL rvalues which are not
-            changed by the conversion if -Wconversion is specified.  */
-         if (rvalue->ts.type == BT_REAL && mpfr_number_p (rvalue->value.real))
-           {
-             /* Calculate the difference between the constant and the rounded
-                value and check it against zero.  */
-             mpfr_t rv, diff;
-             gfc_set_model_kind (lvalue->ts.kind);
-             mpfr_init (rv);
-             gfc_set_model_kind (rvalue->ts.kind);
-             mpfr_init (diff);
-
-             mpfr_set (rv, rvalue->value.real, GFC_RND_MODE);
-             mpfr_sub (diff, rv, rvalue->value.real, GFC_RND_MODE);
-
-             if (!mpfr_zero_p (diff))
-               gfc_warning (OPT_Wconversion, 
-                            "Change of value in conversion from "
-                            " %qs to %qs at %L", gfc_typename (&rvalue->ts),
-                            gfc_typename (&lvalue->ts), &rvalue->where);
-
-             mpfr_clear (rv);
-             mpfr_clear (diff);
-           }
-         else
-           gfc_warning (OPT_Wconversion,
-                        "Possible change of value in conversion from %qs "
-                        "to %qs at %L", gfc_typename (&rvalue->ts),
-                        gfc_typename (&lvalue->ts), &rvalue->where);
-
-       }
-      else if (warn_conversion_extra && lvalue->ts.kind > rvalue->ts.kind)
-       {
-         gfc_warning (OPT_Wconversion_extra,
-                      "Conversion from %qs to %qs at %L",
-                      gfc_typename (&rvalue->ts),
-                      gfc_typename (&lvalue->ts), &rvalue->where);
-       }
-    }
-
   if (gfc_compare_types (&lvalue->ts, &rvalue->ts))
     return true;
 
index 1c0c388c5121e234d930257796f4856f5213f662..5666bfff9a26e063fb2701e6c10eeeee86ec78ca 100644 (file)
@@ -4695,15 +4695,18 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
          /* Larger kinds can hold values of smaller kinds without problems.
             Hence, only warn if target kind is smaller than the source
             kind - or if -Wconversion-extra is specified.  */
-         if (warn_conversion && from_ts.kind > ts->kind)
-           gfc_warning_now (OPT_Wconversion, "Possible change of value in "
-                            "conversion from %s to %s at %L",
-                            gfc_typename (&from_ts), gfc_typename (ts),
-                            &expr->where);
-         else if (warn_conversion_extra)
-           gfc_warning_now (OPT_Wconversion_extra, "Conversion from %s to %s "
-                            "at %L", gfc_typename (&from_ts),
-                            gfc_typename (ts), &expr->where);
+         if (expr->expr_type != EXPR_CONSTANT)
+           {
+             if (warn_conversion && from_ts.kind > ts->kind)
+               gfc_warning_now (OPT_Wconversion, "Possible change of value in "
+                                "conversion from %s to %s at %L",
+                                gfc_typename (&from_ts), gfc_typename (ts),
+                                &expr->where);
+             else if (warn_conversion_extra)
+               gfc_warning_now (OPT_Wconversion_extra, "Conversion from %s to %s "
+                                "at %L", gfc_typename (&from_ts),
+                                gfc_typename (ts), &expr->where);
+           }
        }
       else if ((from_ts.type == BT_REAL && ts->type == BT_INTEGER)
               || (from_ts.type == BT_COMPLEX && ts->type == BT_INTEGER)
@@ -4711,7 +4714,7 @@ gfc_convert_type_warn (gfc_expr *expr, gfc_typespec *ts, int eflag, int wflag)
        {
          /* Conversion from REAL/COMPLEX to INTEGER or COMPLEX to REAL
             usually comes with a loss of information, regardless of kinds.  */
-         if (warn_conversion)
+         if (warn_conversion && expr->expr_type != EXPR_CONSTANT)
            gfc_warning_now (OPT_Wconversion, "Possible change of value in "
                             "conversion from %s to %s at %L",
                             gfc_typename (&from_ts), gfc_typename (ts),
index 7d2f9c768fe3f91a2697020962a2ac99b7d1473f..e467e0b3ff0f1ae050bfa008a4ac5bf811ead248 100644 (file)
@@ -736,6 +736,58 @@ done:
       gfc_internal_error ("gfc_range_check() returned bad value");
     }
 
+  /* Warn about trailing digits which suggest the user added too many
+     trailing digits, which may cause the appearance of higher pecision
+     than the kind kan support.
+
+     This is done by replacing the rightmost non-zero digit with zero
+     and comparing with the original value.  If these are equal, we
+     assume the user supplied more digits than intended (or forgot to
+     convert to the correct kind).
+  */
+
+  if (warn_conversion_extra)
+    {
+      mpfr_t r;
+      char *c, *p;
+      bool did_break;
+
+      c = strchr (buffer, 'e');
+      if (c == NULL)
+       c = buffer + strlen(buffer);
+
+      did_break = false;
+      for (p = c - 1; p >= buffer; p--)
+       {
+         if (*p == '.')
+           continue;
+         
+         if (*p != '0')
+           {
+             *p = '0';
+             did_break = true;
+             break;
+           }
+       }
+
+      if (did_break)
+       {
+         mpfr_init (r);
+         mpfr_set_str (r, buffer, 10, GFC_RND_MODE);
+         if (negate)
+           mpfr_neg (r, r, GFC_RND_MODE);
+
+         mpfr_sub (r, r, e->value.real, GFC_RND_MODE);
+
+         if (mpfr_cmp_ui (r, 0) == 0)
+           gfc_warning (OPT_Wconversion_extra, "Non-significant digits "
+                        "in %qs number at %C, maybe incorrect KIND",
+                        gfc_typename (&e->ts));
+
+         mpfr_clear (r);
+       }
+    }
+
   *result = e;
   return MATCH_YES;
 
index dde4c8c0cfd9cdcd13f7a15e947a6ba491d6657f..057ddb9aa70acd0768b4b8252d4a9b11b829d7a3 100644 (file)
@@ -1,3 +1,14 @@
+2015-06-06  Thomas Koenig  <tkoenig@netcologne.de>
+
+       PR fortran/47359
+       * gfortran.dg/array_constructor_type_17.f03: Adjust error message.
+       * gfortran.dg/warn_conversion.f90: Add warning for change in value
+       for assignment.
+       * gfortran.dg/warn_conversion_3.f90: Add warnings.
+       * gfortran.dg/warn_conversion_5.f90: New test.
+       * gfortran.dg/warn_conversion_6.f90: New test.
+       * gfortran.dg/warn_conversion_7.f90: New test.
+
 2015-06-05  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/66347
index f8f15f9eba133e9d8482a9cefdcd4001fa50e15d..6e009e12547b6e1de2f3e16ce0c49b1838c2e1fc 100644 (file)
@@ -8,5 +8,5 @@ PROGRAM test
   IMPLICIT NONE
 
   INTEGER(KIND=4) :: arr(1)
-  arr = (/ INTEGER(KIND=4) :: HUGE(0_8) /) ! { dg-warning "conversion from" }
+  arr = (/ INTEGER(KIND=4) :: HUGE(0_8) /) ! { dg-warning "Conversion" }
 END PROGRAM test
index e9b7e396e4f098398b3751d7340f118709334418..5bc96cc69d294511f7605d1acdc2f0563fe5a7da 100644 (file)
@@ -18,7 +18,7 @@ SUBROUTINE pr27866c4
   integer(kind=4) :: i4
   i4 = 2.3              ! { dg-warning "conversion" }
   i1 = 500              ! { dg-error "overflow" }
-  a = 2**26-1           ! assignment INTEGER(4) to REAL(4) - no warning
+  a = 2**26-1           ! { dg-warning "Change of value in conversion" }
   b = 1d999             ! { dg-error "overflow" }
 
   a = i4                ! assignment INTEGER(4) to REAL(4) - no warning
index 38d701851cc8d29c1a9bdf7b5cd5b93424f15764..c50c03291664fde586be73128bf14069e0587bb0 100644 (file)
@@ -7,8 +7,8 @@ program main
   complex(8), parameter :: z = cmplx (0.5, 0.5)  ! { dg-warning "Conversion" }
   real :: r1, r2
   r1 = 2.3d0 ! { dg-warning "Change of value in conversion" }
-  r2 = 2.5d0 ! No warning because the value does not change
+  r2 = 2.5d0 ! { dg-warning "Conversion" }
   d1 = .13 ! { dg-warning "Conversion" }
   d2 = .13d0
-  d1 = z     ! { dg-warning "change of value in conversion" }
+  d1 = z     ! { dg-warning "Non-zero imaginary part" }
 end program main
diff --git a/gcc/testsuite/gfortran.dg/warn_conversion_5.f90 b/gcc/testsuite/gfortran.dg/warn_conversion_5.f90
new file mode 100644 (file)
index 0000000..f5e7c4e
--- /dev/null
@@ -0,0 +1,37 @@
+! { dg-do compile }
+! { dg-options "-Wconversion" }
+! PR 47359 - additional warnings for conversions.
+program main
+  implicit none
+  complex(kind=4) :: c4
+  complex(kind=8) :: c8
+  real(kind=4) :: r4
+  real(kind=8) :: r8
+  complex(kind=4), parameter :: c4p = (1.0, -4.)
+  complex, parameter :: c8w = (1.0_8, -4.2_8) ! { dg-warning "Change of value in conversion" }
+  complex (kind=8), parameter :: c8p = (1.0_8, -4.2_8)
+  integer :: i
+
+  c4 = c8p ! { dg-warning "Change of value in conversion" }
+  c4 = 2**26 + 1 ! { dg-warning "Change of value in conversion" }
+  c4 = 1.3d0     ! { dg-warning "Change of value in conversion" }
+  c4 = c8p       ! { dg-warning "Change of value in conversion" }
+  c4 = (1.2, 1000000001) ! { dg-warning "Change of value in conversion" }
+  r4 = (2**26 + 1) * 2.3 ! { dg-warning "Change of value in conversion" }
+  r4 = 2.4d0 ! { dg-warning "Change of value" }
+  r4 = c4p ! { dg-warning "Non-zero imaginary part" }
+  r4 = r4 + 2.3d0 ! { dg-warning "Possible change of value in conversion" }
+  r8 = 2_8**62 - 1_8 ! { dg-warning "Change of value in conversion" }
+  i = c4p ! { dg-warning "Non-zero imaginary part" }
+  i = 42 + 1.3 ! { dg-warning "Change of value in conversion" }
+  i = (1.2, 0.) ! { dg-warning "Change of value in conversion" }
+  c4 = 1.2       ! no warning
+  c4 = -3.25d0   ! no warning
+  c4 = -42       ! no warning
+  c8 = 2**26 + 1 ! no warning
+  i = 22.        ! no warning
+  i = (35., 0.)  ! no warning
+  r4 = 2.5d0     ! no warning
+  r4 = 235       ! no warning
+  r8 = 2.3       ! no warning
+end program main
diff --git a/gcc/testsuite/gfortran.dg/warn_conversion_6.f90 b/gcc/testsuite/gfortran.dg/warn_conversion_6.f90
new file mode 100644 (file)
index 0000000..e16a62e
--- /dev/null
@@ -0,0 +1,21 @@
+! { dg-do compile }
+! { dg-options "-Wconversion -Wconversion-extra" }
+! PR 47359 - additional warnings for conversions.
+program main
+  implicit none
+  real(kind=8) :: a,b
+  complex(kind=8) :: c
+  integer :: i
+  real(kind=4) :: r
+  a = 0.13              ! { dg-warning "Conversion" }
+  print *,0.1_8 ** 0.2  ! { dg-warning "Conversion" }
+  b = a/0.13            ! { dg-warning "Conversion" }
+  i = 12345.            ! { dg-warning "Conversion" }
+  i = (1., 23.)         ! { dg-warning "Non-zero imaginary part" }
+  r = (1., 23.)         ! { dg-warning "Non-zero imaginary part" }
+  b = 0.&                 ! { dg-warning "Possible change of value" }
+       &5_8*c             ! { dg-warning "Conversion" }
+  c = 0.3               ! { dg-warning "Conversion" }
+  a = 0.5               ! { dg-warning "Conversion" }
+end program main
+  
diff --git a/gcc/testsuite/gfortran.dg/warn_conversion_7.f90 b/gcc/testsuite/gfortran.dg/warn_conversion_7.f90
new file mode 100644 (file)
index 0000000..88f5bf1
--- /dev/null
@@ -0,0 +1,7 @@
+! { dg-do compile }
+! { dg-options "-Wconversion-extra -Wconversion" }
+program main
+  implicit none
+  double precision, parameter :: pi = &  ! { dg-warning "Conversion" }
+       & 3.1415829535897932     ! { dg-warning "Non-significant digits" }
+end program main