This patch is an improved version over the one proposed in http://gcc.gnu.org/ml/gcc-patches/2006-07/msg00098.html It doesn't introduce any features. The main difference is the removal of TREE_CONSTANT_OVERFLOW check from real_isinteger function, following the new policy about not handling overflow in the front end. This patch also fixes some minor issues with whitespace and comments. Thanks to Roger Sayle for his helpful comments.
Bootstrapped and tested in trunk revision 115112. As the original one, it is composed by three patches: wcoercion-1of3-split.patch : splits current functionality of Wconversion in two different options and it modifies testcases accordingly. (this one hasn't changed at all, it is included here for completeness) wcoercion-2of3-real_isinteger-2.patch : adds a new function which detects when a real value can be exactly represented as an integer. wcoercion-3of3-coercion_warning-2.patch : adds the new functionality and testcases.
diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/c-common.c wcoercion/gcc/c-common.c --- pristine/gcc/c-common.c 2006-07-01 13:37:45.000000000 +0100 +++ wcoercion/gcc/c-common.c 2006-07-01 13:40:44.000000000 +0100 @@ -949,7 +949,7 @@ overflow_warning (tree value) } /* Print a warning if a large constant is truncated to unsigned, - or if -Wconversion is used and a constant < 0 is converted to unsigned. + or if -Wcoercion is used and a constant < 0 is converted to unsigned. Invoke this function on every expression that might be implicitly converted to an unsigned type. */ @@ -969,7 +969,7 @@ unsigned_conversion_warning (tree result warning (OPT_Woverflow, "large integer implicitly truncated to unsigned type"); else - warning (OPT_Wconversion, + warning (OPT_Wcoercion, "negative integer implicitly converted to unsigned type"); } } diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/c.opt wcoercion/gcc/c.opt --- pristine/gcc/c.opt 2006-06-04 09:53:03.000000000 +0100 +++ wcoercion/gcc/c.opt 2006-06-25 20:33:21.000000000 +0100 @@ -141,6 +141,10 @@ Wchar-subscripts C ObjC C++ ObjC++ Var(warn_char_subscripts) Warn about subscripts whose type is \"char\" +Wcoercion +C ObjC C++ ObjC++ Var(warn_coercion) +Warn for implicit type conversions that may change a value + Wcomment C ObjC C++ ObjC++ Warn about possibly nested block comments, and C++ comments spanning more than one physical line @@ -150,8 +154,12 @@ C ObjC C++ ObjC++ Synonym for -Wcomment Wconversion -C ObjC C++ ObjC++ Var(warn_conversion) -Warn about possibly confusing type conversions +C++ ObjC++ Var(warn_conversion) +Undocumented + +Wtraditional-conversion +C ObjC Var(warn_traditional_conversion) +Warn of prototypes causing type conversions different from what would happen in the absence of prototype Wctor-dtor-privacy C++ ObjC++ Var(warn_ctor_dtor_privacy) diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/c-typeck.c wcoercion/gcc/c-typeck.c --- pristine/gcc/c-typeck.c 2006-07-01 13:38:05.000000000 +0100 +++ wcoercion/gcc/c-typeck.c 2006-07-01 13:40:43.000000000 +0100 @@ -2389,7 +2389,7 @@ convert_arguments (tree typelist, tree v { /* Optionally warn about conversions that differ from the default conversions. */ - if (warn_conversion || warn_traditional) + if (warn_traditional_conversion || warn_traditional) { unsigned int formal_prec = TYPE_PRECISION (type); @@ -2465,8 +2465,8 @@ convert_arguments (tree typelist, tree v } /* Detect integer changing in width or signedness. These warnings are only activated with - -Wconversion, not with -Wtraditional. */ - else if (warn_conversion && INTEGRAL_TYPE_P (type) + -Wtraditional-conversion, not with -Wtraditional. */ + else if (warn_traditional_conversion && INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (TREE_TYPE (val))) { tree would_have_been = default_conversion (val); @@ -2479,7 +2479,7 @@ convert_arguments (tree typelist, tree v and the actual arg is that enum type. */ ; else if (formal_prec != TYPE_PRECISION (type1)) - warning (OPT_Wconversion, "passing argument %d of %qE " + warning (OPT_Wtraditional_conversion, "passing argument %d of %qE " "with different width due to prototype", argnum, rname); else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1)) @@ -2502,11 +2502,11 @@ convert_arguments (tree typelist, tree v && TYPE_UNSIGNED (TREE_TYPE (val))) ; else if (TYPE_UNSIGNED (type)) - warning (OPT_Wconversion, "passing argument %d of %qE " + warning (OPT_Wtraditional_conversion, "passing argument %d of %qE " "as unsigned due to prototype", argnum, rname); else - warning (OPT_Wconversion, "passing argument %d of %qE " + warning (OPT_Wtraditional_conversion, "passing argument %d of %qE " "as signed due to prototype", argnum, rname); } } diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/doc/invoke.texi wcoercion/gcc/doc/invoke.texi --- pristine/gcc/doc/invoke.texi 2006-07-01 13:38:33.000000000 +0100 +++ wcoercion/gcc/doc/invoke.texi 2006-07-01 13:40:44.000000000 +0100 @@ -223,8 +223,8 @@ Objective-C and Objective-C++ Dialects}. @xref{Warning Options,,Options to Request or Suppress Warnings}. @gccoptlist{-fsyntax-only -pedantic -pedantic-errors @gol -w -Wextra -Wall -Waggregate-return -Walways-true -Wno-attributes @gol --Wc++-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment @gol --Wconversion -Wno-deprecated-declarations @gol +-Wc++-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wcoercion @gol +-Wcomment -Wtraditional-conversion -Wno-deprecated-declarations @gol -Wdisabled-optimization -Wno-div-by-zero -Wno-endif-labels @gol -Werror -Werror-* -Werror-implicit-function-declaration @gol -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 @gol @@ -3018,7 +3018,7 @@ traditional C case. Conversions by prototypes between fixed/floating point values and vice versa. The absence of these prototypes when compiling with traditional C would cause serious problems. This is a subset of the possible -conversion warnings, for the full set use @option{-Wconversion}. +conversion warnings, for the full set use @option{-Wtraditional-conversion}. @item Use of ISO C style function definitions. This warning intentionally is @@ -3106,18 +3106,23 @@ only if you have been very careful about declarations and prototypes. Otherwise, it will just be a nuisance; this is why we did not make @option{-Wall} request these warnings. [EMAIL PROTECTED] -Wconversion [EMAIL PROTECTED] Wconversion [EMAIL PROTECTED] -Wtraditional-conversion [EMAIL PROTECTED] Wtraditional-conversion Warn if a prototype causes a type conversion that is different from what would happen to the same argument in the absence of a prototype. This includes conversions of fixed point to floating and vice versa, and conversions changing the width or signedness of a fixed point argument except when the same as the default promotion. -Also, warn if a negative integer constant expression is implicitly -converted to an unsigned type. For example, warn about the assignment [EMAIL PROTECTED] = -1} if @code{x} is unsigned. But do not warn about explicit -casts like @code{(unsigned) -1}. [EMAIL PROTECTED] -Wcoercion [EMAIL PROTECTED] Wcoercion +Warn for implicit conversions that may alter a value. This includes +conversions caused by function prototypes like @code{abs(x)} when [EMAIL PROTECTED] is real and by assignments like [EMAIL PROTECTED] x = -1}. Do not warn about explicit casts like [EMAIL PROTECTED]((int)x)} and @code{x = (unsigned) -1}, or if the value is not +changed by the conversion like @code{abs(2.0)}. + @item -Wsign-compare @opindex Wsign-compare diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/doc/trouble.texi wcoercion/gcc/doc/trouble.texi --- pristine/gcc/doc/trouble.texi 2006-06-11 18:02:27.000000000 +0100 +++ wcoercion/gcc/doc/trouble.texi 2006-06-11 18:58:00.000000000 +0100 @@ -985,10 +985,10 @@ you are removing prototypes that were ma the program worked before without any prototypes, it will work again without them. [EMAIL PROTECTED] Wconversion [EMAIL PROTECTED] Wtraditional-conversion You can find all the places where this problem might occur by compiling -the program with the @option{-Wconversion} option. It prints a warning -whenever an argument is converted. +the program with the @option{-Wtraditional-conversion} option. It +prints a warning whenever an argument is converted. @item Both conversion programs can be confused if there are macro calls in and diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/builtin-protos-1.c wcoercion/gcc/testsuite/gcc.dg/builtin-protos-1.c --- pristine/gcc/testsuite/gcc.dg/builtin-protos-1.c 2006-06-15 19:07:10.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/builtin-protos-1.c 2006-06-15 18:43:03.000000000 +0100 @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options -Wconversion } */ +/* { dg-options -Wtraditional-conversion } */ int test_s (signed int x) diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/dfp/Wconversion-2.c wcoercion/gcc/testsuite/gcc.dg/dfp/Wconversion-2.c --- pristine/gcc/testsuite/gcc.dg/dfp/Wconversion-2.c 2006-06-15 19:07:10.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/dfp/Wconversion-2.c 2006-06-15 18:00:23.000000000 +0100 @@ -1,6 +1,6 @@ -/* Test messages for -Wconversion (based on gcc.dg/Wconversion-2.c). */ +/* Test messages for -Wtraditional-conversion (based on gcc.dg/Wconversion-2.c). */ /* { dg-do compile } */ -/* { dg-options "-std=gnu99 -Wconversion" } */ +/* { dg-options "-std=gnu99 -Wtraditional-conversion" } */ void fsi(signed int); void fd32(_Decimal32); diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/overflow-warn-1.c wcoercion/gcc/testsuite/gcc.dg/overflow-warn-1.c --- pristine/gcc/testsuite/gcc.dg/overflow-warn-1.c 2006-06-15 19:07:10.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/overflow-warn-1.c 2006-06-15 18:18:37.000000000 +0100 @@ -102,7 +102,7 @@ void h2i (int x) { /* For some reason, we only give certain warnings for implicit - conversions among values of the same precision with -Wconversion, + conversions among values of the same precision with -Wcoercion, while we don't give others at all. */ fsi ((unsigned)INT_MAX + 1); si = (unsigned)INT_MAX + 1; diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/overflow-warn-2.c wcoercion/gcc/testsuite/gcc.dg/overflow-warn-2.c --- pristine/gcc/testsuite/gcc.dg/overflow-warn-2.c 2006-06-04 09:53:03.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/overflow-warn-2.c 2006-06-15 18:44:28.000000000 +0100 @@ -1,7 +1,7 @@ -/* Test for diagnostics for constant overflow. Test with -Wconversion. */ +/* Test for diagnostics for constant overflow. Test with -Wtraditional-conversion. */ /* Origin: Joseph Myers <[EMAIL PROTECTED]> */ /* { dg-do compile } */ -/* { dg-options "-std=c99 -Wconversion" } */ +/* { dg-options "-std=c99 -Wtraditional-conversion" } */ #include <limits.h> @@ -82,23 +82,23 @@ void h2 (void) { fsc (SCHAR_MAX + 1); - /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" "-Wconversion" { target *-*-* } 84 } */ + /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 84 } */ fsc (SCHAR_MIN - 1); /* { dg-warning "warning: overflow in implicit constant conversion" } */ - /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" "-Wconversion" { target *-*-* } 86 } */ + /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 86 } */ fsc (UCHAR_MAX); - /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" "-Wconversion" { target *-*-* } 88 } */ + /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 88 } */ fsc (UCHAR_MAX + 1); /* { dg-warning "warning: overflow in implicit constant conversion" } */ - /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" "-Wconversion" { target *-*-* } 90 } */ - fuc (-1); /* { dg-warning "warning: negative integer implicitly converted to unsigned type" } */ - /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wconversion" { target *-*-* } 92 } */ + /* { dg-warning "warning: passing argument 1 of 'fsc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 90 } */ + fuc (-1); + /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 92 } */ fuc (UCHAR_MAX + 1); /* { dg-warning "warning: large integer implicitly truncated to unsigned type" } */ - /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wconversion" { target *-*-* } 94 } */ - fuc (SCHAR_MIN); /* { dg-warning "warning: negative integer implicitly converted to unsigned type" } */ - /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wconversion" { target *-*-* } 96 } */ + /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 94 } */ + fuc (SCHAR_MIN); + /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 96 } */ fuc (SCHAR_MIN - 1); /* { dg-warning "warning: large integer implicitly truncated to unsigned type" } */ - /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wconversion" { target *-*-* } 98 } */ + /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 98 } */ fuc (-UCHAR_MAX); /* { dg-warning "warning: large integer implicitly truncated to unsigned type" } */ - /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wconversion" { target *-*-* } 100 } */ + /* { dg-warning "warning: passing argument 1 of 'fuc' with different width due to prototype" "-Wtraditional-conversion" { target *-*-* } 100 } */ } void fui (unsigned int); @@ -111,7 +111,7 @@ void h2i (int x) { /* For some reason, we only give certain warnings for implicit - conversions among values of the same precision with -Wconversion, + conversions among values of the same precision with -Wtraditional-conversion, while we don't give others at all. */ fsi ((unsigned)INT_MAX + 1); /* { dg-warning "warning: passing argument 1 of 'fsi' as signed due to prototype" } */ si = (unsigned)INT_MAX + 1; @@ -121,12 +121,12 @@ h2i (int x) si = x ? (unsigned)INT_MAX + 2 : 1; fsi (UINT_MAX); /* { dg-warning "warning: passing argument 1 of 'fsi' as signed due to prototype" } */ si = UINT_MAX; - fui (-1); /* { dg-warning "warning: negative integer implicitly converted to unsigned type" } */ - /* { dg-warning "warning: passing argument 1 of 'fui' as unsigned due to prototype" "-Wconversion" { target *-*-* } 124 } */ - ui = -1; /* { dg-warning "warning: negative integer implicitly converted to unsigned type" } */ - ui = x ? -1 : 1U; /* { dg-warning "warning: negative integer implicitly converted to unsigned type" } */ - fui (INT_MIN); /* { dg-warning "warning: negative integer implicitly converted to unsigned type" } */ - /* { dg-warning "warning: passing argument 1 of 'fui' as unsigned due to prototype" "-Wconversion" { target *-*-* } 128 } */ - ui = INT_MIN; /* { dg-warning "warning: negative integer implicitly converted to unsigned type" } */ - ui = x ? INT_MIN : 1U; /* { dg-warning "warning: negative integer implicitly converted to unsigned type" } */ + fui (-1); + /* { dg-warning "warning: passing argument 1 of 'fui' as unsigned due to prototype" "-Wtraditional-conversion" { target *-*-* } 124 } */ + ui = -1; + ui = x ? -1 : 1U; + fui (INT_MIN); + /* { dg-warning "warning: passing argument 1 of 'fui' as unsigned due to prototype" "-Wtraditional-conversion" { target *-*-* } 128 } */ + ui = INT_MIN; + ui = x ? INT_MIN : 1U; } diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/overflow-warn-3.c wcoercion/gcc/testsuite/gcc.dg/overflow-warn-3.c --- pristine/gcc/testsuite/gcc.dg/overflow-warn-3.c 2006-06-15 19:07:10.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/overflow-warn-3.c 2006-06-15 18:20:16.000000000 +0100 @@ -109,7 +109,7 @@ void h2i (int x) { /* For some reason, we only give certain warnings for implicit - conversions among values of the same precision with -Wconversion, + conversions among values of the same precision with -Wcoercion, while we don't give others at all. */ fsi ((unsigned)INT_MAX + 1); si = (unsigned)INT_MAX + 1; diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/overflow-warn-4.c wcoercion/gcc/testsuite/gcc.dg/overflow-warn-4.c --- pristine/gcc/testsuite/gcc.dg/overflow-warn-4.c 2006-06-15 19:07:10.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/overflow-warn-4.c 2006-06-15 18:45:18.000000000 +0100 @@ -109,7 +109,7 @@ void h2i (int x) { /* For some reason, we only give certain warnings for implicit - conversions among values of the same precision with -Wconversion, + conversions among values of the same precision with -Wcoercion while we don't give others at all. */ fsi ((unsigned)INT_MAX + 1); si = (unsigned)INT_MAX + 1; diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/Wcoercion-negative-constants.c wcoercion/gcc/testsuite/gcc.dg/Wcoercion-negative-constants.c --- pristine/gcc/testsuite/gcc.dg/Wcoercion-negative-constants.c 1970-01-01 01:00:00.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/Wcoercion-negative-constants.c 2006-06-25 00:32:47.000000000 +0100 @@ -0,0 +1,59 @@ +/* Test for diagnostics for negative constants coerced to unsigned types + These tests come from gcc/testsuite/gcc.dg/overflow-warn-2.c + Origin: Manuel Lopez-Ibanez <[EMAIL PROTECTED]> */ + +/* { dg-do compile } */ +/* { dg-options "-std=c99 -Wcoercion" } */ + +#include <limits.h> + +void fuc (unsigned char); + +void hc (int x) +{ + unsigned char uc; + + fuc (-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + uc = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + uc = x ? 1U : -1; /* { dg-warning "coercion to 'unsigned char' from 'unsigned int' may alter its value" } */ + /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 18 } */ + uc = x ? SCHAR_MIN : 1U; /* { dg-warning "coercion to 'unsigned char' from 'unsigned int' may alter its value" } */ + /* { dg-warning "negative integer implicitly converted to unsigned type" "" { target *-*-* } 20 } */ + uc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + + fuc('A'); + uc = 'A'; + + uc = x ? 1 : -1; /* { dg-warning "coercion to 'unsigned char' from 'int' may alter its value" } */ + /* { dg-warning "negative integer may be implicitly converted to unsigned type" "" {xfail *-*-*} 27 } */ + uc = x ? SCHAR_MIN : 1; /* { dg-warning "coercion to 'unsigned char' from 'int' may alter its value" } */ + /* { dg-warning "negative integer may be implicitly converted to unsigned type" "" {xfail *-*-*} 29 } */ + +} + +unsigned fui (unsigned int ui); + +void hi (int x) +{ + unsigned ui; + + 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 = -1 * (1 * -1); + ui = (unsigned) -1; + + ui = x ? 1 : -1; /* { dg-warning "coercion to 'unsigned int' from 'int' may alter its value" } */ + /* { dg-warning "negative integer implicitly converted to unsigned type" "" {xfail *-*-*} 51 } */ + ui = x ? INT_MIN : 1; /* { dg-warning "coercion to 'unsigned int' from 'int' may alter its value" } */ + /* { dg-warning "negative integer implicitly converted to unsigned type" "" {xfail *-*-*} 53 } */ + ui = ui ? SCHAR_MIN : 1; /* { dg-warning "coercion to 'unsigned int' from 'int' may alter its value" } */ + /* { dg-warning "negative integer implicitly converted to unsigned type" "" {xfail *-*-*} 55 } */ +} + +unsigned fui(unsigned a) { return a + -1; } /* { dg-warning "negative integer implicitly converted to unsigned type" } */ diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/Wconversion-2.c wcoercion/gcc/testsuite/gcc.dg/Wconversion-2.c --- pristine/gcc/testsuite/gcc.dg/Wconversion-2.c 2006-06-15 19:07:10.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/Wconversion-2.c 2006-06-15 18:23:11.000000000 +0100 @@ -1,8 +1,8 @@ -/* Test messages for -Wconversion, including that they are not +/* Test messages for -Wtraditional-conversion, including that they are not pedwarns. */ /* Origin: Joseph Myers <[EMAIL PROTECTED]> */ /* { dg-do compile } */ -/* { dg-options "-std=c99 -pedantic-errors -Wconversion" } */ +/* { dg-options "-std=c99 -pedantic-errors -Wtraditional-conversion" } */ void fsc(signed char); void fsi(signed int); diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/Wconversion-3.c wcoercion/gcc/testsuite/gcc.dg/Wconversion-3.c --- pristine/gcc/testsuite/gcc.dg/Wconversion-3.c 2006-06-04 09:53:03.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/Wconversion-3.c 2006-06-04 01:01:35.000000000 +0100 @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -Wconversion" } */ +/* { dg-options "-O2 -Wcoercion" } */ unsigned f(unsigned a) { return a + -1; } /* { dg-warning "negative" } */ diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/Wconversion.c wcoercion/gcc/testsuite/gcc.dg/Wconversion.c --- pristine/gcc/testsuite/gcc.dg/Wconversion.c 2006-06-15 19:07:10.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/Wconversion.c 2006-06-15 22:12:45.000000000 +0100 @@ -5,7 +5,7 @@ not used in the appropriate place in the warning code. */ /* { dg-do compile } */ -/* { dg-options -Wconversion } */ +/* { dg-options -Wtraditional-conversion } */ typedef enum { a } __attribute__((packed)) t; void f(t x) {} diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='*~' pristine/gcc/testsuite/g++.old-deja/g++.other/warn4.C wcoercion/gcc/testsuite/g++.old-deja/g++.other/warn4.C --- pristine/gcc/testsuite/g++.old-deja/g++.other/warn4.C 2006-06-07 00:57:15.000000000 +0100 +++ wcoercion/gcc/testsuite/g++.old-deja/g++.other/warn4.C 2006-06-07 00:47:13.000000000 +0100 @@ -1,5 +1,5 @@ // { dg-do assemble } -// { dg-options "-Wconversion" } +// { dg-options "-Wcoercion" } // Copyright (C) 1999 Free Software Foundation, Inc. // Contributed by Nathan Sidwell 21 Nov 1999 <[EMAIL PROTECTED]>
diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='#*' --exclude='*~' pristine/gcc/builtins.c wcoercion/gcc/builtins.c --- pristine/gcc/builtins.c 2006-06-16 23:13:57.000000000 +0100 +++ wcoercion/gcc/builtins.c 2006-07-09 20:32:47.000000000 +0100 @@ -6654,15 +6654,7 @@ integer_valued_real_p (tree t) && integer_valued_real_p (TREE_OPERAND (t, 2)); case REAL_CST: - if (! TREE_CONSTANT_OVERFLOW (t)) - { - REAL_VALUE_TYPE c, cint; - - c = TREE_REAL_CST (t); - real_trunc (&cint, TYPE_MODE (TREE_TYPE (t)), &c); - return real_identical (&c, &cint); - } - break; + return real_isinteger (TREE_REAL_CST (t), TYPE_MODE (TREE_TYPE (t))); case NOP_EXPR: { diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='#*' --exclude='*~' pristine/gcc/real.c wcoercion/gcc/real.c --- pristine/gcc/real.c 2006-06-12 22:37:50.000000000 +0100 +++ wcoercion/gcc/real.c 2006-07-09 20:32:47.000000000 +0100 @@ -4922,3 +4922,13 @@ real_copysign (REAL_VALUE_TYPE *r, const r->sign = x->sign; } +/* Check whether the real constant value given is an integer. */ + +bool +real_isinteger (const REAL_VALUE_TYPE c, enum machine_mode mode) +{ + REAL_VALUE_TYPE cint; + + real_trunc (&cint, mode, &c); + return real_identical (&c, &cint); +} diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='#*' --exclude='*~' pristine/gcc/real.h wcoercion/gcc/real.h --- pristine/gcc/real.h 2006-06-12 22:37:50.000000000 +0100 +++ wcoercion/gcc/real.h 2006-07-09 20:47:47.000000000 +0100 @@ -425,4 +425,7 @@ extern void real_round (REAL_VALUE_TYPE /* Set the sign of R to the sign of X. */ extern void real_copysign (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *); +/* Check whether the real constant value given is an integer. */ +extern bool real_isinteger (const REAL_VALUE_TYPE c, enum machine_mode mode); + #endif /* ! GCC_REAL_H */
diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='#*' --exclude='*~' pristine/gcc/c-common.c wcoercion/gcc/c-common.c --- pristine/gcc/c-common.c 2006-07-01 13:37:45.000000000 +0100 +++ wcoercion/gcc/c-common.c 2006-07-09 20:47:07.000000000 +0100 @@ -1067,6 +1067,109 @@ vector_types_convertible_p (tree t1, tre == INTEGRAL_TYPE_P (TREE_TYPE (t2))); } +/* Warns if the conversion of EXPR to TYPE may alter a value. + This function is called from convert_and_check(). */ + +void +coercion_warning (tree type, tree expr) +{ + bool give_warning = false; + + unsigned int formal_prec = TYPE_PRECISION (type); + + if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST) + { + /* Warn for real constant that is not an exact integer coerced + to integer type. */ + if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE + && TREE_CODE (type) == INTEGER_TYPE + && !real_isinteger (TREE_REAL_CST (expr), TYPE_MODE (TREE_TYPE (expr)))) + give_warning = true; + + /* Warn for an integer constant that does not fit into integer + type. However, warnings for negative constants coerced to + unsigned types are detected by unsigned_conversion_warning. */ + else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE + && TREE_CODE (type) == INTEGER_TYPE + && !int_fits_type_p (expr, type) + && TYPE_UNSIGNED (TREE_TYPE (expr)) == TYPE_UNSIGNED (type)) + give_warning = true; + + else if (TREE_CODE (type) == REAL_TYPE) + { + if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE) + { + REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr); + if (!exact_real_truncate (TYPE_MODE (type), &a)) + give_warning = true; + } + else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE + && formal_prec < TYPE_PRECISION (TREE_TYPE (expr))) + { + REAL_VALUE_TYPE a = TREE_REAL_CST (expr); + if (!exact_real_truncate (TYPE_MODE (type), &a)) + give_warning = true; + } + } + + if (give_warning) + warning (OPT_Wcoercion, + "coercion as %qT alters %qT constant value", + type, TREE_TYPE (expr)); + } + else /* 'expr' is not a constant. */ + { + /* Warn for real types coerced to integer types. */ + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE) + give_warning = true; + + /* Warn for integer types coerced to real types if and only if + all the range of values of the integer type cannot be + represented by the real type. */ + else if (TREE_CODE (type) == REAL_TYPE + && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE) + { + tree type_low_bound = TYPE_MIN_VALUE (TREE_TYPE (expr)); + tree type_high_bound = TYPE_MAX_VALUE (TREE_TYPE (expr)); + 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)) + give_warning = true; + } + + /* Warn for real types coerced to smaller real types. */ + else if (TREE_CODE (type) == REAL_TYPE + && TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE + && formal_prec < TYPE_PRECISION (TREE_TYPE (expr))) + give_warning = true; + + + else if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE) + { + /* Warn for integer types coerced 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 coerced 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 (give_warning) + warning (OPT_Wcoercion, + "coercion to %qT from %qT may alter its value", + type, TREE_TYPE (expr)); + } +} + /* Convert EXPR to TYPE, warning about conversion problems with constants. Invoke this function on every expression that is converted implicitly, i.e. because of language rules and not because of an explicit cast. */ @@ -1074,7 +1177,12 @@ vector_types_convertible_p (tree t1, tre tree convert_and_check (tree type, tree expr) { - tree t = convert (type, expr); + tree t; + + if (warn_coercion) + coercion_warning (type, expr); + + t = convert (type, expr); if (TREE_CODE (t) == INTEGER_CST) { if (TREE_OVERFLOW (t)) diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='#*' --exclude='*~' pristine/gcc/c-common.h wcoercion/gcc/c-common.h --- pristine/gcc/c-common.h 2006-06-21 23:32:46.000000000 +0100 +++ wcoercion/gcc/c-common.h 2006-07-09 20:32:36.000000000 +0100 @@ -656,6 +656,7 @@ struct varray_head_tag; extern void constant_expression_warning (tree); extern void strict_aliasing_warning(tree, tree, tree); extern void empty_body_warning (tree, tree); +extern void coercion_warning (tree type, tree expr); extern tree convert_and_check (tree, tree); extern void overflow_warning (tree); extern bool c_determine_visibility (tree); diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='#*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/Wcoercion-assignments.c wcoercion/gcc/testsuite/gcc.dg/Wcoercion-assignments.c --- pristine/gcc/testsuite/gcc.dg/Wcoercion-assignments.c 1970-01-01 01:00:00.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/Wcoercion-assignments.c 2006-07-09 20:32:36.000000000 +0100 @@ -0,0 +1,87 @@ +/* Test for diagnostics for Wcoercion in assignments. + Origin: Manuel Lopez-Ibanez <[EMAIL PROTECTED]> */ + +/* { dg-do compile } +/* { dg-options "-fsigned-char -std=c99 -Wcoercion" } */ + +#include <limits.h> +#include <float.h> + +# define M_PI 3.14159265358979323846 /* pi */ + +float vfloat; +double vdouble; +long double vlongdouble; + +char vchar; +short int vshortint; +int vint; +long vlongint; +long long vlonglong; + +void h(void) +{ + unsigned int ui = 3; + int si = 3; + float f = 3; + double d = 3; + + vint = 3.1f; /* { dg-warning "coercion" } */ + vint = 3.1; /* { dg-warning "coercion" } */ + vfloat = INT_MAX; /* { dg-warning "coercion" } */ + vfloat = DBL_MIN; /* { dg-warning "coercion" } */ + vfloat = M_PI; /* { dg-warning "coercion" } */ + vfloat = 3.1; /* { dg-warning "coercion" } */ + vint = d; /* { dg-warning "coercion" } */ + vfloat = d; /* { dg-warning "coercion" } */ + vfloat = si; /* { dg-warning "coercion" } */ + vfloat = ui; /* { dg-warning "coercion" } */ + vfloat = 16777217; /* { dg-warning "coercion" } */ + + /* No warning */ + vint = 3; + vint = 3.0f; + vint = 3.0; + vint = 16777217.0f; + vfloat = 3U; + vfloat = 3; + vfloat = INT_MIN; + vdouble = UINT_MAX; + vdouble = ui; + vfloat = 3.0; + vfloat = 3.1f; + vfloat = 0.25; + vfloat = f; + vdouble = d; + vdouble = f; + vdouble = 16777217; + +} + + +unsigned char vuc; +unsigned int vui; + +void h2(void) +{ + unsigned int ui = 3; + int si = 3; + unsigned char uc = 3; + signed char sc = 3; + + vint = ui;/* { dg-warning "coercion" } */ + vui = si; /* { dg-warning "coercion" } */ + vui = sc; /* { dg-warning "coercion" } */ + vui = -1; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + vui = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + vuc = '\xa0'; /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + + /* no warning */ + vint = uc; + vui = uc; + vui = 'A'; + vuc = 'A'; + vint = 'A'; + vchar = 'A'; + vchar = '\xa0'; +} diff -pEbaur --unidirectional-new-file --exclude='*svn*' --exclude='#*' --exclude='*~' pristine/gcc/testsuite/gcc.dg/Wcoercion-calls.c wcoercion/gcc/testsuite/gcc.dg/Wcoercion-calls.c --- pristine/gcc/testsuite/gcc.dg/Wcoercion-calls.c 1970-01-01 01:00:00.000000000 +0100 +++ wcoercion/gcc/testsuite/gcc.dg/Wcoercion-calls.c 2006-07-09 20:32:36.000000000 +0100 @@ -0,0 +1,87 @@ +/* Test for diagnostics for Wcoercion when passing arguments. + Origin: Manuel Lopez-Ibanez <[EMAIL PROTECTED]> */ + +/* { dg-do compile } +/* { dg-options "-fsigned-char -std=c99 -Wcoercion" } */ + +#include <limits.h> +#include <float.h> + +# define M_PI 3.14159265358979323846 /* pi */ + +void fchar(char x); +void ffloat(float x); +void fdouble(double x); +void flongdouble(long double x); + +void fshortint(short int x); +void fint(int x); +void flongint(long int x); +void flonglong(long long x); + +void h(void) +{ + unsigned int ui = 3; + int si = 3; + float f = 3; + double d = 3; + + fint(3.1f); /* { dg-warning "coercion" } */ + fint(3.1); /* { dg-warning "coercion" } */ + ffloat(INT_MAX); /* { dg-warning "coercion" } */ + ffloat(DBL_MIN); /* { dg-warning "coercion" } */ + ffloat(M_PI); /* { dg-warning "coercion" } */ + ffloat(3.1); /* { dg-warning "coercion" } */ + fint(d); /* { dg-warning "coercion" } */ + ffloat(d); /* { dg-warning "coercion" } */ + ffloat(si); /* { dg-warning "coercion" } */ + ffloat(ui); /* { dg-warning "coercion" } */ + ffloat(16777217); /* { dg-warning "coercion" } */ + + + fint(3); + fint(3.0f); + fint(3.0); + fint(16777217.0f); + ffloat(3U); + ffloat(3); + ffloat(INT_MIN); + fdouble(UINT_MAX); + fdouble(ui); + ffloat(3.0); + ffloat(3.1f); + ffloat(0.25); + ffloat(f); + fdouble(d); + fdouble(f); + fdouble(16777217); + +} + + +void fuc(unsigned char uc); +void fui(unsigned int ui); + +void h2(void) +{ + unsigned int ui = 3; + int si = 3; + unsigned char uc = 3; + signed char sc = 3; + + fint(ui); /* { dg-warning "coercion" } */ + fui(si);/* { dg-warning "coercion" } */ + fui(sc); /* { dg-warning "coercion" } */ + fui(-1); /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + fui('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + fuc('\xa0'); /* { dg-warning "negative integer implicitly converted to unsigned type" } */ + + + fint(uc); + fui(uc); + fui('A'); + fuc('A'); + fint('A'); + fchar('A'); + fchar('\xa0'); +}