aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2022-03-30 16:59:33 -0400
committerMarek Polacek <polacek@redhat.com>2022-05-04 16:10:09 -0400
commit1cd3faf5dddb3cbfa2ed308ecf3db4f70bff337e (patch)
tree1342bb9e55c0fdfc47b5370c4af01ed3ffb566ee
parenta733dea9e7c39352ce9f72059938833eaa819467 (diff)
downloadgcc-1cd3faf5dddb3cbfa2ed308ecf3db4f70bff337e.zip
gcc-1cd3faf5dddb3cbfa2ed308ecf3db4f70bff337e.tar.gz
gcc-1cd3faf5dddb3cbfa2ed308ecf3db4f70bff337e.tar.bz2
c-family: Tweak -Woverflow diagnostic
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.
-rw-r--r--gcc/c-family/c-warn.cc16
-rw-r--r--gcc/testsuite/c-c++-common/Wconversion-1.c14
2 files changed, 25 insertions, 5 deletions
diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc
index f24ac5d..cae8929 100644
--- a/gcc/c-family/c-warn.cc
+++ b/gcc/c-family/c-warn.cc
@@ -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
index 0000000..ed65918
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wconversion-1.c
@@ -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." } */
+}