PATCH: Wconversion-sign (try 4, I think)

Manuel López-Ibáñez lopezibanez@gmail.com
Wed Mar 21 21:04:00 GMT 2007


:ADDPATCH diagnostics:

New version of the Wconversion-sign patch. See
http://gcc.gnu.org/ml/gcc-patches/2007-03/msg01217.html for more
details.

This version works as follows:

* For C, Wconversion enables Wconversion-sign unless
Wno-conversion-sign is given.
* For C++, Wconversion does not enable Wconversion-sign, it needs to
be requested explicitly.

Bootstrapped and regression tested.

OK for mainline?


2007-03-21  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

  * doc/invoke.texi (Warning Options): Add -Wconversion-sign.
 (Wconversion): Update description.
 (Wconversion-sign): New.
 * c.opt (Wconversion-sign): New.
 * c-opts.c (c_common_post_options): Uninitialized Wconversion-sign
means disabled for C++. Otherwise, take the status of Wconversion.
 * c-common.c (conversion_warning): Warn with either Wconversion or
Wconversion-sign.
 (warnings_for_convert_and_check): Conditions are already checked by
conversion_warning.
 (convert_and_check): Don't check warnings if the conversion failed.

cp/
 * cvt.c (cp_convert_and_check): Don't check warnings if the conversion failed.

testsuite/
 * gcc.dg/Wconversion-integer.c: Group testcases and add more.
 * gcc.dg/Wconversion-sign.c: New.
 * gcc.dg/Wconversion-integer-no-sign.c: New.
 * g++.dg/warn/Wconversion-integer.C: Move some warnings to Wconversion-sign.C
 * g++.dg/warn/Wconversion-sign.C: New.
 * g++.old-deja/g++.other/warn4.C: Update.
 * g++.dg/warn/Wconversion1.C: Likewise.
-------------- next part --------------
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 123028)
+++ gcc/doc/invoke.texi	(working copy)
@@ -227,7 +227,7 @@ Objective-C and Objective-C++ Dialects}.
 -w  -Wextra  -Wall  -Waddress  -Waggregate-return -Warray-bounds @gol
 -Wno-attributes -Wc++-compat -Wc++0x-compat -Wcast-align  -Wcast-qual  @gol
 -Wchar-subscripts -Wclobbered  -Wcomment @gol
--Wconversion -Wcoverage-mismatch -Wno-deprecated-declarations @gol
+-Wconversion  -Wconversion-sign  -Wcoverage-mismatch  -Wno-deprecated-declarations @gol
 -Wdisabled-optimization  -Wno-div-by-zero  @gol
 -Wempty-body  -Wno-endif-labels @gol
 -Werror  -Werror=* @gol
@@ -3388,19 +3388,32 @@ Warn for variables that might be changed
 
 @item -Wconversion
 @opindex Wconversion
+@opindex Wno-conversion
 Warn for implicit conversions that may alter a value. This includes
 conversions between real and integer, like @code{abs (x)} when
 @code{x} is @code{double}; conversions between signed and unsigned,
 like @code{unsigned ui = -1}; and conversions to smaller types, like
 @code{sqrtf (M_PI)}. Do not warn for explicit casts like @code{abs
 ((int) x)} and @code{ui = (unsigned) -1}, or if the value is not
-changed by the conversion like in @code{abs (2.0)}.
+changed by the conversion like in @code{abs (2.0)}.  Warnings about
+conversions between signed and unsigned integers can be disabled by
+using @option{-Wno-conversion-sign}.
 
 For C++, also warn for conversions between @code{NULL} and non-pointer
 types; confusing overload resolution for user-defined conversions; and
 conversions that will never use a type conversion operator:
 conversions to @code{void}, the same type, a base class or a reference
-to them.
+to them. Warnings about conversions between signed and unsigned
+integers are disabled by default in C++ unless
+@option{-Wconversion-sign} is explicitly enabled.
+
+@item -Wconversion-sign
+@opindex Wconversion-sign
+@opindex Wno-conversion-sign
+Warn for implicit conversions that may change the sign of an integer
+value, like assigning a signed integer expression to an unsigned
+integer variable. An explicit cast silences the warning. In C, this
+option is enabled also by @option{-Wconversion}.
 
 @item -Wempty-body
 @opindex Wempty-body
Index: gcc/testsuite/gcc.dg/Wconversion-integer.c
===================================================================
--- gcc/testsuite/gcc.dg/Wconversion-integer.c	(revision 123028)
+++ gcc/testsuite/gcc.dg/Wconversion-integer.c	(working copy)
@@ -18,25 +18,34 @@ void h (int x)
   unsigned char uc = 3;
   signed char   sc = 3;
 
-  fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  uc = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  fuc ('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  uc = x ? 1U : -1; /* { dg-warning "conversion" } */
-  /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 25 } */
-  uc = x ? SCHAR_MIN : 1U; /* { dg-warning "conversion" } */
-  /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 27 } */
-
-  uc = x ? 1 : -1; /* { dg-warning "conversion" } */
-
-  uc = x ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
+  uc = ui; /* { dg-warning "conversion" } */
+  uc = si; /* { dg-warning "conversion" } */
+  sc = ui; /* { dg-warning "conversion" } */
+  sc = si; /* { dg-warning "conversion" } */
+  fuc (ui); /* { dg-warning "conversion" } */
+  fuc (si); /* { dg-warning "conversion" } */
+  fsc (ui); /* { dg-warning "conversion" } */
+  fsc (si); /* { dg-warning "conversion" } */
 
+  fsi (si);
+  fui (ui);
+  fsi (uc);
+  si = uc;
+  fui (uc);
+  ui = uc;
+  fui ('A');
+  ui = 'A';
+  fsi ('A');
+  si = 'A';
   fuc ('A');
   uc = 'A';
-  uc = (unsigned char) -1;
 
-  fui (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  ui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = x ? 1U : -1; /* { dg-warning "conversion" } */
+  /* { 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" } */
   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" } */
@@ -45,34 +54,17 @@ void h (int x)
   ui = x ? 1 : -1; /* { dg-warning "conversion" } */
   ui = ui ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
 
-  ui = -1 * (1 * -1);
-  ui = (unsigned) -1;
-
-  fsc (uc); /* { dg-warning "conversion" } */
-  sc = uc;  /* { dg-warning "conversion" } */
-  fuc (sc); /* { dg-warning "conversion" } */
-  uc = sc;  /* { dg-warning "conversion" } */
-  fsi (ui); /* { dg-warning "conversion" } */
-  si = ui;  /* { dg-warning "conversion" } */
-  fui (si); /* { dg-warning "conversion" } */ 
-  ui = si;  /* { dg-warning "conversion" } */ 
-  fui (sc); /* { dg-warning "conversion" } */
-  ui = sc;  /* { dg-warning "conversion" } */
-
+  fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = -1;  /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fui (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fuc ('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
   fui ('\xa0');/* { dg-warning "negative integer implicitly converted to unsigned type" } */
   ui = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fsi (0x80000000); /* { dg-warning "conversion" } */
+  si = 0x80000000;  /* { dg-warning "conversion" } */
 
-  fsi (si);
-  fui (ui);
-  fsi (uc);
-  si = uc;
-  fui (uc);
-  ui = uc;
-  fui ('A');
-  ui = 'A';
-  fsi ('A');
-  si = 'A';
-  
 
   fsi (UINT_MAX - 1);  /* { dg-warning "conversion" } */
   si = UINT_MAX - 1;   /* { dg-warning "conversion" } */
@@ -85,10 +77,21 @@ void h (int x)
   fui (UINT_MAX - 1);
   ui = UINT_MAX - 1;
 
-  fsi (0x80000000); /* { dg-warning "conversion" } */
-  si = 0x80000000;  /* { dg-warning "conversion" } */
-}
+  uc = (unsigned char) -1;
+  ui = -1 * (1 * -1);
+  ui = (unsigned) -1;
 
+  fsc (uc); /* { dg-warning "conversion" } */
+  sc = uc;  /* { dg-warning "conversion" } */
+  fuc (sc); /* { dg-warning "conversion" } */
+  uc = sc;  /* { dg-warning "conversion" } */
+  fsi (ui); /* { dg-warning "conversion" } */
+  si = ui;  /* { dg-warning "conversion" } */
+  fui (si); /* { dg-warning "conversion" } */ 
+  ui = si;  /* { dg-warning "conversion" } */ 
+  fui (sc); /* { dg-warning "conversion" } */
+  ui = sc;  /* { dg-warning "conversion" } */
+}
 
 unsigned fui (unsigned a) { return a + -1; } /* { dg-warning "negative integer implicitly converted to unsigned type" } */
 
Index: gcc/testsuite/gcc.dg/Wconversion-sign.c
===================================================================
--- gcc/testsuite/gcc.dg/Wconversion-sign.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wconversion-sign.c	(revision 0)
@@ -0,0 +1,96 @@
+/* Test for diagnostics for implicit conversions between signed and
+   unsigned integer types.
+   These tests come from gcc/testsuite/gcc.dg/overflow-warn-2.c  */
+
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -fsigned-char -Wconversion-sign" } */
+#include <limits.h>
+
+void fsc (signed char sc);
+void fuc (unsigned char uc);
+unsigned fui (unsigned int  ui);
+void fsi (signed int ui);
+
+void h (int x)
+{
+  unsigned int ui = 3;
+  int   si = 3;
+  unsigned char uc = 3;
+  signed char   sc = 3;
+
+  uc = ui; 
+  uc = si; 
+  sc = ui; 
+  sc = si; 
+  fuc (ui);
+  fuc (si);
+  fsc (ui);
+  fsc (si);
+
+  fsi (si);
+  fui (ui);
+  fsi (uc);
+  si = uc;
+  fui (uc);
+  ui = uc;
+  fui ('A');
+  ui = 'A';
+  fsi ('A');
+  si = 'A';
+  fuc ('A');
+  uc = 'A';
+
+  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; 
+  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" } */
+
+  fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = -1;  /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fui (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fuc ('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fui ('\xa0');/* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fsi (0x80000000); /* { dg-warning "conversion" } */
+  si = 0x80000000;  /* { dg-warning "conversion" } */
+
+
+  fsi (UINT_MAX - 1);  /* { dg-warning "conversion" } */
+  si = UINT_MAX - 1;   /* { dg-warning "conversion" } */
+  fsi (UINT_MAX - 1U); /* { dg-warning "conversion" } */
+  si = UINT_MAX - 1U;  /* { dg-warning "conversion" } */
+  fsi (UINT_MAX/3U);
+  si = UINT_MAX/3U;
+  fsi (UINT_MAX/3);
+  si = UINT_MAX/3;
+  fui (UINT_MAX - 1);
+  ui = UINT_MAX - 1;
+
+  uc = (unsigned char) -1;
+  ui = -1 * (1 * -1);
+  ui = (unsigned) -1;
+
+  fsc (uc); /* { dg-warning "conversion" } */
+  sc = uc;  /* { dg-warning "conversion" } */
+  fuc (sc); /* { dg-warning "conversion" } */
+  uc = sc;  /* { dg-warning "conversion" } */
+  fsi (ui); /* { dg-warning "conversion" } */
+  si = ui;  /* { dg-warning "conversion" } */
+  fui (si); /* { dg-warning "conversion" } */ 
+  ui = si;  /* { dg-warning "conversion" } */ 
+  fui (sc); /* { dg-warning "conversion" } */
+  ui = sc;  /* { dg-warning "conversion" } */
+}
+
+unsigned fui (unsigned a) { return a + -1; } /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+
+
Index: gcc/testsuite/gcc.dg/Wconversion-integer-no-sign.c
===================================================================
--- gcc/testsuite/gcc.dg/Wconversion-integer-no-sign.c	(revision 0)
+++ gcc/testsuite/gcc.dg/Wconversion-integer-no-sign.c	(revision 0)
@@ -0,0 +1,96 @@
+/* Test for diagnostics for implicit conversions between integer types
+   These tests come from gcc/testsuite/gcc.dg/overflow-warn-2.c  */
+
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -fsigned-char -Wconversion -Wno-conversion-sign" } */
+
+#include <limits.h>
+
+void fsc (signed char sc);
+void fuc (unsigned char uc);
+unsigned fui (unsigned int  ui);
+void fsi (signed int ui);
+
+void h (int x)
+{
+  unsigned int ui = 3;
+  int   si = 3;
+  unsigned char uc = 3;
+  signed char   sc = 3;
+
+  uc = ui; /* { dg-warning "conversion" } */
+  uc = si; /* { dg-warning "conversion" } */
+  sc = ui; /* { dg-warning "conversion" } */
+  sc = si; /* { dg-warning "conversion" } */
+  fuc (ui); /* { dg-warning "conversion" } */
+  fuc (si); /* { dg-warning "conversion" } */
+  fsc (ui); /* { dg-warning "conversion" } */
+  fsc (si); /* { dg-warning "conversion" } */
+
+  fsi (si);
+  fui (ui);
+  fsi (uc);
+  si = uc;
+  fui (uc);
+  ui = uc;
+  fui ('A');
+  ui = 'A';
+  fsi ('A');
+  si = 'A';
+  fuc ('A');
+  uc = 'A';
+
+  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" } */
+  ui = x ? 1U : -1; /* Warned by -Wconversion-sign.  */
+  ui = x ? INT_MIN : 1U; /* Warned by -Wconversion-sign.  */
+  ui = ui ? SCHAR_MIN : 1U; /* Warned by -Wconversion-sign.  */
+  ui = 1U * -1; /* Warned by -Wconversion-sign.  */
+  ui = ui + INT_MIN; /* Warned by -Wconversion-sign.  */
+  ui = x ? 1 : -1; /* Warned by -Wconversion-sign.  */
+  ui = ui ? SCHAR_MIN : 1; /* Warned by -Wconversion-sign.  */
+
+  fuc (-1); /* Warned by -Wconversion-sign.  */
+  uc = -1; /* Warned by -Wconversion-sign.  */
+  fui (-1); /* Warned by -Wconversion-sign.  */
+  ui = -1; /* Warned by -Wconversion-sign.  */
+  fuc ('\xa0'); /* Warned by -Wconversion-sign.  */
+  uc = '\xa0'; /* Warned by -Wconversion-sign.  */
+  fui ('\xa0'); /* Warned by -Wconversion-sign.  */
+  ui = '\xa0';  /* Warned by -Wconversion-sign.  */
+  fsi (0x80000000); /* Warned by -Wconversion-sign.  */
+  si = 0x80000000;  /* Warned by -Wconversion-sign.  */
+
+
+  fsi (UINT_MAX - 1);  /* Warned by -Wconversion-sign.  */
+  si = UINT_MAX - 1;   /* Warned by -Wconversion-sign.  */
+  fsi (UINT_MAX - 1U); /* Warned by -Wconversion-sign.  */
+  si = UINT_MAX - 1U;  /* Warned by -Wconversion-sign.  */
+  fsi (UINT_MAX/3U);
+  si = UINT_MAX/3U;
+  fsi (UINT_MAX/3);
+  si = UINT_MAX/3;
+  fui (UINT_MAX - 1);
+  ui = UINT_MAX - 1;
+
+  uc = (unsigned char) -1;
+  ui = -1 * (1 * -1);
+  ui = (unsigned) -1;
+
+  fsc (uc); /* Warned by -Wconversion-sign.  */
+  sc = uc;  /* Warned by -Wconversion-sign.  */
+  fuc (sc); /* Warned by -Wconversion-sign.  */
+  uc = sc;  /* Warned by -Wconversion-sign.  */
+  fsi (ui); /* Warned by -Wconversion-sign.  */
+  si = ui;  /* Warned by -Wconversion-sign.  */
+  fui (si); /* Warned by -Wconversion-sign.  */ 
+  ui = si;  /* Warned by -Wconversion-sign.  */ 
+  fui (sc); /* Warned by -Wconversion-sign.  */
+  ui = sc;  /* Warned by -Wconversion-sign.  */
+}
+
+unsigned fui (unsigned a) { return a + -1; } /* Warned by -Wconversion-sign.  */
+
+
Index: gcc/testsuite/g++.old-deja/g++.other/warn4.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.other/warn4.C	(revision 123028)
+++ gcc/testsuite/g++.old-deja/g++.other/warn4.C	(working copy)
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
-// { dg-options "-Wconversion" }
+// { dg-options "-Wconversion-sign" }
 
 // Copyright (C) 1999 Free Software Foundation, Inc.
 // Contributed by Nathan Sidwell 21 Nov 1999 <nathan@acm.org>
Index: gcc/testsuite/g++.dg/warn/Wconversion-integer.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wconversion-integer.C	(revision 123028)
+++ gcc/testsuite/g++.dg/warn/Wconversion-integer.C	(working copy)
@@ -18,49 +18,14 @@ void h (int x)
   unsigned char uc = 3;
   signed char   sc = 3;
 
-  fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  uc = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  fuc ('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  uc = x ? 1U : -1; /* { dg-warning "conversion" } */
-  /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 25 } */
-  uc = x ? SCHAR_MIN : 1U; /* { dg-warning "conversion" } */
-  /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 27 } */
-
-  uc = x ? 1 : -1; /* { dg-warning "conversion" } */
-
-  uc = x ? SCHAR_MIN : 1; /* { dg-warning "conversion" } */
-
-  fuc ('A');
-  uc = 'A';
-  uc = (unsigned char) -1;
-
-  fui (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  ui = -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 = -1 * (1 * -1);
-  ui = (unsigned) -1;
-
-  fsc (uc); /* { dg-warning "conversion" } */
-  sc = uc;  /* { dg-warning "conversion" } */
-  fuc (sc); /* { dg-warning "conversion" } */
-  uc = sc;  /* { dg-warning "conversion" } */
-  fsi (ui); /* { dg-warning "conversion" } */
-  si = ui;  /* { dg-warning "conversion" } */
-  fui (si); /* { dg-warning "conversion" } */ 
-  ui = si;  /* { dg-warning "conversion" } */ 
-  fui (sc); /* { dg-warning "conversion" } */
-  ui = sc;  /* { dg-warning "conversion" } */
-
-  fui ('\xa0');/* { dg-warning "negative integer implicitly converted to unsigned type" } */
-  ui = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = ui; /* { dg-warning "conversion" } */
+  uc = si; /* { dg-warning "conversion" } */
+  sc = ui; /* { dg-warning "conversion" } */
+  sc = si; /* { dg-warning "conversion" } */
+  fuc (ui); /* { dg-warning "conversion" } */
+  fuc (si); /* { dg-warning "conversion" } */
+  fsc (ui); /* { dg-warning "conversion" } */
+  fsc (si); /* { dg-warning "conversion" } */
 
   fsi (si);
   fui (ui);
@@ -72,12 +37,37 @@ void h (int x)
   ui = 'A';
   fsi ('A');
   si = 'A';
-  
+  fuc ('A');
+  uc = 'A';
 
-  fsi (UINT_MAX - 1);  /* { dg-warning "conversion" } */
-  si = UINT_MAX - 1;   /* { dg-warning "conversion" } */
-  fsi (UINT_MAX - 1U); /* { dg-warning "conversion" } */
-  si = UINT_MAX - 1U;  /* { dg-warning "conversion" } */
+  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" } */
+  ui = x ? 1U : -1; /* Warned by -Wconversion-sign.  */
+  ui = x ? INT_MIN : 1U; /* Warned by -Wconversion-sign.  */
+  ui = ui ? SCHAR_MIN : 1U; /* Warned by -Wconversion-sign.  */
+  ui = 1U * -1; /* Warned by -Wconversion-sign.  */
+  ui = ui + INT_MIN; /* Warned by -Wconversion-sign.  */
+  ui = x ? 1 : -1; /* Warned by -Wconversion-sign.  */
+  ui = ui ? SCHAR_MIN : 1; /* Warned by -Wconversion-sign.  */
+
+  fuc (-1); /* Warned by -Wconversion-sign.  */
+  uc = -1; /* Warned by -Wconversion-sign.  */
+  fui (-1); /* Warned by -Wconversion-sign.  */
+  ui = -1; /* Warned by -Wconversion-sign.  */
+  fuc ('\xa0'); /* Warned by -Wconversion-sign.  */
+  uc = '\xa0'; /* Warned by -Wconversion-sign.  */
+  fui ('\xa0'); /* Warned by -Wconversion-sign.  */
+  ui = '\xa0';  /* Warned by -Wconversion-sign.  */
+  fsi (0x80000000); /* Warned by -Wconversion-sign.  */
+  si = 0x80000000;  /* Warned by -Wconversion-sign.  */
+
+
+  fsi (UINT_MAX - 1);  /* Warned by -Wconversion-sign.  */
+  si = UINT_MAX - 1;   /* Warned by -Wconversion-sign.  */
+  fsi (UINT_MAX - 1U); /* Warned by -Wconversion-sign.  */
+  si = UINT_MAX - 1U;  /* Warned by -Wconversion-sign.  */
   fsi (UINT_MAX/3U);
   si = UINT_MAX/3U;
   fsi (UINT_MAX/3);
@@ -85,11 +75,20 @@ void h (int x)
   fui (UINT_MAX - 1);
   ui = UINT_MAX - 1;
 
-  fsi (0x80000000); /* { dg-warning "conversion" } */
-  si = 0x80000000;  /* { dg-warning "conversion" } */
-}
-
-
-unsigned fui (unsigned a) { return a + -1; } /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = (unsigned char) -1;
+  ui = -1 * (1 * -1);
+  ui = (unsigned) -1;
 
+  fsc (uc); /* Warned by -Wconversion-sign.  */
+  sc = uc;  /* Warned by -Wconversion-sign.  */
+  fuc (sc); /* Warned by -Wconversion-sign.  */
+  uc = sc;  /* Warned by -Wconversion-sign.  */
+  fsi (ui); /* Warned by -Wconversion-sign.  */
+  si = ui;  /* Warned by -Wconversion-sign.  */
+  fui (si); /* Warned by -Wconversion-sign.  */ 
+  ui = si;  /* Warned by -Wconversion-sign.  */ 
+  fui (sc); /* Warned by -Wconversion-sign.  */
+  ui = sc;  /* Warned by -Wconversion-sign.  */
+}
 
+unsigned fui (unsigned a) { return a + -1; } /* Warned by -Wconversion-sign.  */
Index: gcc/testsuite/g++.dg/warn/Wconversion1.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wconversion1.C	(revision 123028)
+++ gcc/testsuite/g++.dg/warn/Wconversion1.C	(working copy)
@@ -1,4 +1,4 @@
-// { dg-options "-fsigned-char -Wconversion" }
+// { dg-options "-fsigned-char -Wconversion-sign" }
 
 char c1 = 1024; // { dg-warning "overflow" }
 char c2 = char(1024);
Index: gcc/testsuite/g++.dg/warn/Wconversion-sign.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wconversion-sign.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wconversion-sign.C	(revision 0)
@@ -0,0 +1,95 @@
+/* Test for diagnostics for implicit conversions between signed and
+   unsigned integer types.
+   C++ equivalent of gcc/testsuite/gcc.dg/Wconversion-sign.c  */
+
+// { dg-do compile } 
+// { dg-options "-fsigned-char -Wconversion-sign" } 
+#include <limits.h>
+
+void fsc (signed char sc);
+void fuc (unsigned char uc);
+unsigned fui (unsigned int  ui);
+void fsi (signed int ui);
+
+void h (int x)
+{
+  unsigned int ui = 3;
+  int   si = 3;
+  unsigned char uc = 3;
+  signed char   sc = 3;
+
+  uc = ui; 
+  uc = si; 
+  sc = ui; 
+  sc = si; 
+  fuc (ui);
+  fuc (si);
+  fsc (ui);
+  fsc (si);
+
+  fsi (si);
+  fui (ui);
+  fsi (uc);
+  si = uc;
+  fui (uc);
+  ui = uc;
+  fui ('A');
+  ui = 'A';
+  fsi ('A');
+  si = 'A';
+  fuc ('A');
+  uc = 'A';
+
+  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; 
+  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" } */
+
+  fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = -1;  /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fui (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fuc ('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fui ('\xa0');/* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  ui = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+  fsi (0x80000000); /* { dg-warning "conversion" } */
+  si = 0x80000000;  /* { dg-warning "conversion" } */
+
+
+  fsi (UINT_MAX - 1);  /* { dg-warning "conversion" } */
+  si = UINT_MAX - 1;   /* { dg-warning "conversion" } */
+  fsi (UINT_MAX - 1U); /* { dg-warning "conversion" } */
+  si = UINT_MAX - 1U;  /* { dg-warning "conversion" } */
+  fsi (UINT_MAX/3U);
+  si = UINT_MAX/3U;
+  fsi (UINT_MAX/3);
+  si = UINT_MAX/3;
+  fui (UINT_MAX - 1);
+  ui = UINT_MAX - 1;
+
+  uc = (unsigned char) -1;
+  ui = -1 * (1 * -1);
+  ui = (unsigned) -1;
+
+  fsc (uc); /* { dg-warning "conversion" } */
+  sc = uc;  /* { dg-warning "conversion" } */
+  fuc (sc); /* { dg-warning "conversion" } */
+  uc = sc;  /* { dg-warning "conversion" } */
+  fsi (ui); /* { dg-warning "conversion" } */
+  si = ui;  /* { dg-warning "conversion" } */
+  fui (si); /* { dg-warning "conversion" } */ 
+  ui = si;  /* { dg-warning "conversion" } */ 
+  fui (sc); /* { dg-warning "conversion" } */
+  ui = sc;  /* { dg-warning "conversion" } */
+}
+
+unsigned fui (unsigned a) { return a + -1; } /* { dg-warning "negative integer implicitly converted to unsigned type" } */
+
Index: gcc/cp/cvt.c
===================================================================
--- gcc/cp/cvt.c	(revision 123028)
+++ gcc/cp/cvt.c	(working copy)
@@ -610,7 +610,7 @@ cp_convert_and_check (tree type, tree ex
   
   result = cp_convert (type, expr);
 
-  if (!skip_evaluation && !TREE_OVERFLOW_P (expr))
+  if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node)
     warnings_for_convert_and_check (type, expr, result);
 
   return result;
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 123028)
+++ gcc/c.opt	(working copy)
@@ -164,6 +164,10 @@ Wconversion
 C ObjC C++ ObjC++ Var(warn_conversion) Warning
 Warn for implicit type conversions that may change a value
 
+Wconversion-sign
+C ObjC C++ ObjC++ Var(warn_conversion_sign) Init(-1)
+Warn for implicit type conversions between signed and unsigned integers
+
 Wctor-dtor-privacy
 C++ ObjC++ Var(warn_ctor_dtor_privacy) Warning
 Warn when all constructors and destructors are private
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c	(revision 123028)
+++ gcc/c-opts.c	(working copy)
@@ -1092,7 +1092,14 @@ c_common_post_options (const char **pfil
 	}
       if (flag_inline_functions)
 	flag_inline_trees = 2;
-    }
+    } 
+
+  /* In C, -Wconversion enables -Wconversion-sign (unless disabled
+     through -Wno-conversion-sign). While in C++,
+     -Wconversion-sign needs to be requested explicitly.  */
+  if (warn_conversion_sign == -1)
+    warn_conversion_sign =  (c_dialect_cxx ()) ? 0 : warn_conversion;
+
 
   /* Special format checking options don't work without -Wformat; warn if
      they are used.  */
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 123028)
+++ gcc/c-common.c	(working copy)
@@ -1177,6 +1177,9 @@ conversion_warning (tree type, tree expr
 
   unsigned int formal_prec = TYPE_PRECISION (type);
 
+  if (!warn_conversion && !warn_conversion_sign)
+    return;
+
   if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
     {
       /* Warn for real constant that is not an exact integer converted
@@ -1193,10 +1196,13 @@ conversion_warning (tree type, tree expr
                && !int_fits_type_p (expr, type))
         {
           if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))
-            warning (OPT_Wconversion,
-                     "negative integer implicitly converted to unsigned type");
-          else
-            give_warning = true;
+	    warning (OPT_Wconversion_sign,
+		     "negative integer implicitly converted to unsigned type");
+          else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (TREE_TYPE (expr)))
+	    warning (OPT_Wconversion_sign,
+		     "conversion of unsigned constant value to negative integer");
+	  else
+	    give_warning = true;
         }
       else if (TREE_CODE (type) == REAL_TYPE)
         {
@@ -1234,16 +1240,20 @@ conversion_warning (tree type, tree expr
                && TREE_CODE (type) == INTEGER_TYPE)
         {
           /* Warn for integer types converted to smaller integer types.  */
-          if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr))
-              /* When they are the same width but different signedness,
-                 then the value may change.  */
-              || (formal_prec == TYPE_PRECISION (TREE_TYPE (expr))
-                  && TYPE_UNSIGNED (TREE_TYPE (expr)) != 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 (TREE_TYPE (expr))))
-            give_warning = true;
+          if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr))) 
+	    give_warning = true;
+
+	  /* When they are the same width but different signedness,
+	     then the value may change.  */
+	  else if ((formal_prec == TYPE_PRECISION (TREE_TYPE (expr))
+		    && TYPE_UNSIGNED (TREE_TYPE (expr)) != 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 (TREE_TYPE (expr))))
+	    warning (OPT_Wconversion_sign,
+		     "conversion to %qT from %qT may change the sign of the result",
+		     type, TREE_TYPE (expr));
         }
 
       /* Warn for integer types converted to real types if and only if
@@ -1300,7 +1310,7 @@ warnings_for_convert_and_check (tree typ
           if (!int_fits_type_p (expr, c_common_signed_type (type)))
             warning (OPT_Woverflow,
                      "large integer implicitly truncated to unsigned type");
-          else if (warn_conversion)
+          else
             conversion_warning (type, expr);
         }
       else if (!int_fits_type_p (expr, c_common_unsigned_type (type))) 
@@ -1314,13 +1324,13 @@ warnings_for_convert_and_check (tree typ
 	warning (OPT_Woverflow,
 		 "overflow in implicit constant conversion");
 
-      else if (warn_conversion)
+      else
 	conversion_warning (type, expr);
     }
   else if (TREE_CODE (result) == INTEGER_CST && TREE_OVERFLOW (result)) 
     warning (OPT_Woverflow,
              "overflow in implicit constant conversion");
-  else if (warn_conversion)
+  else
     conversion_warning (type, expr);
 }
 
@@ -1339,7 +1349,7 @@ convert_and_check (tree type, tree expr)
   
   result = convert (type, expr);
 
-  if (!skip_evaluation && !TREE_OVERFLOW_P (expr))
+  if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node)
     warnings_for_convert_and_check (type, expr, result);
 
   return result;


More information about the Gcc-patches mailing list