]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c/35635 (-Wconversion problematic with bitfields)
authorManuel López-Ibáñez <manu@gcc.gnu.org>
Wed, 13 Aug 2008 10:01:52 +0000 (10:01 +0000)
committerManuel López-Ibáñez <manu@gcc.gnu.org>
Wed, 13 Aug 2008 10:01:52 +0000 (10:01 +0000)
2008-08-13  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

PR 35635
* c-common.c (conversion_warning): Use a switch. Ignore boolean
expressions except for conversions to signed:1 bitfields. Handle
COND_EXPR with constant operands.
testsuite/
* gcc.dg/pr35635.c: New.
* gcc.dg/Wconversion-integer.c: Update.
* gcc.dg/Wconversion-integer-no-sign.c: Update.
* gcc.dg/Wsign-conversion.c: Update.
* g++.dg/warn/pr35635.C: New.
* g++.dg/warn/Wconversion-integer.C: Update.
* g++.dg/warn/Wsign-conversion.C: Update.

From-SVN: r139049

gcc/ChangeLog
gcc/c-common.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wconversion-integer.C
gcc/testsuite/g++.dg/warn/Wsign-conversion.C
gcc/testsuite/g++.dg/warn/pr35635.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/Wconversion-integer-no-sign.c
gcc/testsuite/gcc.dg/Wconversion-integer.c
gcc/testsuite/gcc.dg/Wsign-conversion.c
gcc/testsuite/gcc.dg/pr35635.c [new file with mode: 0644]

index 805d73dd3759948af542701d1bb389ce67058a3d..4e03620f40d2fa59a8eb4d66c9ec1423af0feeb0 100644 (file)
@@ -1,3 +1,10 @@
+2008-08-13  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
+
+       PR 35635
+       * c-common.c (conversion_warning): Use a switch. Ignore boolean
+       expressions except for conversions to signed:1 bitfields. Handle
+       COND_EXPR with constant operands.
+       
 2008-08-13  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/15255
index 59da62f7ecc8d0864ac35dc21ebe6a62402047bd..93021820cd68e4e6ea891ba5f7ec19b54af4a1f7 100644 (file)
@@ -1559,39 +1559,63 @@ conversion_warning (tree type, tree expr)
 {
   bool give_warning = false;
 
-  unsigned int formal_prec = TYPE_PRECISION (type);
+  tree expr_type = TREE_TYPE (expr);
 
   if (!warn_conversion && !warn_sign_conversion)
     return;
 
-  if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
+  switch (TREE_CODE (expr))
     {
+    case EQ_EXPR:
+    case NE_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
+    case TRUTH_NOT_EXPR:
+      /* Conversion from boolean to a signed:1 bit-field (which only
+        can hold the values 0 and -1) doesn't lose information - but
+        it does change the value.  */
+      if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) 
+       warning (OPT_Wconversion,
+                 "conversion to %qT from boolean expression", type);
+      return;
+
+    case REAL_CST:
+    case INTEGER_CST:
+
       /* Warn for real constant that is not an exact integer converted
          to integer type.  */
-      if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+      if (TREE_CODE (expr_type) == REAL_TYPE
           && TREE_CODE (type) == INTEGER_TYPE)
         {
-          if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (TREE_TYPE (expr))))
+          if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
             give_warning = true;
         }
       /* Warn for an integer constant that does not fit into integer type.  */
-      else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      else if (TREE_CODE (expr_type) == INTEGER_TYPE
                && TREE_CODE (type) == INTEGER_TYPE
                && !int_fits_type_p (expr, type))
         {
-          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))
+          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type) 
+             && tree_int_cst_sgn (expr) < 0)
            warning (OPT_Wsign_conversion,
                     "negative integer implicitly converted to unsigned type");
-          else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (TREE_TYPE (expr)))
-           warning (OPT_Wsign_conversion,
-                    "conversion of unsigned constant value to negative integer");
+          else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type))
+           warning (OPT_Wsign_conversion,  "conversion of unsigned constant "
+                    "value to negative integer");
          else
            give_warning = true;
         }
       else if (TREE_CODE (type) == REAL_TYPE)
         {
           /* Warn for an integer constant that does not fit into real type.  */
-          if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE)
+          if (TREE_CODE (expr_type) == INTEGER_TYPE)
             {
               REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
               if (!exact_real_truncate (TYPE_MODE (type), &a))
@@ -1599,8 +1623,8 @@ conversion_warning (tree type, tree expr)
             }
           /* Warn for a real constant that does not fit into a smaller
              real type.  */
-          else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
-                   && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+          else if (TREE_CODE (expr_type) == REAL_TYPE
+                   && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
             {
               REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
               if (!exact_real_truncate (TYPE_MODE (type), &a))
@@ -1611,11 +1635,31 @@ conversion_warning (tree type, tree expr)
       if (give_warning)
         warning (OPT_Wconversion,
                  "conversion to %qT alters %qT constant value",
-                 type, TREE_TYPE (expr));
-    }
-  else /* 'expr' is not a constant.  */
-    {
-      tree expr_type = TREE_TYPE (expr);
+                 type, expr_type);
+
+      return;
+
+    case COND_EXPR:
+      {
+       /* In case of COND_EXPR, if both operands are constants or
+          COND_EXPR, then we do not care about the type of COND_EXPR,
+          only about the conversion of each operand.  */
+       tree op1 = TREE_OPERAND (expr, 1);
+       tree op2 = TREE_OPERAND (expr, 2);
+
+       if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST 
+            || TREE_CODE (op1) == COND_EXPR)
+           && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
+               || TREE_CODE (op2) == COND_EXPR))
+         {
+           conversion_warning (type, op1);
+           conversion_warning (type, op2);
+           return;
+         }
+       /* Fall through.  */
+      }
+
+    default: /* 'expr' is not a constant.  */
 
       /* Warn for real types converted to integer types.  */
       if (TREE_CODE (expr_type) == REAL_TYPE
@@ -1631,11 +1675,11 @@ conversion_warning (tree type, tree expr)
 
          /* Don't warn for short y; short x = ((int)y & 0xff);  */
          if (TREE_CODE (expr) == BIT_AND_EXPR 
-             || TREE_CODE (expr) == BIT_IOR_EXPR 
+               || TREE_CODE (expr) == BIT_IOR_EXPR 
              || TREE_CODE (expr) == BIT_XOR_EXPR)
            {
-           /* It both args were extended from a shortest type, use
-              that type if that is safe.  */
+             /* If both args were extended from a shortest type,
+                use that type if that is safe.  */
              expr_type = shorten_binary_op (expr_type, 
                                             TREE_OPERAND (expr, 0), 
                                             TREE_OPERAND (expr, 1), 
@@ -1652,25 +1696,26 @@ conversion_warning (tree type, tree expr)
                       && int_fits_type_p (op0, c_common_signed_type (type))
                       && int_fits_type_p (op0, c_common_unsigned_type (type)))
                      || (TREE_CODE (op1) == INTEGER_CST
-                      && int_fits_type_p (op1, c_common_signed_type (type))
-                      && int_fits_type_p (op1, c_common_unsigned_type (type))))
+                         && int_fits_type_p (op1, c_common_signed_type (type))
+                         && int_fits_type_p (op1, 
+                                             c_common_unsigned_type (type))))
                    return;
                }
            }
           /* Warn for integer types converted to smaller integer types.  */
-          if (formal_prec < TYPE_PRECISION (expr_type)) 
+         if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) 
            give_warning = true;
 
          /* When they are the same width but different signedness,
             then the value may change.  */
-         else if ((formal_prec == TYPE_PRECISION (expr_type)
+         else if ((TYPE_PRECISION (type) == TYPE_PRECISION (expr_type)
                    && TYPE_UNSIGNED (expr_type) != TYPE_UNSIGNED (type))
                   /* Even when converted to a bigger type, if the type is
                      unsigned but expr is signed, then negative values
                      will be changed.  */
                   || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)))
-           warning (OPT_Wsign_conversion,
-                    "conversion to %qT from %qT may change the sign of the result",
+           warning (OPT_Wsign_conversion, "conversion to %qT from %qT "
+                    "may change the sign of the result",
                     type, expr_type);
         }
 
@@ -1682,8 +1727,10 @@ conversion_warning (tree type, tree expr)
         {
           tree type_low_bound = TYPE_MIN_VALUE (expr_type);
           tree type_high_bound = TYPE_MAX_VALUE (expr_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);
+          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);
 
           if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
               || !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
@@ -1693,7 +1740,7 @@ conversion_warning (tree type, tree expr)
       /* Warn for real types converted to smaller real types.  */
       else if (TREE_CODE (expr_type) == REAL_TYPE
                && TREE_CODE (type) == REAL_TYPE
-               && formal_prec < TYPE_PRECISION (expr_type))
+               && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
         give_warning = true;
 
 
index ca8c8cfe5d12a1cd771779b862a6a211ece4c130..50096c9bbc71c9db80f4fc7d4358239dc479d50a 100644 (file)
@@ -1,3 +1,14 @@
+2008-08-13  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
+
+       PR 35635
+       * gcc.dg/pr35635.c: New.
+       * gcc.dg/Wconversion-integer.c: Update.
+       * gcc.dg/Wconversion-integer-no-sign.c: Update.
+       * gcc.dg/Wsign-conversion.c: Update.
+       * g++.dg/warn/pr35635.C: New.
+       * g++.dg/warn/Wconversion-integer.C: Update.
+       * g++.dg/warn/Wsign-conversion.C: Update.
+       
 2008-08-13  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/15255
index 46900825a8b5167fbecbaa8a78a4d1f3342721c1..42d9cb00044b2664f9ba191fa5b35fca7c3d0e7d 100644 (file)
@@ -42,8 +42,8 @@ void h (int x)
 
   uc = x ? 1U : -1; /* { dg-warning "conversion" } */
   uc = x ? SCHAR_MIN : 1U; /* { dg-warning "conversion" } */
-  uc = x ? 1 : -1; /* { dg-warning "conversion" } */
-  uc = x ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+  uc = x ? 1 : -1; /* Warned by -Wsign-conversion.  */
+  uc = x ? SCHAR_MIN : 1; /* Warned by -Wsign-conversion.  */
   ui = x ? 1U : -1; /* Warned by -Wsign-conversion.  */
   ui = x ? INT_MIN : 1U; /* Warned by -Wsign-conversion.  */
   ui = ui ? SCHAR_MIN : 1U; /* Warned by -Wsign-conversion.  */
index b097446c3f84f4f9d2efddd3141f32b5dca982be..83fe2ed660b41c4a0a2fa09fa3da79508c3987a6 100644 (file)
@@ -42,15 +42,15 @@ void h (int x)
 
   uc = x ? 1U : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   uc = x ? SCHAR_MIN : 1U;  /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  uc = x ? 1 : -1; 
-  uc = x ? SCHAR_MIN : 1; 
+  uc = x ? 1 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = x ? SCHAR_MIN : 1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = x ? 1U : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = x ? INT_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = ui ? SCHAR_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = 1U * -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = ui + INT_MIN; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  ui = x ? 1 : -1; /* { dg-warning "conversion" } */
-  ui = ui ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+  ui = x ? 1 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = ui ? SCHAR_MIN : 1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
 
   fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   uc = -1;  /* { dg-warning "negative integer implicitly converted to unsigned type" } */
diff --git a/gcc/testsuite/g++.dg/warn/pr35635.C b/gcc/testsuite/g++.dg/warn/pr35635.C
new file mode 100644 (file)
index 0000000..d3b39a2
--- /dev/null
@@ -0,0 +1,89 @@
+/* PR 35635 */
+/* { dg-do compile } */
+/* { dg-options "-Wconversion -Wsign-conversion" } */
+
+struct unsigned_bit {
+  unsigned int x:1;
+} unsigned_bit;
+struct signed_bit {
+  int x:1;
+} signed_bit;
+int bar;
+int bar2;
+
+void func1()
+{
+  /* The result of boolean operators fits in unsiged int:1, thus do
+     not warn.  */
+  unsigned_bit.x = (bar != 0); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar == 0); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar <= 0); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar >= 0); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar < 0);  /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar > 0);  /* { dg-bogus "conversion" } */
+  unsigned_bit.x = !bar;       /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar || bar2); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar && bar2); /* { dg-bogus "conversion" } */
+
+  /* Both branches of ? fit in the destination, thus do not warn.  */
+  unsigned_bit.x = bar != 0 ? 1 : 0; /* { dg-bogus "conversion" } */
+  unsigned_bit.x = bar != 0 ? 1.0 : 0.0;  /* { dg-bogus "conversion" } */
+
+  /* At least one branch of ? does not fit in the destination, thus
+     warn.  */
+  unsigned_bit.x = bar != 0 ? 2 : 0; /* { dg-warning "conversion" } */
+  unsigned_bit.x = bar != 0 ? 0 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+}
+
+void func2()
+{
+  signed char schar_x;
+
+  /* Both branches of ? fit in the destination, thus do not warn.  */
+  schar_x = bar != 0 ? 1 : 0; /* { dg-bogus "conversion" } */
+  schar_x = bar != 0 ? 2.0 : 10; /* { dg-bogus "conversion" } */
+
+  /* At least one branch of ? does not fit in the destination, thus
+     warn.  */
+  schar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion" } */
+  schar_x = bar != 0 ? (signed char) 1024: -1024; /* { dg-warning "conversion" } */
+}
+
+
+
+void func3()
+{
+  unsigned char uchar_x;
+
+  /* Both branches of ? fit in the destination, thus do not warn.  */
+  uchar_x = bar != 0 ? 1 : 0;
+  uchar_x = bar != 0 ? 2.0 : 10;
+
+  /* At least one branch of ? does not fit in the destination, thus
+     warn.  */
+  uchar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion" } */
+  uchar_x = bar != 0 
+    ? (unsigned char) 1024 
+    : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+}
+
+void func4()
+{
+  signed_bit.x = -1; /* { dg-bogus "conversion" } */
+  signed_bit.x = bar != 0 ? -1.0 : 0.0;  /* { dg-bogus "conversion" } */
+  signed_bit.x = bar != 0 ? -1 : 0; /* { dg-bogus "conversion" } */
+  
+  signed_bit.x = 1;          /* { dg-warning "conversion" } */
+  signed_bit.x = (bar != 0); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar == 0); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar <= 0); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar >= 0); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar < 0);  /* { dg-warning "conversion" } */
+  signed_bit.x = (bar > 0);  /* { dg-warning "conversion" } */
+  signed_bit.x = !bar;       /* { dg-warning "conversion" } */
+  signed_bit.x = (bar || bar2); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar && bar2); /* { dg-warning "conversion" } */
+  signed_bit.x = bar != 0 ? 1 : 0; /* { dg-warning "conversion" } */
+  signed_bit.x = bar != 0 ? 2 : 0; /* { dg-warning "conversion" } */
+}
+
index 0847db28da913332bb57f04d95f3194a64decf85..c17d502d8f33f7dcdd3081640311069d72deba18 100644 (file)
@@ -42,8 +42,8 @@ void h (int x)
 
   uc = x ? 1U : -1; /* { dg-warning "conversion" } */
   uc = x ? SCHAR_MIN : 1U; /* { dg-warning "conversion" } */
-  uc = x ? 1 : -1; /* { dg-warning "conversion" } */
-  uc = x ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+  uc = x ? 1 : -1; /* Warned by -Wsign-conversion.  */
+  uc = x ? SCHAR_MIN : 1; /* Warned by -Wsign-conversion.  */
   ui = x ? 1U : -1; /* Warned by -Wsign-conversion.  */
   ui = x ? INT_MIN : 1U; /* Warned by -Wsign-conversion.  */
   ui = ui ? SCHAR_MIN : 1U; /* Warned by -Wsign-conversion.  */
index 9e3b948251c1cb9e4c7470a8f783e9a0051c60ad..b2101076f9383de72883b68d988b429b807a2a69 100644 (file)
@@ -44,15 +44,15 @@ void h (int x)
   /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 43 } */
   uc = x ? SCHAR_MIN : 1U; /* { dg-warning "conversion" } */
   /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 45 } */
-  uc = x ? 1 : -1; /* { dg-warning "conversion" } */
-  uc = x ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+  uc = x ? 1 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = x ? SCHAR_MIN : 1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = x ? 1U : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = x ? INT_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = ui ? SCHAR_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = 1U * -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = ui + INT_MIN; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  ui = x ? 1 : -1; /* { dg-warning "conversion" } */
-  ui = ui ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+  ui = x ? 1 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = ui ? SCHAR_MIN : 1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
 
   fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   uc = -1;  /* { dg-warning "negative integer implicitly converted to unsigned type" } */
index 45edd3b436145d0aad6b17b905537ca2808655bd..0300850f904a3f5f4f3edf7779712a4630c8b41d 100644 (file)
@@ -42,15 +42,15 @@ void h (int x)
 
   uc = x ? 1U : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   uc = x ? SCHAR_MIN : 1U;  /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  uc = x ? 1 : -1; 
-  uc = x ? SCHAR_MIN : 1; 
+  uc = x ? 1 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = x ? SCHAR_MIN : 1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = x ? 1U : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = x ? INT_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = ui ? SCHAR_MIN : 1U; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = 1U * -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = ui + INT_MIN; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  ui = x ? 1 : -1; /* { dg-warning "conversion" } */
-  ui = ui ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+  ui = x ? 1 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = ui ? SCHAR_MIN : 1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
 
   fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   uc = -1;  /* { dg-warning "negative integer implicitly converted to unsigned type" } */
diff --git a/gcc/testsuite/gcc.dg/pr35635.c b/gcc/testsuite/gcc.dg/pr35635.c
new file mode 100644 (file)
index 0000000..45d10a6
--- /dev/null
@@ -0,0 +1,90 @@
+/* PR 35635 */
+/* { dg-do compile } */
+/* { dg-options "-Wconversion -Wsign-conversion" } */
+
+struct unsigned_bit {
+  unsigned int x:1;
+} unsigned_bit;
+struct signed_bit {
+  int x:1;
+} signed_bit;
+int bar;
+int bar2;
+
+void func1()
+{
+  /* The result of boolean operators fits in unsiged int:1, thus do
+     not warn.  */
+  unsigned_bit.x = (bar != 0); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar == 0); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar <= 0); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar >= 0); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar < 0);  /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar > 0);  /* { dg-bogus "conversion" } */
+  unsigned_bit.x = !bar;       /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar || bar2); /* { dg-bogus "conversion" } */
+  unsigned_bit.x = (bar && bar2); /* { dg-bogus "conversion" } */
+
+  /* Both branches of ? fit in the destination, thus do not warn.  */
+  unsigned_bit.x = bar != 0 ? 1 : 0; /* { dg-bogus "conversion" } */
+  unsigned_bit.x = bar != 0 ? 1.0 : 0.0;  /* { dg-bogus "conversion" } */
+
+  /* At least one branch of ? does not fit in the destination, thus
+     warn.  */
+  unsigned_bit.x = bar != 0 ? 2 : 0; /* { dg-warning "conversion" } */
+  unsigned_bit.x = bar != 0 ? 0 : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+}
+
+void func2()
+{
+  signed char schar_x;
+
+  /* Both branches of ? fit in the destination, thus do not warn.  */
+  schar_x = bar != 0 ? 1 : 0; /* { dg-bogus "conversion" } */
+  schar_x = bar != 0 ? 2.0 : 10; /* { dg-bogus "conversion" } */
+
+  /* At least one branch of ? does not fit in the destination, thus
+     warn.  */
+  schar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion" } */
+  schar_x = bar != 0 ? (signed char) 1024: -1024; /* { dg-warning "conversion" } */
+}
+
+
+
+void func3()
+{
+  unsigned char uchar_x;
+
+  /* Both branches of ? fit in the destination, thus do not warn.  */
+  uchar_x = bar != 0 ? 1 : 0;
+  uchar_x = bar != 0 ? 2.0 : 10;
+
+  /* At least one branch of ? does not fit in the destination, thus
+     warn.  */
+  uchar_x = bar != 0 ? 2.1 : 10; /* { dg-warning "conversion" } */
+  uchar_x = bar != 0 
+    ? (unsigned char) 1024 
+    : -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+}
+
+void func4()
+{
+  signed_bit.x = -1; /* { dg-bogus "conversion" } */
+  signed_bit.x = bar != 0 ? -1.0 : 0.0;  /* { dg-bogus "conversion" } */
+  signed_bit.x = bar != 0 ? -1 : 0; /* { dg-bogus "conversion" } */
+
+  
+  signed_bit.x = 1;          /* { dg-warning "conversion" } */
+  signed_bit.x = (bar != 0); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar == 0); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar <= 0); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar >= 0); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar < 0);  /* { dg-warning "conversion" } */
+  signed_bit.x = (bar > 0);  /* { dg-warning "conversion" } */
+  signed_bit.x = !bar;       /* { dg-warning "conversion" } */
+  signed_bit.x = (bar || bar2); /* { dg-warning "conversion" } */
+  signed_bit.x = (bar && bar2); /* { dg-warning "conversion" } */
+  signed_bit.x = bar != 0 ? 1 : 0; /* { dg-warning "conversion" } */
+  signed_bit.x = bar != 0 ? 2 : 0; /* { dg-warning "conversion" } */
+}
+