]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c-family: Tweak -Woverflow diagnostic
authorMarek Polacek <polacek@redhat.com>
Wed, 30 Mar 2022 20:59:33 +0000 (16:59 -0400)
committerMarek Polacek <polacek@redhat.com>
Wed, 4 May 2022 20:10:09 +0000 (16:10 -0400)
When g++ emits

warning: overflow in conversion from 'int' to 'char' changes value from '300' to '',''

for code like "char c = 300;" it might raise a few eyebrows.  With this
warning we're not interested in the ASCII representation of the char, only
the numerical value, so convert constants of type char to int.  It looks
like this conversion only needs to be done for char_type_node.

gcc/c-family/ChangeLog:

* c-warn.cc (warnings_for_convert_and_check): Convert constants of type
char to int.

gcc/testsuite/ChangeLog:

* c-c++-common/Wconversion-1.c: New test.

gcc/c-family/c-warn.cc
gcc/testsuite/c-c++-common/Wconversion-1.c [new file with mode: 0644]

index f24ac5d05394ac84de6f4d324ec6f7c613326135..cae89294aea124159f38b84de5f95742a8cc869b 100644 (file)
@@ -1404,8 +1404,14 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr,
     result = TREE_OPERAND (result, 1);
 
   bool cst = TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant;
-
   tree exprtype = TREE_TYPE (expr);
+  tree result_diag;
+  /* We're interested in the actual numerical value here, not its ASCII
+     representation.  */
+  if (cst && TYPE_MAIN_VARIANT (TREE_TYPE (result)) == char_type_node)
+    result_diag = fold_convert (integer_type_node, result);
+  else
+    result_diag = result;
 
   if (TREE_CODE (expr) == INTEGER_CST
       && (TREE_CODE (type) == INTEGER_TYPE
@@ -1430,7 +1436,7 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr,
                                  "changes value from %qE to %qE")
                             : G_("unsigned conversion from %qT to %qT "
                                  "changes value from %qE to %qE")),
-                           exprtype, type, expr, result);
+                           exprtype, type, expr, result_diag);
              else
                warning_at (loc, OPT_Woverflow,
                            (TYPE_UNSIGNED (exprtype)
@@ -1449,7 +1455,7 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr,
            warning_at (loc, OPT_Woverflow,
                        "overflow in conversion from %qT to %qT "
                        "changes value from %qE to %qE",
-                       exprtype, type, expr, result);
+                       exprtype, type, expr, result_diag);
          else
            warning_at (loc, OPT_Woverflow,
                        "overflow in conversion from %qT to %qT "
@@ -1466,7 +1472,7 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr,
            warning_at (loc, OPT_Woverflow,
                        "overflow in conversion from %qT to %qT "
                        "changes value from %qE to %qE",
-                       exprtype, type, expr, result);
+                       exprtype, type, expr, result_diag);
          else
            warning_at (loc, OPT_Woverflow,
                        "overflow in conversion from %qT to %qT "
@@ -1483,7 +1489,7 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr,
        warning_at (loc, OPT_Woverflow,
                    "overflow in conversion from %qT to %qT "
                    "changes value from %qE to %qE",
-                   exprtype, type, expr, result);
+                   exprtype, type, expr, result_diag);
       else
        warning_at (loc, OPT_Woverflow,
                    "overflow in conversion from %qT to %qT "
diff --git a/gcc/testsuite/c-c++-common/Wconversion-1.c b/gcc/testsuite/c-c++-common/Wconversion-1.c
new file mode 100644 (file)
index 0000000..ed65918
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-Wconversion" } */
+
+typedef char T;
+
+void g()
+{
+  char c = 300; /* { dg-warning "conversion from .int. to .char. changes value from .300. to .44." } */
+  T t = 300; /* { dg-warning "conversion from .int. to .T. {aka .char.} changes value from .300. to .44." } */
+  signed char sc = 300; /* { dg-warning "conversion from .int. to .signed char. changes value from .300. to .44." } */
+  unsigned char uc = 300; /* { dg-warning "conversion from .int. to .unsigned char. changes value from .300. to .44." } */
+  unsigned char uc2 = 300u; /* { dg-warning "conversion from .unsigned int. to .unsigned char. changes value from .300. to .44." } */
+  char c2 = (double)1.0 + 200; /* { dg-warning "overflow in conversion from .double. to .char. changes value from .2.01e\\+2. to .127." } */
+}