re PR c/48956 (-Wconversion should warn when a complex value is assigned to a real...
authorMikhail Maltsev <maltsevm@gmail.com>
Fri, 15 May 2015 18:02:50 +0000 (18:02 +0000)
committerMikhail Maltsev <miyuki@gcc.gnu.org>
Fri, 15 May 2015 18:02:50 +0000 (18:02 +0000)
PR c/48956

gcc/c-family/
* c-common.c (int_safely_convertible_to_real_p): Define.
(unsafe_conversion_p): Check conversions involving complex types.
(conversion_warning): Add new warning message for conversions which
discard imaginary component.
* c-common.h: (enum conversion_safety): Add new enumerator for such
conversions.

gcc/testsuite/
* gcc.dg/Wconversion-complex-c99.c: New test.
* gcc.dg/Wconversion-complex-gnu.c: New test.

From-SVN: r223223

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wconversion-complex-c99.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wconversion-complex-gnu.c [new file with mode: 0644]

index 48d483e..199ba43 100644 (file)
@@ -1,3 +1,13 @@
+2015-05-15  Mikhail Maltsev  <maltsevm@gmail.com>
+
+       PR c/48956
+       * c-common.c (int_safely_convertible_to_real_p): Define.
+       (unsafe_conversion_p): Check conversions involving complex types.
+       (conversion_warning): Add new warning message for conversions which
+       discard imaginary component.
+       * c-common.h: (enum conversion_safety): Add new enumerator for such
+       conversions.
+
 2015-05-14  Marek Polacek  <polacek@redhat.com>
 
        PR c/66066
index 31c4c0d..8c7fdd2 100644 (file)
@@ -2707,17 +2707,42 @@ shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
   return result_type;
 }
 
-/* Checks if expression EXPR of real/integer type cannot be converted
-   to the real/integer type TYPE. Function returns non-zero when:
+/* Returns true iff any integer value of type FROM_TYPE can be represented as
+   real of type TO_TYPE.  This is a helper function for unsafe_conversion_p.  */
+
+static bool
+int_safely_convertible_to_real_p (const_tree from_type, const_tree to_type)
+{
+  tree type_low_bound = TYPE_MIN_VALUE (from_type);
+  tree type_high_bound = TYPE_MAX_VALUE (from_type);
+  REAL_VALUE_TYPE real_low_bound =
+         real_value_from_int_cst (0, type_low_bound);
+  REAL_VALUE_TYPE real_high_bound =
+         real_value_from_int_cst (0, type_high_bound);
+
+  return exact_real_truncate (TYPE_MODE (to_type), &real_low_bound)
+        && exact_real_truncate (TYPE_MODE (to_type), &real_high_bound);
+}
+
+/* Checks if expression EXPR of complex/real/integer type cannot be converted
+   to the complex/real/integer type TYPE.  Function returns non-zero when:
        * EXPR is a constant which cannot be exactly converted to TYPE.
        * EXPR is not a constant and size of EXPR's type > than size of TYPE,
-         for EXPR type and TYPE being both integers or both real.
+         for EXPR type and TYPE being both integers or both real, or both
+         complex.
+       * EXPR is not a constant of complex type and TYPE is a real or
+         an integer.
        * EXPR is not a constant of real type and TYPE is an integer.
        * EXPR is not a constant of integer type which cannot be
          exactly converted to real type.
+
    Function allows conversions between types of different signedness and
    can return SAFE_CONVERSION (zero) in that case.  Function can produce
-   signedness warnings if PRODUCE_WARNS is true.  */
+   signedness warnings if PRODUCE_WARNS is true.
+
+   Function allows conversions from complex constants to non-complex types,
+   provided that imaginary part is zero and real part can be safely converted
+   to TYPE.  */
 
 enum conversion_safety
 unsafe_conversion_p (location_t loc, tree type, tree expr, bool produce_warns)
@@ -2728,6 +2753,11 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, bool produce_warns)
 
   if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
     {
+      /* If type is complex, we are interested in compatibility with
+        underlying type.  */
+      if (TREE_CODE (type) == COMPLEX_TYPE)
+         type = TREE_TYPE (type);
+
       /* Warn for real constant that is not an exact integer converted
         to integer type.  */
       if (TREE_CODE (expr_type) == REAL_TYPE
@@ -2777,6 +2807,63 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, bool produce_warns)
            }
        }
     }
+
+  else if (TREE_CODE (expr) == COMPLEX_CST)
+    {
+      tree imag_part = TREE_IMAGPART (expr);
+      /* Conversion from complex constant with zero imaginary part,
+        perform check for conversion of real part.  */
+      if ((TREE_CODE (imag_part) == REAL_CST
+          && real_zerop (imag_part))
+         || (TREE_CODE (imag_part) == INTEGER_CST
+             && integer_zerop (imag_part)))
+       /* Note: in this branch we use recursive call to unsafe_conversion_p
+          with different type of EXPR, but it is still safe, because when EXPR
+          is a constant, it's type is not used in text of generated warnings
+          (otherwise they could sound misleading).  */
+       return unsafe_conversion_p (loc, type, TREE_REALPART (expr),
+                                   produce_warns);
+      /* Conversion from complex constant with non-zero imaginary part.  */
+      else
+       {
+         /* Conversion to complex type.
+            Perform checks for both real and imaginary parts.  */
+         if (TREE_CODE (type) == COMPLEX_TYPE)
+           {
+             /* Unfortunately, produce_warns must be false in two subsequent
+                calls of unsafe_conversion_p, because otherwise we could
+                produce strange "double" warnings, if both real and imaginary
+                parts have conversion problems related to signedness.
+
+                For example:
+                int32_t _Complex a = 0x80000000 + 0x80000000i;
+
+                Possible solution: add a separate function for checking
+                constants and combine result of two calls appropriately.  */
+             enum conversion_safety re_safety =
+                 unsafe_conversion_p (loc, type, TREE_REALPART (expr), false);
+             enum conversion_safety im_safety =
+                 unsafe_conversion_p (loc, type, imag_part, false);
+
+             /* Merge the results into appropriate single warning.  */
+
+             /* Note: this case includes SAFE_CONVERSION, i.e. success.  */
+             if (re_safety == im_safety)
+               give_warning = re_safety;
+             else if (!re_safety && im_safety)
+               give_warning = im_safety;
+             else if (re_safety && !im_safety)
+               give_warning = re_safety;
+             else
+               give_warning = UNSAFE_OTHER;
+           }
+         /* Warn about conversion from complex to real or integer type.  */
+         else
+           give_warning = UNSAFE_IMAGINARY;
+       }
+    }
+
+  /* Checks for remaining case: EXPR is not constant.  */
   else
     {
       /* Warn for real types converted to integer types.  */
@@ -2856,20 +2943,11 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, bool produce_warns)
       else if (TREE_CODE (expr_type) == INTEGER_TYPE
               && TREE_CODE (type) == REAL_TYPE)
        {
-         tree type_low_bound, type_high_bound;
-         REAL_VALUE_TYPE real_low_bound, real_high_bound;
-
          /* Don't warn about char y = 0xff; float x = (int) y;  */
          expr = get_unwidened (expr, 0);
          expr_type = TREE_TYPE (expr);
 
-         type_low_bound = TYPE_MIN_VALUE (expr_type);
-         type_high_bound = TYPE_MAX_VALUE (expr_type);
-         real_low_bound = real_value_from_int_cst (0, type_low_bound);
-         real_high_bound = real_value_from_int_cst (0, type_high_bound);
-
-         if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
-             || !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
+         if (!int_safely_convertible_to_real_p (expr_type, type))
            give_warning = UNSAFE_OTHER;
        }
 
@@ -2878,6 +2956,58 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, bool produce_warns)
               && TREE_CODE (type) == REAL_TYPE
               && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
        give_warning = UNSAFE_REAL;
+
+      /* Check conversion between two complex types.  */
+      else if (TREE_CODE (expr_type) == COMPLEX_TYPE
+              && TREE_CODE (type) == COMPLEX_TYPE)
+       {
+         /* Extract underlying types (i.e., type of real and imaginary
+            parts) of expr_type and type.  */
+         tree from_type = TREE_TYPE (expr_type);
+         tree to_type = TREE_TYPE (type);
+
+         /* Warn for real types converted to integer types.  */
+         if (TREE_CODE (from_type) == REAL_TYPE
+             && TREE_CODE (to_type) == INTEGER_TYPE)
+           give_warning = UNSAFE_REAL;
+
+         /* Warn for real types converted to smaller real types.  */
+         else if (TREE_CODE (from_type) == REAL_TYPE
+                  && TREE_CODE (to_type) == REAL_TYPE
+                  && TYPE_PRECISION (to_type) < TYPE_PRECISION (from_type))
+           give_warning = UNSAFE_REAL;
+
+         /* Check conversion for complex integer types.  Here implementation
+            is simpler than for real-domain integers because it does not
+            involve sophisticated cases, such as bitmasks, casts, etc.  */
+         else if (TREE_CODE (from_type) == INTEGER_TYPE
+                  && TREE_CODE (to_type) == INTEGER_TYPE)
+           {
+             /* Warn for integer types converted to smaller integer types.  */
+             if (TYPE_PRECISION (to_type) < TYPE_PRECISION (from_type))
+               give_warning = UNSAFE_OTHER;
+
+             /* Check for different signedness, see case for real-domain
+                integers (above) for a more detailed comment.  */
+             else if (((TYPE_PRECISION (to_type) == TYPE_PRECISION (from_type)
+                   && TYPE_UNSIGNED (to_type) != TYPE_UNSIGNED (from_type))
+                   || (TYPE_UNSIGNED (to_type) && !TYPE_UNSIGNED (from_type)))
+                   && produce_warns)
+               warning_at (loc, OPT_Wsign_conversion,
+                       "conversion to %qT from %qT "
+                       "may change the sign of the result",
+                       type, expr_type);
+           }
+         else if (TREE_CODE (from_type) == INTEGER_TYPE
+                  && TREE_CODE (to_type) == REAL_TYPE
+                  && !int_safely_convertible_to_real_p (from_type, to_type))
+           give_warning = UNSAFE_OTHER;
+       }
+
+      /* Warn for complex types converted to real or integer types.  */
+      else if (TREE_CODE (expr_type) == COMPLEX_TYPE
+              && TREE_CODE (type) != COMPLEX_TYPE)
+       give_warning = UNSAFE_IMAGINARY;
     }
 
   return give_warning;
@@ -2927,6 +3057,7 @@ conversion_warning (location_t loc, tree type, tree expr)
 
     case REAL_CST:
     case INTEGER_CST:
+    case COMPLEX_CST:
       conversion_kind = unsafe_conversion_p (loc, type, expr, true);
       if (conversion_kind == UNSAFE_REAL)
        warning_at (loc, OPT_Wfloat_conversion,
@@ -2956,6 +3087,10 @@ conversion_warning (location_t loc, tree type, tree expr)
        warning_at (loc, OPT_Wfloat_conversion,
                    "conversion to %qT from %qT may alter its value",
                    type, expr_type);
+      else if (conversion_kind == UNSAFE_IMAGINARY)
+       warning_at (loc, OPT_Wconversion,
+                   "conversion to %qT from %qT discards imaginary component",
+                   type, expr_type);
       else if (conversion_kind)
        warning_at (loc, OPT_Wconversion,
                    "conversion to %qT from %qT may alter its value",
index 444d80d..62eac9f 100644 (file)
@@ -728,15 +728,22 @@ struct visibility_flags
   unsigned inlines_hidden : 1; /* True when -finlineshidden in effect.  */
 };
 
-/* These enumerators are possible types of unsafe conversions.
-   SAFE_CONVERSION The conversion is safe
-   UNSAFE_OTHER Another type of conversion with problems
-   UNSAFE_SIGN Conversion between signed and unsigned integers
-    which are all warned about immediately, so this is unused
-   UNSAFE_REAL Conversions that reduce the precision of reals
-    including conversions from reals to integers
- */
-enum conversion_safety { SAFE_CONVERSION = 0, UNSAFE_OTHER, UNSAFE_SIGN, UNSAFE_REAL };
+/* These enumerators are possible types of unsafe conversions.  */
+enum conversion_safety {
+  /* The conversion is safe.  */
+  SAFE_CONVERSION = 0,
+  /* Another type of conversion with problems.  */
+  UNSAFE_OTHER,
+  /* Conversion between signed and unsigned integers
+     which are all warned about immediately, so this is unused.  */
+  UNSAFE_SIGN,
+  /* Conversions that reduce the precision of reals including conversions
+     from reals to integers.  */
+  UNSAFE_REAL,
+  /* Conversions from complex to reals or integers, that discard imaginary
+     component.  */
+  UNSAFE_IMAGINARY
+};
 
 /* Global visibility options.  */
 extern struct visibility_flags visibility_options;
index 5875476..cdd1c28 100644 (file)
@@ -1,3 +1,9 @@
+2015-05-15  Mikhail Maltsev  <maltsevm@gmail.com>
+
+       PR c/48956
+       * gcc.dg/Wconversion-complex-c99.c: New test.
+       * gcc.dg/Wconversion-complex-gnu.c: New test.
+
 2015-05-15  Marc Glisse  <marc.glisse@inria.fr>
 
        PR tree-optimization/64454
diff --git a/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c b/gcc/testsuite/gcc.dg/Wconversion-complex-c99.c
new file mode 100644 (file)
index 0000000..0e6c390
--- /dev/null
@@ -0,0 +1,138 @@
+/* PR c/48956: Test for diagnostics for implicit conversions from complex
+   to real types and narrowing conversions of complex types.  */
+
+/* Architecture restrictions taken from Wconversion-real-integer.c.
+   Likewise, the magic value 16777217.  */
+
+/* { dg-do compile } */
+/* { dg-skip-if "doubles are floats,ints are 16bits" { "avr-*-*" } { "*" } { "" } } */
+/* { dg-options " -std=c99 -pedantic -Wconversion " } */
+/* { dg-require-effective-target int32plus } */
+/* { dg-require-effective-target double64plus } */
+
+/* A number which does not fit into float.  */
+#define MAX_FLOAT_PLUS 16777217.
+
+/* Other types could be added, but that won't affect test coverage.  */
+void ffloatc (float _Complex);
+void fdoublec (double _Complex);
+
+void ffloat (float);
+void fdouble (double);
+
+void fsi (int);
+void fui (unsigned);
+
+float _Complex vfloatc;
+double _Complex vdoublec;
+
+float vfloat;
+double vdouble;
+
+int vsi;
+unsigned vui;
+
+/* Check implicit conversions of complex values to reals.  */
+void
+var_complex_to_real (void)
+{
+  float _Complex floatc = 0.;
+  double _Complex doublec = 0.;
+
+  ffloatc (floatc);
+  fdoublec (doublec);
+  vfloatc = floatc;
+  vdoublec = doublec;
+
+  ffloat (floatc); /* { dg-warning "conversion" } */
+  fdouble (floatc); /* { dg-warning "conversion" } */
+  vfloat = floatc; /* { dg-warning "conversion" } */
+  vdouble = floatc; /* { dg-warning "conversion" } */
+
+  ffloat (doublec); /* { dg-warning "conversion" } */
+  fdouble (doublec); /* { dg-warning "conversion" } */
+  vfloat = doublec; /* { dg-warning "conversion" } */
+  vdouble = doublec; /* { dg-warning "conversion" } */
+}
+
+/* Check implicit narrowing conversions of complex values.  */
+void
+var_complex_narrowing (void)
+{
+  float _Complex floatc = 0.;
+  double _Complex doublec = 0.;
+
+  vdoublec = floatc;
+  vfloatc = doublec; /* { dg-warning "float-conversion" } */
+
+  fdoublec (floatc);
+  ffloatc (doublec); /* { dg-warning "float-conversion" } */
+}
+
+/* Check implicit conversions of complex values to integers.  */
+void
+var_complex_to_int (void)
+{
+  float _Complex floatc = 0.;
+  double _Complex doublec = 0.;
+
+  fsi (floatc); /* { dg-warning "conversion" } */
+  fui (floatc); /* { dg-warning "conversion" } */
+  vsi = floatc; /* { dg-warning "conversion" } */
+  vui = floatc; /* { dg-warning "conversion" } */
+
+  fsi (doublec); /* { dg-warning "conversion" } */
+  fui (doublec); /* { dg-warning "conversion" } */
+  vsi = doublec; /* { dg-warning "conversion" } */
+  vui = doublec; /* { dg-warning "conversion" } */
+}
+
+/* Check implicit conversion of constant complex values to floats.  */
+void
+const_complex_to_real (void)
+{
+  ffloat (__builtin_complex (0., 1.)); /* { dg-warning "conversion" } */
+  fdouble (__builtin_complex (0., 1.)); /* { dg-warning "conversion" } */
+
+  vfloat = __builtin_complex (0., 1.); /* { dg-warning "conversion" } */
+  vdouble = __builtin_complex (0., 1.); /* { dg-warning "conversion" } */
+
+  vfloat = __builtin_complex (1., 0.) + __builtin_complex (1., 0.);
+  vdouble = __builtin_complex (0., 0.) * __builtin_complex (1., 1.);
+  ffloat (__builtin_complex (1., 0.) + __builtin_complex (1., 0.));
+  fdouble (__builtin_complex (1., 0.) + __builtin_complex (1., 0.));
+
+  vfloat = __builtin_complex (MAX_FLOAT_PLUS, 0.); /* { dg-warning "float-conversion" } */
+  ffloat (__builtin_complex (MAX_FLOAT_PLUS, 0.)); /* { dg-warning "float-conversion" } */
+}
+
+/* Check implicit conversion of constant complex values to integers.  */
+void
+const_complex_to_int (void)
+{
+  vsi = __builtin_complex (-1., 0.);
+  vui = __builtin_complex (1., 0.);
+  fsi (__builtin_complex (-1., 0.));
+  fui (__builtin_complex (1., 0.));
+
+  vui = __builtin_complex (-1., 0.); /* { dg-warning "overflow" } */
+  fui (__builtin_complex (-1., 0.)); /* { dg-warning "overflow" } */
+
+  vsi = __builtin_complex (0.5, 0.); /* { dg-warning "float-conversion" } */
+  fui (__builtin_complex (0.5, 0.)); /* { dg-warning "float-conversion" } */
+
+  vsi = __builtin_complex (-0.5, 0.); /* { dg-warning "float-conversion" } */
+  fui (__builtin_complex (-0.5, 0.)); /* { dg-warning "float-conversion" } */
+}
+
+/* Check implicit narrowing conversion of constant complex values to.  */
+void
+const_complex_narrowing (void)
+{
+  ffloatc (__builtin_complex (-100., 100.));
+
+  ffloatc (__builtin_complex (MAX_FLOAT_PLUS, 0.)); /* { dg-warning "float-conversion" } */
+  ffloatc (__builtin_complex (0., MAX_FLOAT_PLUS)); /* { dg-warning "float-conversion" } */
+  ffloatc (__builtin_complex (MAX_FLOAT_PLUS, MAX_FLOAT_PLUS)); /* { dg-warning "float-conversion" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/Wconversion-complex-gnu.c b/gcc/testsuite/gcc.dg/Wconversion-complex-gnu.c
new file mode 100644 (file)
index 0000000..3839a39
--- /dev/null
@@ -0,0 +1,127 @@
+/* PR c/48956: Test for diagnostics for implicit conversions involving complex
+   types.  See also Wconversion-complex-c99.c.
+
+   These tests cover integer complex values (which are GNU extensions).  */
+
+/* { dg-do compile } */
+/* { dg-skip-if "doubles are floats,ints are 16bits" { "avr-*-*" } { "*" } { "" } } */
+/* { dg-options " -std=gnu99 -Wconversion " } */
+/* { dg-require-effective-target int32plus } */
+/* { dg-require-effective-target double64plus } */
+
+#include <limits.h>
+
+void fsi (int);
+void fui (unsigned);
+void ffloat (float);
+int vsi;
+unsigned int vui;
+float vfloat;
+
+void fsic (int _Complex);
+void fuic (unsigned _Complex);
+void ffloatc (float _Complex);
+int _Complex vsic;
+unsigned _Complex vuic;
+float _Complex vfloatc;
+
+/* Check implicit conversions of float complex-domain values to integer
+   complex-domain types.  */
+void
+var_float_to_int (void)
+{
+  double _Complex doublec = 0.;
+
+  fsic (doublec); /* { dg-warning "float-conversion" } */
+  fuic (doublec); /* { dg-warning "float-conversion" } */
+
+  vsic = doublec; /* { dg-warning "float-conversion" } */
+  vuic = doublec; /* { dg-warning "float-conversion" } */
+}
+
+/* Check implicit conversions of integer complex-domain values to integer
+   real-domain types.  */
+void
+var_complex_to_real (void)
+{
+  int _Complex ic = 0;
+  unsigned _Complex uc = 0;
+  unsigned long long _Complex ullc = 0;
+
+  fsic (ic);
+  fuic (uc);
+  vsic = ic;
+  vuic = uc;
+
+  fsi (ic); /* { dg-warning "conversion" } */
+  vsi = ic; /* { dg-warning "conversion" } */
+  fui (uc); /* { dg-warning "conversion" } */
+  vui = uc; /* { dg-warning "conversion" } */
+
+  fuic (ullc); /* { dg-warning "conversion" } */
+  vuic = ullc; /* { dg-warning "conversion" } */
+
+  fui (ic); /* { dg-warning "conversion" } */
+  vui = ic; /* { dg-warning "conversion" } */
+}
+
+/* Check implicit conversions of float complex-domain constants to integer
+   types.  */
+void
+const_float_to_int (void)
+{
+  fsic (1. - 1.i);
+  fuic (1. + 1.i);
+  vsic = 1. - 1.i;
+  vuic = 1. + 1.i;
+
+  fsic (0.5 + 0.i); /* { dg-warning "float-conversion" } */
+  vsic = 0.5 + 0.i; /* { dg-warning "float-conversion" } */
+  fuic (0.5 + 0.i); /* { dg-warning "float-conversion" } */
+}
+
+/* Check implicit conversions of integer complex-domain constants to integer
+   types.  */
+void
+const_complex_int_to_real_int (void)
+{
+  fsi (-1 + 0i);
+  fui (1 + 0i);
+  vsi = -1 + 0i;
+  vui = 1 + 0i;
+
+  fui (1 + 1i); /* { dg-warning "conversion" } */
+  vui = 1 + 1i; /* { dg-warning "conversion" } */
+
+  fui (UINT_MAX + 1ull + 0i); /* { dg-warning "conversion" } */
+  vui = UINT_MAX + 1ull + 0i; /* { dg-warning "conversion" } */
+
+  ffloat (UINT_MAX + 0i); /* { dg-warning "float-conversion" } */
+  vfloat = UINT_MAX + 0i; /* { dg-warning "float-conversion" } */
+}
+
+void
+const_complex_int_narrowing (void)
+{
+  fsic (1 - 1i);
+  fuic (1 + 1i);
+  vsic = 1 - 1i;
+  vuic = 1 + 1i;
+
+  fuic (UINT_MAX + 1ull + 1i); /* { dg-warning "conversion" } */
+  fuic ((UINT_MAX + 1ull) * 1i); /* { dg-warning "conversion" } */
+  fuic ((UINT_MAX + 1ull) + (UINT_MAX + 1ull) * 1i); /* { dg-warning "conversion" } */
+
+  vuic = (UINT_MAX + 1ull) * 1i; /* { dg-warning "conversion" } */
+  vuic = (UINT_MAX + 1ull) + 1i; /* { dg-warning "conversion" } */
+  vuic = (UINT_MAX + 1ull) + (UINT_MAX + 1ull) * 1i; /* { dg-warning "conversion" } */
+
+  ffloatc (UINT_MAX * 1i); /* { dg-warning "float-conversion" } */
+  ffloatc (UINT_MAX + 1i); /* { dg-warning "float-conversion" } */
+  ffloatc (UINT_MAX + UINT_MAX * 1i); /* { dg-warning "float-conversion" } */
+
+  vfloatc = UINT_MAX * 1i; /* { dg-warning "float-conversion" } */
+  vfloatc = UINT_MAX + 1i; /* { dg-warning "float-conversion" } */
+  vfloatc = UINT_MAX + UINT_MAX * 1i; /* { dg-warning "float-conversion" } */
+}
+