Handle -Wsign-conversion in conversion_warning.
authorJason Merrill <jason@redhat.com>
Fri, 10 Jan 2020 17:49:03 +0000 (12:49 -0500)
committerJason Merrill <jason@redhat.com>
Tue, 21 Jan 2020 23:40:19 +0000 (18:40 -0500)
It seemed strange to me to warn about sign conversion in
unsafe_conversion_p, when other warnings are in conversion_warning, and the
latter function is the only place that asks the former function to warn.
This change is also necessary for my -Warith-conversion patch.

* c-common.c (unsafe_conversion_p): Don't warn, return UNSAFE_SIGN.
* c-warn.c (conversion_warning): Warn about UNSAFE_SIGN.

gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-family/c-warn.c

index fdddb98a74d1a97821854079278b5427e22816ce..fbbc924243d3e2d452d8d76ab7fa89fd572f8e6c 100644 (file)
@@ -1,3 +1,8 @@
+2020-01-21  Jason Merrill  <jason@redhat.com>
+
+       * c-common.c (unsafe_conversion_p): Don't warn, return UNSAFE_SIGN.
+       * c-warn.c (conversion_warning): Warn about UNSAFE_SIGN.
+
 2020-01-20  Nathan Sidwell  <nathan@acm.org>
 
        PR preprocessor/80005
index 82c08945a50bf30666dfd7c8a5ed7044a2f20de0..4a7f3a52335fa4c8e4853a0557f343d6dac85b22 100644 (file)
@@ -1312,9 +1312,9 @@ int_safely_convertible_to_real_p (const_tree from_type, const_tree to_type)
        * 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.
+   Function allows conversions between types of different signedness if
+   CHECK_SIGN is false and can return SAFE_CONVERSION (zero) in that
+   case.  Function can return UNSAFE_SIGN if CHECK_SIGN is true.
 
    RESULT, when non-null is the result of the conversion.  When constant
    it is included in the text of diagnostics.
@@ -1325,14 +1325,11 @@ int_safely_convertible_to_real_p (const_tree from_type, const_tree to_type)
 
 enum conversion_safety
 unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
-                    bool produce_warns)
+                    bool check_sign)
 {
   enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */
   tree expr_type = TREE_TYPE (expr);
 
-  bool cstresult = (result
-                   && TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant);
-
   loc = expansion_point_location_if_in_system_header (loc);
 
   expr = fold_for_warn (expr);
@@ -1360,32 +1357,13 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
              && tree_int_cst_sgn (expr) < 0)
            {
-             if (produce_warns)
-               {
-                 if (cstresult)
-                   warning_at (loc, OPT_Wsign_conversion,
-                               "unsigned conversion from %qT to %qT "
-                               "changes value from %qE to %qE",
-                               expr_type, type, expr, result);
-                 else
-                   warning_at (loc, OPT_Wsign_conversion,
-                               "unsigned conversion from %qT to %qT "
-                               "changes the value of %qE",
-                               expr_type, type, expr);
-               }
+             if (check_sign)
+               give_warning = UNSAFE_SIGN;
            }
          else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type))
            {
-             if (cstresult)
-               warning_at (loc, OPT_Wsign_conversion,
-                           "signed conversion from %qT to %qT changes "
-                           "value from %qE to %qE",
-                           expr_type, type, expr, result);
-             else
-               warning_at (loc, OPT_Wsign_conversion,
-                           "signed conversion from %qT to %qT changes "
-                           "the value of %qE",
-                           expr_type, type, expr);
+             if (check_sign)
+               give_warning = UNSAFE_SIGN;
            }
          else
            give_warning = UNSAFE_OTHER;
@@ -1425,7 +1403,7 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
           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), result,
-                                   produce_warns);
+                                   check_sign);
       /* Conversion from complex constant with non-zero imaginary part.  */
       else
        {
@@ -1433,21 +1411,11 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
             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),
-                                      result, false);
+               unsafe_conversion_p (loc, type, TREE_REALPART (expr),
+                                    result, check_sign);
              enum conversion_safety im_safety =
-               unsafe_conversion_p (loc, type, imag_part, result, false);
+               unsafe_conversion_p (loc, type, imag_part, result, check_sign);
 
              /* Merge the results into appropriate single warning.  */
 
@@ -1530,15 +1498,13 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
          /* When they are the same width but different signedness,
             then the value may change.  */
          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 (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)))
-                  && produce_warns)
-           warning_at (loc, OPT_Wsign_conversion, "conversion to %qT from %qT "
-                       "may change the sign of the result",
-                       type, expr_type);
+                  && check_sign)
+           give_warning = UNSAFE_SIGN;
        }
 
       /* Warn for integer types converted to real types if and only if
@@ -1594,13 +1560,10 @@ unsafe_conversion_p (location_t loc, tree type, tree expr, tree result,
              /* 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);
+                        && TYPE_UNSIGNED (to_type) != TYPE_UNSIGNED (from_type))
+                       || (TYPE_UNSIGNED (to_type) && !TYPE_UNSIGNED (from_type)))
+                      && check_sign)
+               give_warning = UNSAFE_SIGN;
            }
          else if (TREE_CODE (from_type) == INTEGER_TYPE
                   && TREE_CODE (to_type) == REAL_TYPE
index 59d4aaf44352fc0f1214fffedb2d719d4627ba80..fb0d53b079ebb4c2db6e366d180ac722c0f0e968 100644 (file)
@@ -784,8 +784,7 @@ enum conversion_safety {
   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.  */
+  /* Conversion between signed and unsigned integers.  */
   UNSAFE_SIGN,
   /* Conversions that reduce the precision of reals including conversions
      from reals to integers.  */
index bd749579e9537db791bed5d412d55afcd8996126..6dbc660ddb442c58513caf438ec02137cad9ea83 100644 (file)
@@ -1210,7 +1210,39 @@ conversion_warning (location_t loc, tree type, tree expr, tree result)
        else
          break;
 
-       if (TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant)
+       if (conversion_kind == UNSAFE_SIGN)
+         {
+           bool cstresult
+             = (result
+                && TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant);
+           if (TYPE_UNSIGNED (type))
+             {
+               if (cstresult)
+                 warning_at (loc, OPT_Wsign_conversion,
+                             "unsigned conversion from %qT to %qT "
+                             "changes value from %qE to %qE",
+                             expr_type, type, expr, result);
+               else
+                 warning_at (loc, OPT_Wsign_conversion,
+                             "unsigned conversion from %qT to %qT "
+                             "changes the value of %qE",
+                             expr_type, type, expr);
+             }
+           else
+             {
+               if (cstresult)
+                 warning_at (loc, OPT_Wsign_conversion,
+                             "signed conversion from %qT to %qT changes "
+                             "value from %qE to %qE",
+                             expr_type, type, expr, result);
+               else
+                 warning_at (loc, OPT_Wsign_conversion,
+                             "signed conversion from %qT to %qT changes "
+                             "the value of %qE",
+                             expr_type, type, expr);
+             }
+         }
+       else if (TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant)
          warning_at (loc, warnopt,
                      "conversion from %qT to %qT changes value from %qE to %qE",
                      expr_type, type, expr, result);
@@ -1234,23 +1266,29 @@ conversion_warning (location_t loc, tree type, tree expr, tree result)
 
     default: /* 'expr' is not a constant.  */
       conversion_kind = unsafe_conversion_p (loc, type, expr, result, true);
-      if (conversion_kind == UNSAFE_IMAGINARY)
-       warning_at (loc, OPT_Wconversion,
-                   "conversion from %qT to %qT discards imaginary component",
-                   expr_type, type);
-      else
-       {
-         int warnopt;
-         if (conversion_kind == UNSAFE_REAL)
-           warnopt = OPT_Wfloat_conversion;
-         else if (conversion_kind)
-           warnopt = OPT_Wconversion;
-         else
-           break;
+      {
+       int warnopt;
+       if (conversion_kind == UNSAFE_REAL)
+         warnopt = OPT_Wfloat_conversion;
+       else if (conversion_kind == UNSAFE_SIGN)
+         warnopt = OPT_Wsign_conversion;
+       else if (conversion_kind)
+         warnopt = OPT_Wconversion;
+       else
+         break;
+       if (conversion_kind == UNSAFE_SIGN)
+         warning_at (loc, warnopt, "conversion to %qT from %qT "
+                     "may change the sign of the result",
+                     type, expr_type);
+       else if (conversion_kind == UNSAFE_IMAGINARY)
+         warning_at (loc, warnopt,
+                     "conversion from %qT to %qT discards imaginary component",
+                     expr_type, type);
+       else
          warning_at (loc, warnopt,
                      "conversion from %qT to %qT may change value",
                      expr_type, type);
-       }
+      }
     }
 }